Small issue on StringExtensions.UrlDecode

I have a client that uses % in their URLs. This is possible and normally this implies a hex number in the url. However… it is possible To have a URL like ttis:

GET https://localhost:46780/puzzel/Legering van ijzer met 14% silicium

In this case, UrlEncoding gives:

Legering%20van%20%C4%B3zer%20met%2014%%20silicium

Which is fine. However, the decoder assumes two digits after the % sign.
Not sure if this is an OK fix, but this seems to do the trick:

public static string UrlDecode(string text)
{
  if (String.IsNullOrEmpty(text)) return null;

  var bytes = new List<byte>();

  var textLength = text.Length;
  for (var i = 0; i < textLength; i++)
  {
    var c = text[i];
    if (c == '+')
    {
      bytes.Add(32);
    }
    else if (c == '%' && text[i + 1] != '%') // test for additional % sign
    {
      var hexNo = Convert.ToByte(text.Substring(i + 1, 2), 16);
      bytes.Add(hexNo);
      i += 2;
    }
    else
    {
      bytes.Add((byte)c);
    }
  }

  byte[] byteArray = bytes.ToArray();
  return Encoding.UTF8.GetString(byteArray, 0, byteArray.Length);
}

If that’s the case they should also be encoding the % so that it results in:

Legering%20van%20%C4%B3zer%20met%2014%25%20silicium

i.e. as encoded with:

encodeURIComponent('Legering van ijzer met 14% silicium')

instead of:

Legering%20van%20%C4%B3zer%20met%2014%%20silicium

They can’t just use special URL encoded chars without encoding them as well.

This is the exact url sent:

https://localhost:25810/puzzle/question/Legering%20van%20%C4%B3zer%20met%2014%25%20silicium

And it gives this:

FormatException: Could not find any recognizable digits.

  • System.ParseNumbers.StringToInt(ReadOnlySpan s, int radix, int flags, ref int currPos)

  • System.Convert.ToByte(string value, int fromBase)

  • ServiceStack.StringExtensions.UrlDecode(string text) in StringExtensions.cs

  • ServiceStack.AppHostBase.ProcessRequest(HttpContext context, Func next) in AppHostBase.NetCore.cs

  • Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context)

System.FormatException: Could not find any recognizable digits.
at System.ParseNumbers.StringToInt(ReadOnlySpan1 s, Int32 radix, Int32 flags, Int32& currPos) at System.Convert.ToByte(String value, Int32 fromBase) at ServiceStack.StringExtensions.UrlDecode(String text) in C:\BuildAgent\work\912418dcce86a188\src\ServiceStack.Text\StringExtensions.cs:line 155 at ServiceStack.AppHostBase.ProcessRequest(HttpContext context, Func1 next) in C:\BuildAgent\work\3481147c480f4a2f\src\ServiceStack\AppHostBase.NetCore.cs:line 264
at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context)

Can you provide the raw HTTP Request?

Better yet. Here’s a small test program that demonstrates the behaviour:
http://www.webfeud.com/wf/HttpRequestTest.zip

It seems that the URL gets mangled as soon as the reuqest is passed to ServiceStack.

1 Like

Cheers, issue was the path is already URL Decoded in .NET Core, resolved in this commit.

Will let you know when this change is on MyGet.

1 Like

Awesome - as always :grinning: :+1:

FYI now available from the latest v5.10.5+ that’s now on MyGet.

Confirmed! Works like a charm.

1 Like