在Racket的REPL中发出HTTP GET请求

13

我觉得我有点遗漏了什么,但是在浏览了net/url的文档并且进行了一些探索后,我没有找到一种从交互提示符中发出GET请求的方法。基本上,我想模仿我的Python工作流程来浏览网站:

response = urlopen("http://www.someurl.com")

在 Racket 中是否可行?

2个回答

13

使用call/input-url具有以下几个优点:

  • 你不需要自己关闭端口。
  • 即使出现异常,端口也会被关闭。
  • 它的第三个参数是(input-port? -> any/c)--即一个接受input-port并返回任何内容的函数。除了自己编写的函数外,这还可以是已定义的函数,例如port->stringread-html-as-xml等。

例如:

(call/input-url (string->url "http://www.google.com/")
                get-pure-port
                port->string)
注意:当我正在打这个答案时,我注意到Óscar已经编辑了他的重定向。我的类似编辑将是:
(call/input-url (string->url "http://www.google.com/")
                (curry get-pure-port #:redirections 4)
                port->string)

当然,在REPL中频繁输入这两种方式都相对啰嗦。所以,Óscar建议定义一个自己的url-open函数是个好主意。我认为使用call/input-url来实现它更佳。


1
除了手动解析标头之外,是否有提取状态代码的方法?我很惊讶我找不到任何帮助函数来完成这项任务,无论是在Racket本身还是在您的http库中。 - offby1
抱歉,直到现在我才注意到您的评论!我的http库有函数可以做到这一点:https://github.com/greghendershott/http/blob/master/http/head.rkt#L22-L45 - Greg Hendershott

7

试试这个:

(require net/url)

(define input (get-pure-port (string->url "http://www.someurl.com")))
(define response (port->string input))
(close-input-port input)

现在 response 变量将包含来自服务器的http响应。更好的是,将以上内容封装在一个过程中,同时还要注意我增加了允许的最大重定向次数:

(define (urlopen url)
  (let* ((input (get-pure-port (string->url url) #:redirections 5))
         (response (port->string input)))
    (close-input-port input)
    response))

(urlopen "http://www.someurl.com") ; this will return the response

编辑:

根据@GregHendershott的建议(详见他的答案),这里提供另一种更加稳健的实现所需功能的方法:

(define (urlopen url)
  (call/input-url
   (string->url url)
   (curry get-pure-port #:redirections 5)
   port->string))

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接