WinHTTP 中) 的统一资源定位符 (URL

URL 是位于 Internet 上的资源的位置和访问方法的紧凑表示形式。 每个 URL 都包含一个方案 (HTTP、HTTPS、FTP 或 Gopher) 和一个特定于方案的字符串。 此字符串还可以包含目录路径、搜索字符串或资源名称的组合。 Microsoft Windows HTTP Services (WinHTTP) 函数提供创建、合并、分解和规范 URL 的功能。 有关详细信息,请参阅 RFC 1738统一资源定位符RFC 2396统一资源标识符 (URI) :通用语法

什么是规范化 URL?

URL 的指定语法和语义为变体和错误留有余地。 规范化是将实际 URL 规范化为正确、标准的“规范”形式的过程。

这涉及到将某些字符编码为“转义序列”。无需将字母数字 US-ASCII 字符编码 (数字 0-9、大写字母 A-Z 和小写字母 a-z) 。 大多数其他字符必须转义,包括控制字符、空格字符、百分号、“不安全字符” ( <、 >、、“、#、{、}、|、\、^、~、[、]和 ' ) ,以及码位高于 127 的所有字符。

使用 WinHTTP 函数处理 URL

WinHTTP 提供两个用于处理 URL 的函数。 WinHttpCrackUrl 将 URL 分隔为其组件部分, WinHttpCreateUrl 从组件创建 URL。

分隔 URL

WinHttpCrackUrl 函数将 URL 分成其组件部分,并返回传递给函数的 URL_COMPONENTS 结构指示的组件。

构成 URL_COMPONENTS 结构的组件包括方案编号、主机名、端口号、用户名、密码、URL 路径和其他信息(如搜索参数)。 除方案和端口号外,每个组件都有一个保存信息的字符串成员和一个保存字符串成员长度的成员。 方案和端口号只有一个存储相应值的成员;所有成功调用 WinHttpCrackUrl 时,都会返回方案和端口号。

若要检索 URL_COMPONENTS 结构中特定组件的值,存储该组件的字符串长度的成员必须设置为非零值。 字符串成员可以是指向缓冲区的指针或 NULL

如果指针成员包含指向缓冲区的指针,则字符串长度成员必须包含该缓冲区的大小。 WinHttpCrackUrl 函数在缓冲区中以字符串的形式返回组件信息,并将字符串长度存储在字符串长度成员中。

如果指针成员设置为 NULL,则可以将字符串长度成员设置为任何非零值。 WinHttpCrackUrl 函数存储指向包含组件信息的 URL 字符串的第一个字符的指针,并将字符串长度设置为与组件相关的 URL 字符串剩余部分中的字符数。

所有设置为 NULL 且长度非零成员的指针成员指向 URL 字符串中的相应起点。 必须使用存储在长度成员中的长度来确定单个组件信息的末尾。

若要正确完成 URL_COMPONENTS 结构的初始化,必须将 dwStructSize 成员设置为 URL_COMPONENTS 结构的大小。

创建 URL

WinHttpCreateUrl 函数使用前面所述的 URL_COMPONENTS 结构中的信息来创建 URL。

对于每个必需的组件,指针成员应包含指向保存信息的缓冲区的指针。 如果指针成员包含指向以零结尾的字符串的指针,则应将长度成员设置为零;如果指针成员包含指向不以零结尾的字符串的指针,则长度成员应设置为字符串长度。 任何不需要的组件的指针成员必须设置为 NULL

代码示例

以下示例代码演示如何使用 WinHttpCrackUrlWinHttpCreateUrl 来反汇编现有 URL、修改其组件之一,并将其重新组合到新的 URL 中。

  URL_COMPONENTS urlComp;
  LPCWSTR pwszUrl1 = 
    L"https://search.msn.com/results.asp?RS=CHECKED&FORM=MSNH&v=1&q=wininet";
  DWORD dwUrlLen = 0;

  // Initialize the URL_COMPONENTS structure.
  ZeroMemory(&urlComp, sizeof(urlComp));
  urlComp.dwStructSize = sizeof(urlComp);

  // Set required component lengths to non-zero so that they are cracked.
  urlComp.dwSchemeLength    = (DWORD)-1;
  urlComp.dwHostNameLength  = (DWORD)-1;
  urlComp.dwUrlPathLength   = (DWORD)-1;
  urlComp.dwExtraInfoLength = (DWORD)-1;

  // Crack the URL.
  if( !WinHttpCrackUrl( pwszUrl1, (DWORD)wcslen(pwszUrl1), 0, &urlComp ) )
      printf( "Error %u in WinHttpCrackUrl.\n", GetLastError( ) );
  else
  {
    // Change the search information.  New info is the same length.
    urlComp.lpszExtraInfo = L"?RS=CHECKED&FORM=MSNH&v=1&q=winhttp";

    // Obtain the size of the new URL and allocate memory.
    WinHttpCreateUrl( &urlComp, 0, NULL, &dwUrlLen );
    LPWSTR pwszUrl2 = new WCHAR[dwUrlLen];

    // Create a new URL.
    if( !WinHttpCreateUrl( &urlComp, 0, pwszUrl2, &dwUrlLen ) )
      printf( "Error %u in WinHttpCreateUrl.\n", GetLastError( ) );
    else
    {
      // Show both URLs.
      printf( "Old URL:  %S\nNew URL:  %S\n", pwszUrl1, pwszUrl2 );
    }

    // Free allocated memory.
    delete [] pwszUrl2;
  }