4

I can use the following code to easily get the HTML source from the URL, but how can I get the actual URL itself? Because sometimes the initial URL goes through some redirects and the actual URL is not the same and I would like to capture it for usage. I cannot seem to find any good documentation on the usage of methods or properties for winHTTP in Delphi. Thanks!

var http: variant;
begin
 http:=createoleobject('WinHttp.WinHttpRequest.5.1');
 http.open('GET', 'http://URLtoWebsite.com', false);
 http.send;
 showmessage(http.responsetext);
end;
gts6
  • 41
  • 2
  • Why not use an established library such as Indy or ICS? – Jerry Dodge Mar 27 '17 at 23:16
  • 1
    Initially I did use indy, and then even with the sslIOhandler, it still has issues with lots of ssl sites. So I figured it would be simpler to use winhttp instead. Its definitely simpler for grabbing the source html. But im definitely open to any other options if not possible using winhttp. And would like to avoid indy as well unless theres no other alternative. – gts6 Mar 27 '17 at 23:47
  • OK, but why are you using the COM/OLE wrapper, instead of using the [WinInet](https://msdn.microsoft.com/en-us/library/windows/desktop/aa385331.aspx) or [WinHTTP](https://msdn.microsoft.com/en-us/library/windows/desktop/aa382925.aspx) API directly? There is no real benefit to using the COM/OLE wrapper except in scripting environments. Look at `InternetQueryOption()` with the `INTERNET_OPTION_URL` flag, or `HttpQueryInfo()` with the `HTTP_QUERY_CONTENT_LOCATION`, `HTTP_QUERY_LOCATION` and `HTTP_QUERY_URI` flags. – Remy Lebeau Mar 28 '17 at 00:25

2 Answers2

2

You can use something like this

function GetFinalURL(const AMainURL: string): string;
var
  http: Variant;
begin
  Result := '';
  http := CreateOleObject('WinHttp.WinHttpRequest.5.1');
  http.Option(6) := False;
  http.open('GET', AMainURL, false);
  http.send;
  if http.Status = 302 then
    Result := http.getResponseHeader('Location')
  else
  Result := AMainURL;
end;

Another way using Indy

function GetFinalURL(const AMainURL: string): string;
var
  idHTTP: TIdHTTP;
begin
  Result := '';
  idHTTP := TIdHTTP.Create(nil);
  try
    idHTTP.HandleRedirects := True;
    try
      idHTTP.Get(AMainURL);
      Result := idHTTP.Request.URL;
    except
    end;
  finally
    idHTTP.Free;
  end;
end;
RepeatUntil
  • 2,272
  • 4
  • 32
  • 57
  • In WinHTTP, option 6 is `WinHttpRequestOption_EnableRedirects`, and `http.getResponseHeader('Location')` may not be a complete URL. In Indy, `TIdHTTP.Request.URL` may not be a complete URL, either. Redirects can be relative to the previously requested URL, so you may have to combine the two URLs, such as with the Win32 API `UrlCombine()` function. – Remy Lebeau Mar 28 '17 at 00:29
  • so then it would seem that its not possible using strictly winHTTP, is that correct? I guess im stuck using Indy then – gts6 Mar 30 '17 at 05:42
  • @gts6 The choice will be yours, You need to decide which library you want to use. The above functions answering your Q using `WinHTTP` and `Indy`. – RepeatUntil Mar 30 '17 at 14:44
0

You can set WinHttpSetStatusCallback with WINHTTP_CALLBACK_FLAG_REDIRECT parameter to receive notifications about every redirect occurred during request.

Alexander Ushakov
  • 5,139
  • 3
  • 27
  • 50