上下文:JA"编程Erlang" 2ed,第16章关于文件,第256页,使用解析来自二进制文件的URL的示例。
建议的步骤(在编写scavenge_urls模块的代码之后)是:
B = socket_examples:nano_get_url("www.erlang.org"),
L = scavenge_urls:bin2urls(B),
scavenge_urls:urls2htmlFile(L,"gathered.html").
这失败了(巧妙地) - 列表L最终为空。单独运行第一步,观察到一个奇怪的事情 - 它确实返回二进制文件,但它不是我想要的二进制文件:
9> B.
<<"HTTP/1.1 404 Not Found\r\nServer: nginx\r\nDate: Sun, 19 Nov 2017 01:57:07 GMT\r\nContent-Type: text/html; charset=UTF-8\r\n"...>>
shows that this is where the problem lies.
然而在浏览器中对母舰的所有好处!我能够通过替换对socket_examples:nano_get_urls / 1的调用来完成练习,首先使用CURLing替换相同的url,将其转储到文件中,然后将文件:read_file / 1。接下来的步骤都很顺利。
在socket_examples模块中偷看,我看到了:
nano_get_url(Host) ->
{ok,Socket} = gen_tcp:connect(Host,80,[binary, {packet, 0}]), %% (1)
ok = gen_tcp:send(Socket, "GET / HTTP/1.0\r\n\r\n"), %% (2)
receive_data(Socket, []).
receive_data(Socket, SoFar) ->
receive
{tcp,Socket,Bin} -> %% (3)
receive_data(Socket, [Bin|SoFar]);
{tcp_closed,Socket} -> %% (4)
list_to_binary(reverse(SoFar)) %% (5)
end.
没有什么看起来可疑。首先它建立连接,然后它触发GET,然后它接收响应。我以前从来没有必须先明确连接,然后激活GET秒,我的http客户端库隐藏了我的内容。所以也许我不知道该找什么......我相信Joe的代码没有任何明显的错误! =)然而,带有注释(3),(4)和(5)的行不是我完全理解的。
那么,任何想法,同事Erlangers? 谢天谢地!
答案 0 :(得分:4)
问题不在于Erlang。看起来运行erlang.org的服务器也需要Host
标头:
$ nc www.erlang.org 80
GET / HTTP/1.0
HTTP/1.1 404 Not Found
Server: nginx
Date: Sun, 19 Nov 2017 05:51:39 GMT
Content-Type: text/html; charset=UTF-8
Content-Length: 162
Connection: close
Vary: Accept-Encoding
<html>
<head><title>404 Not Found</title></head>
<body bgcolor="white">
<center><h1>404 Not Found</h1></center>
<hr><center>nginx</center>
</body>
</html>
$ nc www.erlang.org 80
GET / HTTP/1.0
Host: www.erlang.org
HTTP/1.1 200 OK
Server: nginx
Date: Sun, 19 Nov 2017 05:51:50 GMT
Content-Type: text/html; charset=UTF-8
Content-Length: 12728
Connection: close
Vary: Accept-Encoding
<!DOCTYPE html>
<html>
...
您的Erlang代码也适用于GET HTTP/1.0\r\n
之后的主机标头:
1> Host = "www.erlang.org".
"www.erlang.org"
2> {ok, Socket} = gen_tcp:connect(Host, 80, [binary, {packet, 0}]).
{ok,#Port<0.469>}
3> ok = gen_tcp:send(Socket, "GET / HTTP/1.0\r\nHost: www.erlang.org\r\n\r\n").
ok
4> flush().
Shell got {tcp,#Port<0.469>,
<<"HTTP/1.1 200 OK\r\nServer: nginx\r\n...>>
Shell got {tcp_closed,#Port<0.469>}