13
votes

I feel like I'm missing something, but after perusing the docs for net/url and poking around in general, I was unable to figure out a way to issue a GET request from the interactive prompt. Basically, I want to imitate my python workflow for poking around a website:

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

is this feasible in Racket?

2

2 Answers

13
votes

Using call/input-url has a few advantages:

  • You don't need to close the port yourself.
  • The port is closed even if there's an exception.
  • Its third argument is (input-port? -> any/c) -- that is, a function that takes an input-port and returns anything. In addition to a function you write yourself, this could be an already-defined function like port->string, read-html-as-xml, and so on.

For example:

(call/input-url (string->url "http://www.google.com/")
                get-pure-port
                port->string)

Note: As I was typing this answer, I notice that Óscar edited his to do redirects. My similar edit would be:

(call/input-url (string->url "http://www.google.com/")
                (curry get-pure-port #:redirections 4)
                port->string)

Of course, either way is still fairly verbose to type frequently at the REPL. So Óscar's suggestion to define your own url-open function is a good one. Implementing it using call/input-url would be preferable, I think.

7
votes

Try this:

(require net/url)

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

Now the response variable will contain the http response from the server. Even better, pack the above in a procedure, also notice that I added a maximum number of redirections allowed:

(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

EDIT:

Following @GregHendershott's excellent advice (see his answer for details), here's another, more robust way to implement the desired functionality:

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