diff --git a/src/storage/plugins/CurlStorage.cxx b/src/storage/plugins/CurlStorage.cxx
index 07f25c441..98f6de247 100644
--- a/src/storage/plugins/CurlStorage.cxx
+++ b/src/storage/plugins/CurlStorage.cxx
@@ -456,11 +456,11 @@ CurlStorage::GetInfo(const char *uri_utf8, gcc_unused bool follow)
 }
 
 gcc_pure
-static const char *
+static std::string_view
 UriPathOrSlash(const char *uri) noexcept
 {
-	const char *path = uri_get_path(uri);
-	if (path == nullptr)
+	auto path = uri_get_path(uri);
+	if (path.data() == nullptr)
 		path = "/";
 	return path;
 }
@@ -495,7 +495,7 @@ private:
 	 */
 	gcc_pure
 	StringView HrefToEscapedName(const char *href) const noexcept {
-		const char *path = uri_get_path(href);
+		StringView path = uri_get_path(href);
 		if (path == nullptr)
 			return nullptr;
 
@@ -504,16 +504,16 @@ private:
 		   case in hex digits in escaped characters; TODO:
 		   implement properly */
 		path = StringAfterPrefixIgnoreCase(path, base_path.c_str());
-		if (path == nullptr || *path == 0)
+		if (path == nullptr || path.empty())
 			return nullptr;
 
-		const char *slash = strchr(path, '/');
+		const char *slash = path.Find('/');
 		if (slash == nullptr)
 			/* regular file */
 			return path;
-		else if (slash[1] == 0)
+		else if (slash == &path.back())
 			/* trailing slash: collection; strip the slash */
-			return {path, slash};
+			return {path.data, slash};
 		else
 			/* strange, better ignore it */
 			return nullptr;
diff --git a/src/util/UriExtract.cxx b/src/util/UriExtract.cxx
index 4e45040ce..c78bd9e8f 100644
--- a/src/util/UriExtract.cxx
+++ b/src/util/UriExtract.cxx
@@ -48,12 +48,12 @@ IsValidSchemeChar(char ch)
 
 gcc_pure
 static bool
-IsValidScheme(StringView p) noexcept
+IsValidScheme(std::string_view p) noexcept
 {
 	if (p.empty() || !IsValidSchemeStart(p.front()))
 		return false;
 
-	for (size_t i = 1; i < p.size; ++i)
+	for (size_t i = 1; i < p.size(); ++i)
 		if (!IsValidSchemeChar(p[i]))
 			return false;
 
@@ -65,18 +65,23 @@ IsValidScheme(StringView p) noexcept
  * double slash).
  */
 gcc_pure
-static const char *
-uri_after_scheme(const char *uri) noexcept
+static std::string_view
+uri_after_scheme(std::string_view uri) noexcept
 {
-	if (uri[0] == '/' && uri[1] == '/' && uri[2] != '/')
-		return uri + 2;
+	if (uri.length() > 2 &&
+	    uri[0] == '/' && uri[1] == '/' && uri[2] != '/')
+		return uri.substr(2);
 
-	const char *colon = strchr(uri, ':');
-	return colon != nullptr &&
-		IsValidScheme({uri, colon}) &&
-		colon[1] == '/' && colon[2] == '/'
-		? colon + 3
-		: nullptr;
+	auto colon = uri.find(':');
+	if (colon == std::string_view::npos ||
+	    !IsValidScheme(uri.substr(0, colon)))
+		return {};
+
+	uri = uri.substr(colon + 1);
+	if (uri[0] != '/' || uri[1] != '/')
+		return {};
+
+	return uri.substr(2);
 }
 
 bool
@@ -101,12 +106,16 @@ uri_is_relative_path(const char *uri) noexcept
 	return !uri_has_scheme(uri) && *uri != '/';
 }
 
-const char *
-uri_get_path(const char *uri) noexcept
+std::string_view
+uri_get_path(std::string_view uri) noexcept
 {
-	const char *ap = uri_after_scheme(uri);
-	if (ap != nullptr)
-		return strchr(ap, '/');
+	auto ap = uri_after_scheme(uri);
+	if (ap.data() != nullptr) {
+		auto slash = ap.find('/');
+		if (slash == std::string_view::npos)
+			return {};
+		return ap.substr(slash);
+	}
 
 	return uri;
 }
diff --git a/src/util/UriExtract.hxx b/src/util/UriExtract.hxx
index a47cf2cd0..05e288b30 100644
--- a/src/util/UriExtract.hxx
+++ b/src/util/UriExtract.hxx
@@ -57,9 +57,9 @@ uri_is_relative_path(const char *uri) noexcept;
  * Returns the URI path (including the query string) or nullptr if the
  * given URI has no path.
  */
-gcc_pure gcc_nonnull_all
-const char *
-uri_get_path(const char *uri) noexcept;
+gcc_pure
+std::string_view
+uri_get_path(std::string_view uri) noexcept;
 
 gcc_pure
 const char *
diff --git a/src/util/UriRelative.cxx b/src/util/UriRelative.cxx
index 619afa812..507861a46 100644
--- a/src/util/UriRelative.cxx
+++ b/src/util/UriRelative.cxx
@@ -163,8 +163,8 @@ uri_apply_relative(const std::string &relative_uri,
 		return base_uri.substr(0, i) + relative_uri;
 	}
 
-	const char *_base_path = uri_get_path(base_uri.c_str());
-	if (_base_path == nullptr) {
+	const auto _base_path = uri_get_path(base_uri);
+	if (_base_path.data() == nullptr) {
 		std::string result(base_uri);
 		if (relative_uri.front() != '/')
 			result.push_back('/');
@@ -183,7 +183,7 @@ uri_apply_relative(const std::string &relative_uri,
 	if (!ConsumeSpecial(relative_path, base_path))
 		return {};
 
-	std::string result(base_uri.c_str(), _base_path);
+	std::string result(base_uri.data(), _base_path.data());
 	result.append(base_path.data, base_path.size);
 	result.append(relative_path);
 	return result;