WinHttp.WinHttpRequest 添加到内容类型

WinHttp.WinHttpRequest adding to the content-type

我正在尝试使用 vba WinHttp.WinHttpRequest 向 kigo 的 api 发出请求, 我能够发送请求,但 WinHttpRequest 更改了内容类型添加 Charset=UTF-8 发送请求的时候,那个kigo的api returns 415 error.

我这样设置内容类型

web_Http.SetRequestHeader "Content-Type", "application/json"

但是当我在 Wireshark 中查看请求时,内容类型是这样的

Content-Type: application/json; Charset=UTF-8

有什么想法吗?

我发现 this,这与我的问题类似,但我不明白解决方案。

我也 运行 遇到了这个问题。它似乎仅限于 WinHttp.WinHttpRequest COM 接口。有几个不同的选项可以解决这个问题。

经过一番挖掘,我从一位微软员工那里找到了 this post。解释的很清楚,建议用二进制数组发送。

If you are POSTing a string using the WinHttpRequest object, you cannot override how it encodes the string for transmission. The WinHttpRequest object will always convert the Unicode string to UTF-8.

However, note that a Unicode string that contains only 7-bit LATIN-1/ISO-8859-1 characters will remain unchanged when encoded as UTF-8 ;-) In such cases, the WinHttpRequest object does not append a "Charset=UTF-8" attribute to your Content-Type header. (And I would think that the server would assume that the POST data is ISO-8859-1.)

So, if the XML text data that you are POSTing contains LATIN-1 alphanumeric or punctuation character codes (each less than decimal 128), then all you should have to do is specify the "ISO-8859-1" charset in your Content-Type header:

WinHttpReq.SetRequestHeader "Content-Type", "application/xml;Charset=ISO-8859-1"

However, if your POST data contains 8-bit characters, then you cannot supply the data as a string to the Send method. In order to avoid the UTF-8 conversion, your application must convert the string into a byte array, and supply that instead. The WinHttpRequest object will not attempt any data conversion on a byte array.

Regards,

Stephen Sulzer

Microsoft Corporation


除了发送二进制数组外,第二种选择是切换到 Msxml2.XMLHTTP or Msxml2.ServerXMLHTTP. Neither of these mangle the Content-Type header。幸运的是,在创建 WinHttp.WinHttpRequest 时,Microsoft 有意使用 Msxml2.XMLHTTP 作为界面模板。所以,转换代码是相当简单的。

此外,Msxml2.ServerXMLHTTP COM 接口 uses WinHTTP internally。因此,虽然您无法访问 WinHttp.WinHttpRequest 独有的某些功能,但两者都使用相同的后端。


第三个选项是使用ADODB.Stream. It allows you to work with an IStream, which isn't something you can normally do from VBA. The sample code below is based on the answer on the question "How to create BinaryArray in VbScript?"

' Create a Binary Stream
Set objStreamBinary = CreateObject("ADODB.Stream")  
objStreamBinary.Type = 1
objStreamBinary.Open  

' Create a Text Stream
Set objStreamText = CreateObject("ADODB.Stream")  
objStreamText.Type = 2
objStreamText.Open
' Copy the POST data to the Text Stream
objStreamText.WriteText strRequest  
objStreamText.Position = 2
' Copy the Text Stream Contents to the Binary Stream
objStreamText.CopyTo objStreamBinary
objStreamText.Close  

' Read the contents of the Binary Stream
' and send it to the WinHttpRequest object
web_Http.Send objStreamBinary.Read(-1)