如何在 OCaml 中发出简单的 GET 请求?
How do I make a simple GET request in OCaml?
我正在尝试做一些应该很简单的事情:向 url 发出 GET 请求。但是,当我搜索如何执行此操作的示例时,我经常会遇到类似 this.
这样的近乎胡言乱语的内容
有谁知道如何使用 OCaml 发出简单的 HTTP 请求?我是 OCaml 新手,有一些 Haskell exp.
注意:
使用尽可能低级别的 OCaml 的解决方案将是理想的。我看过使用的 Cohttp
库,但我对原生 (?) HTTP
OCaml 库或类似的东西更感兴趣。
作为对 @antron
的回应,我们将不胜感激使用尽可能低级别的本机 OCaml 的解决方案。我被引导相信这将涉及 Unix
库。但是,如果有另一种不涉及第三方库的解决方案,那将同样受欢迎。
使用 Cohttp 库。见 Client example.
相关行是:
Cohttp_lwt_unix.Client.get (Uri.of_string "http://www.reddit.com/")
这为您提供了 Lwt
monad 中的一对 (response, body)
。 response
基本上是一条记录,而 body
是一条流。该示例的其余部分只是打印其中一些有趣的部分。
对于 OCaml 中的低级 Unix 编程(即使您不太了解),我推荐这本优秀的书 Unix System Programming in OCaml。它会告诉你如何编写你想要的客户端。
对于那些寻找完全独立的解决方案的人,我找到了一个至少可以在任何 Unix* 上运行的解决方案,例如 OS。
来自Rosetta Code:
let try_finalise f x finally y =
let res = try f x with e -> finally y; raise e in
finally y;
res
let rec restart_on_EINTR f x =
try f x with Unix.Unix_error (Unix.EINTR, _, _) -> restart_on_EINTR f x
let double_fork_treatment server service (client_descr, _ as client) =
let treat () =
match Unix.fork () with
| 0 ->
if Unix.fork () <> 0 then exit 0;
Unix.close server; service client; exit 0
| k ->
ignore (restart_on_EINTR (Unix.waitpid []) k)
in
try_finalise treat () Unix.close client_descr
let install_tcp_server_socket addr =
let s = Unix.socket Unix.PF_INET Unix.SOCK_STREAM 0 in
try
Unix.bind s addr;
Unix.listen s 10;
s
with e -> Unix.close s; raise e
let tcp_server treat_connection addr =
ignore (Sys.signal Sys.sigpipe Sys.Signal_ignore);
let server_sock = install_tcp_server_socket addr in
while true do
let client = restart_on_EINTR Unix.accept server_sock in
treat_connection server_sock client
done
let server () =
let port = 8080 in
let host = (Unix.gethostbyname (Unix.gethostname())).Unix.h_addr_list.(0) in
let addr = Unix.ADDR_INET (host, port) in
let treat sock (client_sock, client_addr as client) =
let service (s, _) =
let response = "\
HTTP/1.1 200 OK\r\n\
Content-Type: text/html; charset=UTF-8\r\n\r\n\
<html><head><title>Goodbye, world!</title>\
<style>body { background-color: #0FF }\
h1 { font-size:3em; color: black; }</style></head>\
<body><h1>Goodbye, world!</h1></body></html>\r\n"
in
Unix.write s response 0 (String.length response);
in
double_fork_treatment sock service client
in
tcp_server treat addr
let _ =
Unix.handle_unix_error server ()
这不是一条线,但相对简单。
也许在 OCaml 中发送 GET 请求的最基本方法是使用 Unix library and the basic input/output routines from Pervasives.
这是一个非常简单的例子:
let ip = Unix.((gethostbyname "caml.inria.fr").h_addr_list.(0))
let addr = Unix.ADDR_INET (ip, 80)
let sock = Unix.(socket PF_INET SOCK_STREAM 0)
let _ = Unix.connect sock addr
let in_ch = Unix.in_channel_of_descr sock
let out_ch = Unix.out_channel_of_descr sock
let _ =
output_string out_ch
"GET /pub/docs/manual-ocaml/index.html HTTP/1.1\r\n\
Host: caml.inria.fr\r\n\
User-Agent: OCaml\r\n\
Connection: close\r\n\
\r\n";
flush out_ch
let _ =
try
while true do
print_string (input_line in_ch)
done
with End_of_file ->
Unix.close sock
如果将 open Unix
放在文件顶部,则不需要 Unix.
前缀,但为了清楚起见,我更愿意保留它们。
程序可以用ocamlc unix.cma -o get get.ml
编译成字节码。
我同意@ChriS 的建议,阅读 Leroy 和 Rémy 的 Unix system programming in OCaml(我已将 link 添加到在线版本);这是一本好书。
我正在尝试做一些应该很简单的事情:向 url 发出 GET 请求。但是,当我搜索如何执行此操作的示例时,我经常会遇到类似 this.
这样的近乎胡言乱语的内容有谁知道如何使用 OCaml 发出简单的 HTTP 请求?我是 OCaml 新手,有一些 Haskell exp.
注意:
使用尽可能低级别的 OCaml 的解决方案将是理想的。我看过使用的 Cohttp
库,但我对原生 (?) HTTP
OCaml 库或类似的东西更感兴趣。
作为对 @antron
的回应,我们将不胜感激使用尽可能低级别的本机 OCaml 的解决方案。我被引导相信这将涉及 Unix
库。但是,如果有另一种不涉及第三方库的解决方案,那将同样受欢迎。
使用 Cohttp 库。见 Client example.
相关行是:
Cohttp_lwt_unix.Client.get (Uri.of_string "http://www.reddit.com/")
这为您提供了 Lwt
monad 中的一对 (response, body)
。 response
基本上是一条记录,而 body
是一条流。该示例的其余部分只是打印其中一些有趣的部分。
对于 OCaml 中的低级 Unix 编程(即使您不太了解),我推荐这本优秀的书 Unix System Programming in OCaml。它会告诉你如何编写你想要的客户端。
对于那些寻找完全独立的解决方案的人,我找到了一个至少可以在任何 Unix* 上运行的解决方案,例如 OS。
来自Rosetta Code:
let try_finalise f x finally y =
let res = try f x with e -> finally y; raise e in
finally y;
res
let rec restart_on_EINTR f x =
try f x with Unix.Unix_error (Unix.EINTR, _, _) -> restart_on_EINTR f x
let double_fork_treatment server service (client_descr, _ as client) =
let treat () =
match Unix.fork () with
| 0 ->
if Unix.fork () <> 0 then exit 0;
Unix.close server; service client; exit 0
| k ->
ignore (restart_on_EINTR (Unix.waitpid []) k)
in
try_finalise treat () Unix.close client_descr
let install_tcp_server_socket addr =
let s = Unix.socket Unix.PF_INET Unix.SOCK_STREAM 0 in
try
Unix.bind s addr;
Unix.listen s 10;
s
with e -> Unix.close s; raise e
let tcp_server treat_connection addr =
ignore (Sys.signal Sys.sigpipe Sys.Signal_ignore);
let server_sock = install_tcp_server_socket addr in
while true do
let client = restart_on_EINTR Unix.accept server_sock in
treat_connection server_sock client
done
let server () =
let port = 8080 in
let host = (Unix.gethostbyname (Unix.gethostname())).Unix.h_addr_list.(0) in
let addr = Unix.ADDR_INET (host, port) in
let treat sock (client_sock, client_addr as client) =
let service (s, _) =
let response = "\
HTTP/1.1 200 OK\r\n\
Content-Type: text/html; charset=UTF-8\r\n\r\n\
<html><head><title>Goodbye, world!</title>\
<style>body { background-color: #0FF }\
h1 { font-size:3em; color: black; }</style></head>\
<body><h1>Goodbye, world!</h1></body></html>\r\n"
in
Unix.write s response 0 (String.length response);
in
double_fork_treatment sock service client
in
tcp_server treat addr
let _ =
Unix.handle_unix_error server ()
这不是一条线,但相对简单。
也许在 OCaml 中发送 GET 请求的最基本方法是使用 Unix library and the basic input/output routines from Pervasives.
这是一个非常简单的例子:
let ip = Unix.((gethostbyname "caml.inria.fr").h_addr_list.(0))
let addr = Unix.ADDR_INET (ip, 80)
let sock = Unix.(socket PF_INET SOCK_STREAM 0)
let _ = Unix.connect sock addr
let in_ch = Unix.in_channel_of_descr sock
let out_ch = Unix.out_channel_of_descr sock
let _ =
output_string out_ch
"GET /pub/docs/manual-ocaml/index.html HTTP/1.1\r\n\
Host: caml.inria.fr\r\n\
User-Agent: OCaml\r\n\
Connection: close\r\n\
\r\n";
flush out_ch
let _ =
try
while true do
print_string (input_line in_ch)
done
with End_of_file ->
Unix.close sock
如果将 open Unix
放在文件顶部,则不需要 Unix.
前缀,但为了清楚起见,我更愿意保留它们。
程序可以用ocamlc unix.cma -o get get.ml
编译成字节码。
我同意@ChriS 的建议,阅读 Leroy 和 Rémy 的 Unix system programming in OCaml(我已将 link 添加到在线版本);这是一本好书。