How to prevent Invoke-RestMethod from un-escaping forward slashes

While working on RabbitMQTools module I came across a problem with un-escaping forward slashes in Urls by Invoke-RestMethod cmdlet. The default Virtual Host on RabbitMQ is called "/" and when invoking Api methods it must be encoded with %2f:

As it turns out, this will only work if PowerShell is using .Net Framework 4.5 or newer. All the previous versions will un-escape the forward slash changing Url to:

which is not recognised by the server and results with exception. The reason for this behaviour is historical and related to security [1]. Microsoft decided to un-escape forward slash and dot characters to prevent malicious attacks. As this was valid years ago, nowadays with the progress of REST APIs, sometimes it is required to use forward slash in the Url.

If you need to support forward slashes in Url when using .NET Framework 4.0, then there is a way to prevent un-escaping by modifying internal flag on UriParser class. Unfortunately, because the field is internal, it has to be done using reflection:

What the code does is checking whether UnEscapeDotsAndSlashes flag is set on the UriParser class and removes it if necessary . This will stop the un-escaping of Uri allowing Invoke-RestMethod cmdlet to call the API with proper Url.

To check whether UnEscapeDotsAndSlashes flag is on run the following code:

The caveat

Unfortunately, there is caveat with this approach. As it will modify setting for the whole Application Domain it means that once executed in PowerShell session it will apply to any consecutive operations on Uri, even those run outside of your module. If you decide to use this approach, please switch it on only when necessary and revert to previous setting once you are done. It is also a good idea to state clearly the fact that the hack is in use.

To see an example of how it is used in RabbitMQTools module, check AddRabbitMQExchange cmdlet.

Thanks

I’d like to thank stimpy77 who authored the C# solution[2] on StackOverflow.

Disclaimer

The propsed solution is invasive and modifies default behaviour of .NET Framework. You may used it at your own risk. The author doesn’t take any responsibility for any effect which are result of using that approach.

References

1. Erroneous URI parsing for encoded, reserved characters, according to RFC 3986 on Microsoft Connect

2. The discussion on StackOverflow which shows the solution in C#.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s