title: Percent-encoded slash ("/") is decoded before the request dispatch
body: <p>I have an URL containing several slash characters (<code>/</code>) as a part of the filename (not the URL). But when I send http request, the percent-encoded <code>%2F</code> is translated to <code>/</code> before the request dispatch, therefore generating a wrong URL.</p>
  
  <p><strong>How can I make a literal http request ignoring the percent-encoded values in PowerShell?</strong></p>
  
  <p>Actual URL used (<a href="http://commondatastorage.googleapis.com/chromium-browser-continuous/index.html?prefix=Win_x64/292817/" rel="noreferrer">Chromium browser</a>):</p>
  
  <p><a href="https://www.googleapis.com/download/storage/v1/b/chromium-browser-continuous/o/Win_x64%2F292817%2Fchrome-win32.zip?generation=1409504089694000&amp;alt=media" rel="noreferrer"><code>https://www.googleapis.com/download/storage/v1/b/chromium-browser-continuous/o/Win_x64%2F292817%2Fchrome-win32.zip?generation=1409504089694000&amp;alt=media</code></a></p>
  
  <hr>
  
  <p>I have tried <a href="http://technet.microsoft.com/en-us/library/hh849901.aspx" rel="noreferrer"><code>Invoke-WebRequest</code></a> cmdlet:</p>
  
  <pre><code>Invoke-WebRequest -Uri $ChromeUrl -OutFile $FilePath -Verbose
  
  VERBOSE: GET https://www.googleapis.com/download/storage/v1/b/chromium-browser-continuous/o/Win_x64/292817/chrome-win32.zip?generation=1409504089694000&amp;alt=media with 0-byte payload1`
  </code></pre>
  
  <p>Not found error.</p>
  
  <p>Also tried <code>WebClient</code>'s <a href="http://msdn.microsoft.com/en-us/library/ms144194(v=vs.110).aspx" rel="noreferrer"><code>DownloadFile</code></a> method:</p>
  
  <pre><code>$wclient = New-Object System.Net.WebClient
  $wclient.DownloadFile($ChromeUrl, $FilePath)
  </code></pre>
  
  <p>Returns 404 due to wrong URL requested again.</p>
  
  <hr>
  
  <h2>Workaround 1 (successful)</h2>
  
  <p>Reflection-based workarounds provided by <a href="https://stackoverflow.com/users/3905079/briantist"><em>briantist</em></a> and <a href="https://stackoverflow.com/users/1473915/tanuj-mathur"><em>Tanuj Mathur</em></a> are both working great. The latter one:</p>
  
  <pre><code>$UrlFixSrc = @" 
  using System;
  using System.Reflection;
  
  public static class URLFix 
  { 
      public static void ForceCanonicalPathAndQuery(Uri uri)
      {
          string paq = uri.PathAndQuery;
          FieldInfo flagsFieldInfo = typeof(Uri).GetField("m_Flags", BindingFlags.Instance | BindingFlags.NonPublic);
          ulong flags = (ulong) flagsFieldInfo.GetValue(uri);
          flags &amp;= ~((ulong) 0x30);
          flagsFieldInfo.SetValue(uri, flags);
      }
  } 
  "@ 
  
  Add-Type -TypeDefinition $UrlFixSrc-Language CSharp
  [URLFix]::ForceCanonicalPathAndQuery([URI]$ChromeUrl)
  
  Invoke-WebRequest -Uri $ChromeUrl -OutFile $FilePath -Verbose
  
  VERBOSE: GET https://www.googleapis.com/download/storage/v1/b/chromium-browser-continuous/o/Win_x64%2F292640%2Fchrome-win32.zip?generation=1409351584147000&amp;alt=media
  </code></pre>
  
  <h2>Workaround 2 (successful)</h2>
  
  <p>More clean solution (offered by <a href="https://stackoverflow.com/users/1473915/tanuj-mathur"><em>Tanuj Mathur</em></a>), but requires access to system files, is by adding a config file <code>%SystemRoot%\System32\WindowsPowerShell\v1.0\powershell.exe.config</code> with the following content:</p>
  
  <pre><code>&lt;?xml version="1.0" encoding="utf-8" ?&gt; 
   &lt;configuration&gt; 
     &lt;uri&gt;
       &lt;schemeSettings&gt;
        &lt;add name="http" genericUriParserOptions="DontUnescapePathDotsAndSlashes" /&gt;
        &lt;add name="https" genericUriParserOptions="DontUnescapePathDotsAndSlashes" /&gt;
       &lt;/schemeSettings&gt;
     &lt;/uri&gt;
  &lt;/configuration&gt;
  </code></pre>
  
  <p>Corresponding modifications has to be done in <code>powerhsell_ise.exe.config</code> for it to work in ISE.</p>
  
  <h2>Workaround 3 (failed)</h2>
  
  <p>I thought its a <a href="http://msdn.microsoft.com/en-us/library/vstudio/system.uri(v=vs.100).aspx" rel="noreferrer"><code>System.URI</code></a> class constructor problem that is called upon implicit casting, which translates the escaped values. Tried an overloaded variant <a href="http://msdn.microsoft.com/en-us/library/vstudio/9zh9wcb3(v=vs.100).aspx" rel="noreferrer"><code>Uri ([String]uriString, [Boolean]dontEscape)</code></a>. But there was no difference. The same outcome with or without <code>dontEscape</code> argument.</p>
  
  <pre><code>$uri = new-object System.Uri($ChromeUrl, $true)
  $uri | Format-List OriginalString, AbsoluteUri
  
    OriginalString : https://www.googleapis.com/download/storage/v1/b/chromium-browser-continuous/o/Win_x64%2F292817%2Fchrome-win32.zip?generation=1409504089694000&amp;alt=media
    AbsoluteUri    : https://www.googleapis.com/download/storage/v1/b/chromium-browser-continuous/o/Win_x64/292817/chrome-win32.zip?generation=1409504089694000&amp;alt=media
  </code></pre>
  
  <hr>
  
  <h2>Workaround 4 (failed)</h2>
  
  <p>Also tried to fool URI parser by replacing percent character with its percent-encoded value <code>%25</code>. But then it ignored everything completely.</p>
  
  <pre><code>Invoke-WebRequest -Uri $ChromeUrl.Replace('%', '%25') -OutFile $DownloadPath -Verbose
  
  VERBOSE: GET https://www.googleapis.com/download/storage/v1/b/chromium-browser-continuous/o/Win_x64%252F292817%252Fchrome-win32.zip?generation=1409504089694000&amp;alt=media with 0-byte pa yload
  </code></pre>
  
  <hr>
  
  <h2>Workaround 5 (not implemented)</h2>
  
  <p>The only way I found that requests URL properly is through Internet Explorer instance.</p>
  
  <pre><code>$ie = New-Object -ComObject InternetExplorer.Application                
  $ie.Visible = $true
  $ie.Silent = $false
  $ie.Navigate2($ChromeUrl)
  </code></pre>
  
  <p>But then I don't know how to automate the 'Saves as' button click and save it to desired path. Also, even if implemented, I don't feel like this is a good solution. What happens when IE is already running or uninstalled from the system?</p>