Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

WinHttp.WinHttpRequest adding to the content-type

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.

like image 664
Manuel Peixoto Avatar asked Feb 26 '16 01:02

Manuel Peixoto


1 Answers

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)
like image 111
jveazey Avatar answered Oct 20 '22 18:10

jveazey