1

Based on some SO question I saw earlier, I'm using WinHttpRequest inside of Inno Setup to make a GET request to a web server (localhost:8000 right now). Minimal code below, the request is to the built-in Django debug server (python manage.py runserver).

procedure InitializeWizard();
var
    WinHttpReq: Variant;
    url: string;
    HTTPREQUEST_SETCREDENTIALS_FOR_SERVER: integer;
begin
    url := 'http://localhost:8000/odbc/test/';
    HTTPREQUEST_SETCREDENTIALS_FOR_SERVER := 0;

    WinHttpReq := CreateOleObject('WinHttp.WinHttpRequest.5.1');
    WinHttpReq.Open('GET', url, false);
    WinHttpReq.SetRequestHeader('Accept','application/json');
    WinHttpReq.SetCredentials('username','password',HTTPREQUEST_SETCREDENTIALS_FOR_SERVER);
    WinHttpReq.Send();
    MsgBox(WinHttpReq.Status, mbInformation, MB_OK);
    MsgBox(WinHttpReq.ResponseText, mbInformation, MB_OK);
end;

This gives me a 403, authentication credentials not provided.

On the contrary, this code in the Python requests library works successfully.

>> import requests
>> r = requests.get('http://localhost:8000/odbc/test/', auth=('username','password'))
>> r.status_code
200

Am I misunderstanding how the WinHttpRequest object works? Because Wireshark confirms an Authorization: Basic *hashstring* header was sent in the header with the Python requests, but not in the WinHttpRequest case. A likely workaround would be to set the header myself for the WinHttpRequest object but I'm just curious if I'm doing anything wrong.

Gist with packet captures: https://gist.github.com/anonymous/597468ba76b59dae4a8d7809ee1c6feb

Wireshark screenshots:

WinHttpRequest in Inno Setup Wireshark capture

Python requests library Wireshark capture

Nils Guillermin
  • 1,867
  • 3
  • 21
  • 51
  • Works for me (against Apache server) - 1) Do you have any special characters in the username/password? 2) Can you try to capture the HTTP traffic using e.g. Wireshark, both for the Inno Setup code and the Python code? And post them here? Or at least webserver logs for both. – Martin Prikryl Oct 18 '16 at 18:04
  • Added wireshark capture screenshots. Is there a better format for posting wireshark captures? – Nils Guillermin Oct 18 '16 at 18:27
  • When you stop the capturing, you can save the traffic to a file. Note that that the `WinHttpRequest` sends two HTTP requests. First time, without authentication, and then after receiving 401, it sends second request with authorization. So we need to see both requests, including the responses from the server. – Martin Prikryl Oct 18 '16 at 19:31
  • Added Gist. I do not see where you see two requests from `WinHttpRequest`. – Nils Guillermin Oct 19 '16 at 11:30
  • They are not in your captures, because your server does not send the `WWW-Authenticate` header. But I can see them, when I test your code against my (Apache) server. If I configure my server to behave as your does (no `WWW-Authenticate` header), I get the same behavior as you (one request only, no `Authenticate` header). – Martin Prikryl Oct 19 '16 at 11:46

1 Answers1

1

My guess is that this is an incompatibility between the WinHttpRequest and your "Django debug server".


The WinHttpRequest sends the Authenticate header, only after being challenged by the server with the WWW-Authenticate header.

There's no such header in the 403 response from your server. Hence the WinHttpRequest does not send the Authorization header.

Solutions are:

  • Make your server return the WWW-Authenticate header (and ideally the 401 status - though this is not required by the WinHttpRequest).

  • Send the Authenticate header explicitly by:

    WinHttpReq.SetRequestHeader('Authorization', 'Basic ???');
    
Martin Prikryl
  • 188,800
  • 56
  • 490
  • 992