diff --git a/src/PackageUrl.cs b/src/PackageUrl.cs
index ae49a2e..324ed2c 100644
--- a/src/PackageUrl.cs
+++ b/src/PackageUrl.cs
@@ -42,6 +42,11 @@ namespace PackageUrl
[Serializable]
public sealed class PackageURL
{
+ ///
+ /// The url encoding of /.
+ ///
+ private const string EncodedSlash = "%2F";
+
private static readonly Regex s_typePattern = new Regex("^[a-zA-Z][a-zA-Z0-9.+-]+$", RegexOptions.Compiled);
///
@@ -135,7 +140,8 @@ public override string ToString()
purl.Append('/');
if (Namespace != null)
{
- purl.Append(WebUtility.UrlEncode(Namespace));
+ string encodedNamespace = WebUtility.UrlEncode(Namespace).Replace(EncodedSlash, "/");
+ purl.Append(encodedNamespace);
purl.Append('/');
}
if (Name != null)
@@ -238,7 +244,7 @@ private void Parse(string purl)
int i;
for (i = 1; i < firstPartArray.Length - 2; ++i)
{
- @namespace += firstPartArray[i] + ',';
+ @namespace += firstPartArray[i] + '/';
}
@namespace += firstPartArray[i];
diff --git a/tests/TestAssets/test-suite-data.json b/tests/TestAssets/test-suite-data.json
index 6f97708..25fdf13 100644
--- a/tests/TestAssets/test-suite-data.json
+++ b/tests/TestAssets/test-suite-data.json
@@ -47,6 +47,18 @@
"subpath": "googleapis/api/annotations",
"is_invalid": false
},
+ {
+ "description": "valid go purl with version, subpath, and multi-part namespace",
+ "purl": "pkg:GOLANG/github.com/gorilla/context@234fd47e07d1004f0aed9c#api/",
+ "canonical_purl": "pkg:golang/github.com/gorilla/context@234fd47e07d1004f0aed9c#api",
+ "type": "golang",
+ "namespace": "github.com/gorilla",
+ "name": "context",
+ "version": "234fd47e07d1004f0aed9c",
+ "qualifiers": null,
+ "subpath": "api",
+ "is_invalid": false
+ },
{
"description": "bitbucket namespace and name should be lowercased",
"purl": "pkg:bitbucket/birKenfeld/pyGments-main@244fd47e07d1014f0aed9c",