在请求分发之前对百分比编码的斜杠(“ /”)进行解码 [英] Percent-encoded slash ("/") is decoded before the request dispatch

查看:98
本文介绍了在请求分发之前对百分比编码的斜杠(“ /”)进行解码的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个URL,其中包含几个斜杠字符( / )作为文件名的一部分(而不是URL)。但是当我发送http请求时,在请求分派之前,将百分比编码的%2F 转换为 / ,因此生成了错误的URL。

I have an URL containing several slash characters (/) as a part of the filename (not the URL). But when I send http request, the percent-encoded %2F is translated to / before the request dispatch, therefore generating a wrong URL.

如何在不使用PowerShell的百分比编码的情况下发出字面的http请求?

使用的实际网址(铬浏览器):

https://www.googleapis.com/download/storage/v1/ b / chromium-browser-continuous / o / Win_x64%2F292817%2Fchrome-win32.zip?generation = 1409504089694000& alt = media

我已经尝试过 Invoke-WebRequ est cmdlet:

I have tried Invoke-WebRequest cmdlet:

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&alt=media with 0-byte payload1`

未找到错误。

还尝试了 WebClient DownloadFile 方法:

Also tried WebClient's DownloadFile method:

$wclient = New-Object System.Net.WebClient
$wclient.DownloadFile($ChromeUrl, $FilePath)

由于再次请求的URL错误而返回404。

Returns 404 due to wrong URL requested again.

briantist Tanuj Mathur 都运转良好。后者:

Reflection-based workarounds provided by briantist and Tanuj Mathur are both working great. The latter one:

$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 &= ~((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&alt=media



Workaro und 2(成功)



更干净的解决方案(由 提供> Tanuj Mathur ),但需要访问系统文件,方法是添加配置文件%SystemRoot%\System32\WindowsPowerShell\v1.0\powershell。 exe.config 并包含以下内容:

Workaround 2 (successful)

More clean solution (offered by Tanuj Mathur), but requires access to system files, is by adding a config file %SystemRoot%\System32\WindowsPowerShell\v1.0\powershell.exe.config with the following content:

<?xml version="1.0" encoding="utf-8" ?> 
 <configuration> 
   <uri>
     <schemeSettings>
      <add name="http" genericUriParserOptions="DontUnescapePathDotsAndSlashes" />
      <add name="https" genericUriParserOptions="DontUnescapePathDotsAndSlashes" />
     </schemeSettings>
   </uri>
</configuration>

必须在 powerhsell_ise.exe.config 使其可以在ISE中工作。

Corresponding modifications has to be done in powerhsell_ise.exe.config for it to work in ISE.

我认为它是 系统。 URI 类构造函数问题,在隐式强制转换时会调用,它会转换转义的值。尝试了重载的变体 Uri([String] uriString,[Boolean] dontEscape) 。但是没有区别。有或没有 dontEscape 参数的结果相同。

I thought its a System.URI class constructor problem that is called upon implicit casting, which translates the escaped values. Tried an overloaded variant Uri ([String]uriString, [Boolean]dontEscape). But there was no difference. The same outcome with or without dontEscape argument.

$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&alt=media
  AbsoluteUri    : https://www.googleapis.com/download/storage/v1/b/chromium-browser-continuous/o/Win_x64/292817/chrome-win32.zip?generation=1409504089694000&alt=media






解决方法4 (失败)



还尝试通过用百分比编码值%25 替换百分比字符来欺骗URI解析器。但是随后它完全忽略了所有内容。


Workaround 4 (failed)

Also tried to fool URI parser by replacing percent character with its percent-encoded value %25. But then it ignored everything completely.

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&alt=media with 0-byte pa yload






解决方法5(未实现)



我发现正确请求URL的唯一方法是通过Internet Explorer实例。


Workaround 5 (not implemented)

The only way I found that requests URL properly is through Internet Explorer instance.

$ie = New-Object -ComObject InternetExplorer.Application                
$ie.Visible = $true
$ie.Silent = $false
$ie.Navigate2($ChromeUrl)

但是我不知道如何自动化单击另存为按钮,然后将其保存到所需的路径。另外,即使实施,我也不认为这是一个很好的解决方案。当IE已经在运行或从系统中卸载时会发生什么?

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?

推荐答案

我最近一直在处理您的代码几个小时,这很笨拙。在Powershell ISE中运行时,给定的代码及其变体全部通过,但在Powershell控制台上失败。
问题本身似乎是此处连接Microsoft。

I've been playing around with your code for the last few hours, and it's a doozy. The given code and it's variants all pass when run in the Powershell ISE, but fail on the Powershell console. The issue itself seems to be the one documented on Microsoft Connect here.

有趣的是,根据用户 Glenn Block的 答案问题,此错误已在.NET Framework 4.5中修复。
您可以通过运行命令 $ PSVersionTable 来检查Powershell正在使用的.NET框架的版本。只要 CLRVersion 值的格式为4.0.30319.x,其中x> 1700,那么您正在运行框架的v4.5。

Interestingly, as per user Glenn Block's answer on a related issue, this bug was fixed in .NET Framework 4.5. You can check the version of the .NET framework being used by your Powershell by running the command $PSVersionTable. As long as the CLRVersion value is of the form 4.0.30319.x, where x > 1700, then you are running v4.5 of the framework.

我在计算机上的.NET Framework 4.5上运行了Powershell v4.0,因此可以解释为什么Powershell ISE可以显示正确的行为,但是我无法弄清楚Powershell控制台为什么会这样做不。我验证了两者加载的.NET程序集,它们似乎是相同的。

I'm running Powershell v4.0 on .NET framework 4.5 on my machine, so that explains why Powershell ISE shows the correct behaviour, but I was not able to figure out why Powershell console does not. I verified the .NET assemblies loaded by both, and they seem to be the same.

就目前情况而言,我们有两个选择。
一种方法是使用反射并在.Net类上设置一个私有字段以防止此行为(如此答案)。
另一种方法是使用Microsoft Connect问题中列出的解决方法。这涉及以下步骤:

As things stand, we have two options. One is to use reflection and set a private field on the .Net class to prevent this behaviour (as outlined in this answer). The other is to use the workaround listed in the Microsoft Connect issue. This involves the following steps:


  1. 转到Powershell安装文件夹(这是 C:\Windows\ \System32\WindowsPowerShell\v1.0\ )。此文件夹中应包含文件 powershell.exe

  2. 在此文件夹中创建一个新的文本文件,并将其命名为 powershell.exe.config

  3. 在文本编辑器中打开此文件,并将以下文本粘贴到其中:

    <?xml version = 1.0 encoding = utf-8吗?>
    < configuration>
    < uri>
    < schemeSettings>
    <添加名称= http genericUriParserOptions = DontUnescapePathDotsAndSlashes />
    <添加名称= https genericUriParserOptions = DontUnescapePathDotsAndSlashes />
    < / schemeSettings>
    < / uri>
    < / configuration>

  1. Go to your Powershell install folder (this was "C:\Windows\System32\WindowsPowerShell\v1.0\" on my machine). This folder should have the file powershell.exe in it.
  2. Create a new text file in this folder, and name it powershell.exe.config
  3. Open this file in a text editor, and paste the following text into it: <?xml version="1.0" encoding="utf-8" ?> <configuration> <uri> <schemeSettings> <add name="http" genericUriParserOptions="DontUnescapePathDotsAndSlashes" /> <add name="https" genericUriParserOptions="DontUnescapePathDotsAndSlashes" /> </schemeSettings> </uri> </configuration>

保存此文件。关闭所有正在运行的Powershell实例。

Save this file. Close ALL running instances of Powershell.

这篇关于在请求分发之前对百分比编码的斜杠(“ /”)进行解码的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆