2

我最近的任务是使用套接字编程在 C 中创建一个代理。代理只需要使用 HTTP/1.0 构建。经过几个小时的工作,我制作了一个可以与 Chromium 一起使用的代理。可以加载各种网站,例如google和几个.edu网站;但是,许多网站给我一个找不到页面的 404 错误(这些链接在不通过我的代理时工作正常)。这些 404 错误甚至发生在站点的根地址“/”上……这没有意义。

这可能是我的 HTTP 请求的问题吗?从浏览器发送的 HTTP 请求被解析为 HTTP 请求方法、主机名和端口。例如,如果从浏览器解析 GET 请求,则会与提供的主机名和端口建立 TCP 连接,并以以下格式发送 HTTP GET 请求:

GET /path/name/item.html HTTP/1.0\r\n\r\n

此格式适用于少量网站,但会为其余网站创建 404 错误消息。这可能是问题吗?如果没有,还有什么可能给我这个问题?

任何帮助将不胜感激。

4

1 回答 1

7

一个可能的解释是您设计了一个 HTTP/1.0 代理,而现在共享托管站点上的任何网站都只能使用 HTTP/1.1(嗯,不完全是,但我会在一秒钟内解决这个问题)。

这不是唯一可能的问题,但你必须举一个网站的例子,这个网站像这样失败,以获得更多的想法。

您似乎了解 HTTP 的基础知识,客户端与服务器建立 TCP 连接并通过它发送 HTTP 请求,该请求由请求行(例如GET /path/name/item.html HTTP/1.0)和一组可选的标头行组成,全部由 CRLF 分隔(即\r\n)。整个批次以两个连续的 CRLF 序列结束,此时另一端的服务器将请求与资源匹配并发回适当的响应。资源全部由路径(例如/path/name/item.html)标识,路径可以是真实文件,也可以是动态页面。

自从它第一次被发明以来,HTTP 的大部分内容几乎没有变化。但是,请考虑客户端如何找到要连接的服务器。你给它的是一个 URL,像这样:

http://www.example.com/path/name/item.html

从这里它会看到方案http,所以它知道它正在建立一个 HTTP 连接。下一部分是主机名。在原始 HTTP 下,假设每个主机名都解析为自己的 IP 地址,然后客户端连接到该 IP 地址并发出请求。由于当时每台服务器只有一个网站,因此效果很好。

然而,随着网站数量的增加,为每个网站分配不同的 IP 地址变得越来越困难,特别是因为许多网站非常简单,可以很容易地在同一台物理机器上共享。将多个域指向同一个 IP 地址很容易(DNS 系统使这变得非常简单),但是当服务器收到 TCP 请求时,它只会知道它有一个对其 IP 地址的请求——它不知道是哪个网站寄回。因此,添加了一个新Host标头,以便客户端可以在请求本身中指示它正在请求哪个主机名。这意味着一台服务器可以托管许多网站,并且网络服务器可以使用Host标头来告诉在响应中服务哪个网站。

现在这很常见 - 如果您不使用Host标头,那么许多网站将不知道您要使用哪个服务器。通常发生的情况是,他们假设他们拥有的列表中有一些默认网站,并且很可能没有您要的文件。即使您要求/,如果您不提供Host标头,那么网络服务器可能会给您一个 404,如果它是这样配置的 - 如果没有合理的默认网站给您,这并不是不合理的。

如果您想了解更多技术细节,可以在 HTTP RFC中找到Host标头的描述。

此外,网站可能只是简单地拒绝 HTTP/1.0 -如果这种情况发生在这么多网站上,我会有点惊讶,但你永远不知道。不过,请先尝试Host标题。

与某些人认为的相反,没有什么可以阻止您将Host标头与 HTTP/1.0 一起使用,尽管您可能仍然会发现一些不喜欢这样的服务器。它比支持完整的 HTTP/1.1 要容易一些,这需要您了解分块编码和其他复杂性,尽管对于简单的示例代码,您可能只需添加Host标头并将其称为 HTTP/1.1(我不建议这样做)但是,对于生产代码来说已经足够了)。

无论如何,您可以尝试添加Host标头来提出您的请求,如下所示:

GET /path/name/item.html HTTP/1.0\r\n
Host: www.example.com\r\n
\r\n

为了便于阅读,我将它分成几行 - 你可以看到末尾仍然有空白行。

即使这不会导致您看到的问题,现在Host标题也是一个非常好的主意,因为肯定有一些网站没有它就无法工作。如果您仍然遇到问题,请给我一个不适合您的网站示例,我们可以尝试找出原因。

如果我所说的任何内容不清楚或需要更多详细信息,请询问。

于 2013-01-15T17:23:19.420 回答