user1853330
user1853330

Reputation: 21

How can I find if a webpage exists using WinINet

I am trying to connect and ensure various pages exist on a webserver provided by an instrument we design. I am trying to do this through C++ Win32 using WinInet commands.

I am happy that I have connected correctly to the webserver via HTTP:

hInternet = InternetOpen("Test", INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0/*INTERNET_FLAG_ASYNC*/);
hhttp = InternetConnect(hInternet, "192.168.111.222", INTERNET_DEFAULT_HTTP_PORT, "admin", "admin", INTERNET_SERVICE_HTTP, 0, 0);

I believe I then have to open a request.

hHttpRequest = HttpOpenRequest(hhttp, "GET", "galogo.png", NULL, "192.168.111.222", lplpszAcceptTypes, INTERNET_FLAG_RELOAD | INTERNET_FLAG_PRAGMA_NOCACHE, 0);

and then send the request.

HttpSendRequest(hHttpRequest, NULL, 0, NULL, 0)

Note: 192.168.111.222 is the address of the unit running the webserver and galogo.png is an image displayed on the home page. Please also note that I am error checking between each statements so if I do disconnect the Ethernet then I do get a failure.

Initially I did try just connecting to the home.html page but this always passed so I thought I should try and get the image but I am probably lacking in knowledge. Other examples seem to then stream data but I wasn't sure if I needed to do this.

Most of the examples I have seen seem to show the HtppSendRequest in this format and I don't really understand about headers etc. Maybe it is here I am going wrong.

Upvotes: 1

Views: 2415

Answers (3)

ALK007
ALK007

Reputation: 23

Its is Simple following are the Steps: 1- Open Connection 2- Connect 3- Open request 4- Send request 5- Read file 6- Save file (as png or jpg) 7- Close handles The code is as follow:

#include <iostream>
#include <string>
#include <Windows.h>
#include <wininet.h>
#pragma comment(lib, "wininet")

using namespace std;
void download(string domain,string url,string filepath)
{
    //Step 1:
    HINTERNET hIntSession = InternetOpenA("MyApp", INTERNET_OPEN_TYPE_DIRECT, NULL, NULL, 0);
    //Step 2:
    HINTERNET hHttpSession = InternetConnectA(hIntSession, domain.c_str(), 80, 0, 0, INTERNET_SERVICE_HTTP, 0, NULL);
    //Step 3:
    HINTERNET hHttpRequest = HttpOpenRequestA( hHttpSession, "GET",url.c_str(),0, 0, 0, INTERNET_FLAG_RELOAD, 0);
    TCHAR* szHeaders = L"";
    CHAR szReq[1024] = "";
    //Step 4:
    if( !HttpSendRequest(hHttpRequest, szHeaders, wcslen(szHeaders), szReq, strlen(szReq))) {
        DWORD dwErr = GetLastError();
        cout<<"error "<<dwErr<<endl;
        /// handle error
    }
    TCHAR szBuffer[1025];
    DWORD dwRead=0;
    FILE *f;
    f=fopen(filepath.c_str(),"wb");
    //Step 5 & 6:
    while(InternetReadFile(hHttpRequest,szBuffer, 1024, &dwRead) && dwRead)
    {
        fwrite(szBuffer,sizeof(BYTE),1024,f);
        dwRead=0;
    }
    fclose(f);
    //Step 7:
    InternetCloseHandle(hHttpRequest);
    InternetCloseHandle(hHttpSession);
    InternetCloseHandle(hIntSession);
}
int main()
{
    download("www.stacktoheap.com","images/stackoverflow.png","C:\\Example\\example.png");
}

Upvotes: 0

user1853330
user1853330

Reputation: 21

So, using a combination of cURL and Wireshark I'm finally there. I was making some fundamental mistakes but basically on the right track.

First open the connection and connect as previously stated, making sure it is not ASYNC (this lead to some overlapped IO errors):

hInternet = InternetOpen("Test", INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0/*INTERNET_FLAG_ASYNC*/);

hhttp = InternetConnect(hInternet, "192.168.111.222", INTERNET_DEFAULT_HTTP_PORT, "admin", "admin", INTERNET_SERVICE_HTTP, 0, 0);

I needed to create the request and then send it. I only needed to specify the page as the request will take in connection details.

hHttpRequest = HttpOpenRequest(hhttp, "GET", "home.html", NULL, NULL, lplpszAcceptTypes, INTERNET_FLAG_RELOAD | INTERNET_FLAG_PRAGMA_NOCACHE, 0);

HttpSendRequest(hHttpRequest, NULL, 0, NULL, 0);

Then use the HttpQueryInfo function to retrieve the status and convert back to integer. Make sure you are sending the handle from the Request not the Connect.

//These are defined earlier
DWORD statCharLen = 0;
char statChar[256]="";    
statCharLen = sizeof(statChar);

HttpQueryInfo(hHttpRequest, HTTP_QUERY_STATUS_CODE, statChar, &statCharLen, NULL);

Finally shut down connection:

InternetCloseHandle(hInternet)

Thanks

Upvotes: 0

Mike Dillamore
Mike Dillamore

Reputation: 198

The HttpQueryInfo function will give header information relating to the request, and you can extract the HTTP status code from this.

You may be able to achieve the result more easily using higher level WinINet functions. I would suggest a sequence consisting of InternetOpen, InternetOpenUrl, HttpQueryInfo and then repeated calls to InternetReadFile if the HTTP status code is OK.

This Delphi code (from Delphi 7, so pre-Unicode) seems to do the job: -

function GetUrlContent(const Agent, Url: string): string;
var
  NetHandle: HINTERNET;
  UrlHandle: HINTERNET;
  Buffer: array [0..1024] of Char;
  BytesRead: DWORD;
  Dummy: DWORD;
  BufLen: DWORD;
  HttpStatus: string;
begin
  Result := '';
  NetHandle := InternetOpen(PChar(Agent), INTERNET_OPEN_TYPE_PRECONFIG,
    nil, nil, 0);

  if Assigned(NetHandle) then
  begin
    UrlHandle := InternetOpenUrl(NetHandle, PChar(Url), nil, 0,
      INTERNET_FLAG_RELOAD, 0);

    if Assigned(UrlHandle) then
    // UrlHandle valid?  Proceed with download.
    try
      BufLen := Length(Buffer);
      Dummy := 0;
      // only get the file if the HTTP status code is 200
      if HttpQueryInfo(UrlHandle, HTTP_QUERY_STATUS_CODE, @Buffer[0], BufLen, Dummy) then
      begin
        HttpStatus := Buffer;
        if HttpStatus = '200' then
        begin
          FillChar(Buffer, SizeOf(Buffer), 0);
          repeat
            Result := Result + Buffer;
            FillChar(Buffer, SizeOf(Buffer), 0);
            InternetReadFile(UrlHandle, @Buffer, SizeOf(Buffer), BytesRead);
          until BytesRead = 0;
        end
        else begin
          raise Exception.CreateFmt('HTTP status code %s', [HttpStatus]);
        end;
      end
      else begin
        raise Exception.Create('Unable to read HTTP status code');
      end;
    finally
      InternetCloseHandle(UrlHandle);
    end
    else begin
      // UrlHandle is not valid.  Raise an exception.
      raise Exception.CreateFmt('Cannot open URL %s', [Url]);
    end;
    InternetCloseHandle(NetHandle);
  end
  else begin
    // NetHandle is not valid.  Raise an exception.
    raise Exception.Create('Unable to initialize WinINet');
  end;
end;

Upvotes: 2

Related Questions