Как разобрать веб-URL?

Мне нужно разбить URL-адрес на разные сегменты. Возьмите этот путь, например:

http://login:[email protected]:8080/some_path/something_else.html?param1=val&param2=val#nose
\__/   \___/ \______/ \_____________________/ \__/\____________________________/ \___________________/ \__/
 |       |      |               |               |                |                        |              |
Scheme Username Password       Host            Port             Path                    Query         Fragment

Это должно сломаться следующим образом:

Protocol: HTTP
Username: login
Password: password
Host: somehost.somedomain.com
Port: 8080
Path Info: /some_path/something_else.html
Query String: param1=val&param2=val

Как я могу сделать это в Delphi? Есть ли что-то готовое, которое может разделить это для меня? Если нет, как я могу разобрать все возможные форматы? Предполагается, что это может быть другой протокол, например HTTPS или RTSP.

Ответ 1

XE2 поставляется с Indy, который имеет класс TIdURI для этой цели, например:

uses
  ..., IdURI;

var
  URI: TIdURI;

URI := TIdURI.Create('http://login:[email protected]:8080/some_path/something_else.html?param1=val&param2=val');
try
  // Protocol = URI.Protocol
  // Username = URI.Username
  // Password = URI.Password
  // Host = URI.Host
  // Port = URI.Port
  // Path = URI.Path
  // Query = URI.Params
finally
  URI.Free;
end;

Ответ 2

Вы можете использовать метод InternetCrackUrl.

Попробуйте этот простой

{$APPTYPE CONSOLE}

uses
  Windows,
  SysUtils,
  WinInet;

procedure ParseURL(const lpszUrl: string);
var
  lpszScheme      : array[0..INTERNET_MAX_SCHEME_LENGTH - 1] of Char;
  lpszHostName    : array[0..INTERNET_MAX_HOST_NAME_LENGTH - 1] of Char;
  lpszUserName    : array[0..INTERNET_MAX_USER_NAME_LENGTH - 1] of Char;
  lpszPassword    : array[0..INTERNET_MAX_PASSWORD_LENGTH - 1] of Char;
  lpszUrlPath     : array[0..INTERNET_MAX_PATH_LENGTH - 1] of Char;
  lpszExtraInfo   : array[0..1024 - 1] of Char;
  lpUrlComponents : TURLComponents;
begin
  ZeroMemory(@lpszScheme, SizeOf(lpszScheme));
  ZeroMemory(@lpszHostName, SizeOf(lpszHostName));
  ZeroMemory(@lpszUserName, SizeOf(lpszUserName));
  ZeroMemory(@lpszPassword, SizeOf(lpszPassword));
  ZeroMemory(@lpszUrlPath, SizeOf(lpszUrlPath));
  ZeroMemory(@lpszExtraInfo, SizeOf(lpszExtraInfo));
  ZeroMemory(@lpUrlComponents, SizeOf(TURLComponents));

  lpUrlComponents.dwStructSize      := SizeOf(TURLComponents);
  lpUrlComponents.lpszScheme        := lpszScheme;
  lpUrlComponents.dwSchemeLength    := SizeOf(lpszScheme);
  lpUrlComponents.lpszHostName      := lpszHostName;
  lpUrlComponents.dwHostNameLength  := SizeOf(lpszHostName);
  lpUrlComponents.lpszUserName      := lpszUserName;
  lpUrlComponents.dwUserNameLength  := SizeOf(lpszUserName);
  lpUrlComponents.lpszPassword      := lpszPassword;
  lpUrlComponents.dwPasswordLength  := SizeOf(lpszPassword);
  lpUrlComponents.lpszUrlPath       := lpszUrlPath;
  lpUrlComponents.dwUrlPathLength   := SizeOf(lpszUrlPath);
  lpUrlComponents.lpszExtraInfo     := lpszExtraInfo;
  lpUrlComponents.dwExtraInfoLength := SizeOf(lpszExtraInfo);

  InternetCrackUrl(PChar(lpszUrl), Length(lpszUrl), ICU_DECODE or ICU_ESCAPE, lpUrlComponents);

  Writeln(Format('Protocol : %s',[lpszScheme]));
  Writeln(Format('Host     : %s',[lpszHostName]));
  Writeln(Format('User     : %s',[lpszUserName]));
  Writeln(Format('Password : %s',[lpszPassword]));
  Writeln(Format('Path     : %s',[lpszUrlPath]));
  Writeln(Format('ExtraInfo: %s',[lpszExtraInfo]));
end;

begin
  try
   ParseURL('http://login:[email protected]/some_path/something_else.html?param1=val&param2=val');
  except
    on E: Exception do
      Writeln(E.ClassName, ': ', E.Message);
  end;
  readln;
end.

Это вернет

Protocol : http
Host     : somehost.somedomain.com
User     : login
Password : password
Path     : /some_path/something_else.html
ExtraInfo: ?param1=val&param2=val