We help IT Professionals succeed at work.

WinHttp - posting form data

Medium Priority
Last Modified: 2013-12-03
I am successfully posting form data to a php web object using WinHttp
So this isn't a question about how to post form data to a web page using WinHttp.

Question: How do I succesfully post form data multiple times using the same connection?
In my first request, I post minimal data to see if authentication is required, that works fine.

But then in my following request:
The web page only sees the REMOTE_LOGIN pair... nothing else
BUT if I send this one FIRST the web page sees all name/value pairs.

I'm assuming I'm not setting a HTTP parameter correctly to handle this type of 'multiple' post.
Any ideas?

Watch Question


Well, it seems that the question posted is either too difficult or too vague.
Here's what I have discovered so far.
I have verified that the HTTP connection has the 'keep alive' attribute enabled and is working as expected.
What seems to be the issue, in posting to a PHP page is how to maintain the 'logged-in/authenticated' state after the initial login submit.
I've read the MSDN documentation regarding WinHttp Authentication

My next attempt at a solution will be to maintain the PHPSESSIONID cookie information  in the header.
At this point, since it seems that I am the only one trying to answer my question, I will have problems with issuing 500 points to someone who says, "Yes, you're on the right track", but if you correct my solution with something I haven't considered then I'll award all 500 points.


Here's what I did to resolve the issue.
If anyone can clearly explain to me why I have to manually set the Content-Length in the header myself  then 500 is yours.

CStringW header;
ULONG postdata_len = strRequest.GetLength();
header.Format(L"Content-Length: %d", postdata_len);
DWORD header_len = header.GetLength();

 ::WinHttpSendRequest( m_hRequest                                          , header      // , WINHTTP_NO_ADDITIONAL_HEADERS                  , header_len      // , 0
            , (LPVOID)((LPCTSTR)strRequest)
            , postdata_len                                    , postdata_len
            , 0);
Author of the Year 2009

It seems that the PHP object is looking for that particular header and rejecting or otherwise mishandling the situation when it is not present.

The Content-Length header is optional, but that does not mean that the server can't require it or take special action when it is expected but missing.


Appreciate your input Dan,
I'm defining "PHP object" in terms of what WinHttp refers to as simply the web page.
For instance login.php - these pages don't require special/custom handling when it comes to reading HTTP header data. I'm just trying to replicate what IE or Firefox does on these pages, but without the user interface. I'm handling the cookie data fine to avoid authenticatin on each request. The question remains - Why causes WinHTTPSendRequest(..) to not update the content length in the header on EVERY request ?
Author of the Year 2009

There is clearly some code being executed on the server in the PHP program... (as opposed to, for isntance, simply spitting back an simple HTML page).  I can assume that because the server would need to take a different path if the login was incorrect.  

So, that's where I'd focus my attention:  Examine the coding in the PHP program to see what special things it is doing regarding the header data.


Yes, we've set up the server to respond differently when the POST contains REMOTE_LOGIN=1.
All we respond with is 200 or 401.

The server is correctly reading the HTTP request as sent.
In the example given, the first request(via WinHTTPSendRequest) correctly sets Content-Length to 14 and the server reads the request just fine. Once I change the post data and attempt to resend the data, the Content-Length is stuck at 14, unless I change the Header information myself. To me this is a bug with WinHTTPSendRequest. Let me know if you see something amiss with my conclusion.
Author of the Year 2009
Without seeing the version of the function that failed, it's hard to know.  However...

According to
the third parameter, dwHeadersLength, can be set to
if you want the function to re-calculate the length of the headers.  In your  example, it appears that you had been setting it to 0 (possibly providing an implied/undocumented meaning of "use existing header data").

>> I change the post data and attempt to resend the data

I assume that you are using the same hRequest (from a previous WinHttpOpenRequest call).  It's possible that the WinHttp functions would work more intuitively if you simply opened a new request before each send.

Note that my experience is mainly with the older WinInet functions, but in my time-tested systems, I make each transaction stand on its own.  I even close the session after each transaction so I can start clean.  Anyway, I don't know all of the nuances of what happens when you start with a "dirty" (previously-used) hRequest.


Setting the dwHeadersLength to -1 simply calculates the length of the additional header data for you.
BUT remember - dwOptionalLength -> Content-Length(not the header length) is the one not being adjusted correctly by the function on multiple posts.

I'm just saying that I should not even have to provide addional header data to this function in order for it to know what the Content-Length of the posted data is. It obviously uses dwOptionalLength correctly on my first post without even having to provide the data, but is failing to do so on following posts.
Remember that this function works as documented, on the FIRST post, but fails on multiple post.

> "but in my time-tested systems, I make each transaction stand on its own."
I think that's an alternate route for me to go also.

If you find something else, let me know, otherwise I'm happy to award you the points for your efforts.


Please note that Microsoft's WinHttp team is working with me now on the issue. I'm awarding points based on effort and willingness to help.