WinHttp.WinHttpRequest adding to the content-type
Asked Answered
Z

1

12

I'm trying to make a request to kigo's api using vba WinHttp.WinHttpRequest, i was able to send a request, but WinHttpRequest changes the content-type adding Charset=UTF-8 when it sends the request, with that kigo's api returns 415 error.

I set the content-type like this

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

but when the i look at the request in Wireshark the content-type is like this

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

Any ideas?

I found this, that is similar to my problem but i dont understand the solution.

Zenaidazenana answered 26/2, 2016 at 1:42 Comment(8)
What charset are they expecting? have you tried specifying it in your Content-Type string?Discretionary
The content-type should be only application/json without anything else, if the content-type have anything beyond application/json i get an error. Yes i tried to specify the Content-Type string. This happens after i setup the request.Zenaidazenana
Try ending your string with a semicolon. Any luck?Discretionary
I tried, no luck. my problem is similar to this one linkZenaidazenana
Hmm.. that's not looking good.. is VBA your only option? Best of luck!Discretionary
Unfortunately yes, thanksZenaidazenana
Have you tried using MSXML2.XMLHTTP instead of winhttp.WinHttpRequest?Spile
@Spile thanks man, i was able to make the request with MSXML2.XMLHTTPZenaidazenana
H
7

I'm running into this problem, as well. It seems to be limited to the WinHttp.WinHttpRequest COM interface. There are a couple of different options to resolve this.

After some digging, I found this post from a Microsoft employee. It gives a clear explanation and recommends sending in a binary array.

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


A second option, other than sending in a binary array, is to switch to Msxml2.XMLHTTP or Msxml2.ServerXMLHTTP. Neither of these mangle the Content-Type header. Luckily, when WinHttp.WinHttpRequest was created, Microsoft intentionally used Msxml2.XMLHTTP as a template for the interface. So, it is fairly trivial to convert the code.

Also, the Msxml2.ServerXMLHTTP COM interface uses WinHTTP internally. So, while you are losing access to some of the features that are exclusive to WinHttp.WinHttpRequest, both use the same backend.


The third option is to use 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)
Hatten answered 19/8, 2016 at 6:8 Comment(4)
Since VBA doesn't have strongly typed arrays - VBA has strongly typed arrays. VBScript is a different language.Dealing
@Dealing thanks. I wasn't aware. I have removed that sentence from my answer.Hatten
Just changing to Set objHTTP = CreateObject("Msxml2.XMLHTTP") worked for me.Whitmore
The issue is that adding ANY Charset to the Content-Type runs afoul of a bug in Apahe and Azure that blocks the request because it thinks it's malformed.Moscow

© 2022 - 2024 — McMap. All rights reserved.