Sometimes you want to construct a URI that has an escaped forward slash. For example, the RabbitMQ Management API requires that you encode the default rabbit VirtualHost ‘/’ as ‘%2f’. Here is the URL to get the details of a queue:
http://192.168.1.4:55672/api/queues/%2f/EasyNetQ_Default_Error_Queue
But if I try use WebRequest or WebClient the ‘%2f’ is un-escaped to a ‘/’, so the URL becomes:
http://192.168.1.4:55672/api/queues///EasyNetQ_Default_Error_Queue
And I get a 404 not found back :(
Both WebRequest and WebClient use System.Uri internally. It’s easy to demonstrate this behaviour with the following code:
var uri = new Uri(url);
Console.Out.WriteLine("uri = {0}", uri.PathAndQuery);
// outputs /api/queues///EasyNetQ_Default_Error_Queue
A bit of digging in the System.Uri code thanks to the excellent ReSharper 6.0, and help from this Stack Overflow question, shows that it’s possible to reset some flags and stop this behaviour. Here’s my LeaveDotsAndSlashesEscaped method (it’s .NET 4.0 specific):
private void LeaveDotsAndSlashesEscaped()
{
var getSyntaxMethod =
typeof (UriParser).GetMethod("GetSyntax", BindingFlags.Static | BindingFlags.NonPublic);
if (getSyntaxMethod == null)
{
throw new MissingMethodException("UriParser", "GetSyntax");
}
var uriParser = getSyntaxMethod.Invoke(null, new object[] { "http" });
var setUpdatableFlagsMethod =
uriParser.GetType().GetMethod("SetUpdatableFlags", BindingFlags.Instance | BindingFlags.NonPublic);
if (setUpdatableFlagsMethod == null)
{
throw new MissingMethodException("UriParser", "SetUpdatableFlags");
}
setUpdatableFlagsMethod.Invoke(uriParser, new object[] {0});
}
The usual caveats of poking into system assemblies with reflection apply. Don’t expect this to work with any other version of .NET than 4.0.
LeaveDotsAndSlashesEscaped();
const string url = "http://192.168.1.4:55672/api/queues/%2f/EasyNetQ_Default_Error_Queue";
var uri = new Uri(url);
Console.Out.WriteLine("uri = {0}", uri.PathAndQuery);
// outputs /api/queues/%2f/EasyNetQ_Default_Error_Queue
<uri>
<schemeSettings>
<add name="http" genericUriParserOptions="DontUnescapePathDotsAndSlashes" />
</schemeSettings>
</uri>
5 comments:
thanks man !!!
Thanks, this post did not solve my problem but it put me in the right direction. See my post on stackoverlfow: http://stackoverflow.com/questions/16170442/wcf-uritemplate-urlencode
Wow... that's so dangerous and so hacky.
I've been working on this bug for 2 days.
Thanks. You've made my day!
Note that this needs tweaked a bit to have an impact on https URIs. You need to change the parameter to
getSyntaxMethod.Invoke() from "http" to "https"
Post a Comment