Monolune

How to download files using Racket

Suppose you want to use Racket to download a file or a web page over HTTP. Fortunately, stock installations of Racket provide procedures for downloading files over HTTP and HTTPS in the net/url library.

Downloading over HTTP

#lang racket
(require net/url)

;; Download the data.
(define the-url (string->url "http://www.example.com/mydata.dat"))
(define the-data (port->bytes (get-pure-port the-url)))

;; Write the data to a file.
(define out (open-output-file "mydata.dat"))
(write-bytes the-data out)
(close-output-port out)

The procedure get-pure-port from the net/url package is the one that does the actual downloading.

If you prefer to get the downloaded data as a string instead of writing it to a file, use port->string instead of port->bytes. An example of this will be shown shortly.

WARNING: the code above can also be used to download over HTTPS, but by default, Racket will not verify the server's certificate. To enable validation of server certificates when downloading over HTTPS, read the following section.

Enable verification of server certificates

#lang racket
(require net/url
         net/url-connect)

;; Download the data.
(define the-url (string->url "https://www.example.com/mydata.dat"))
(define the-data
  (parameterize ([current-https-protocol 'secure])  ; Enable server certificate validation.
    (port->bytes (get-pure-port the-url))))

;; Write the data to a file.
(define out (open-output-file "mydata.dat"))
(write-bytes the-data out)
(close-output-port out)

In this snippet of code, the server certificates will be verified when HTTPS is used. Server certificate validation is enabled by setting the current-https-protocol parameter, which is provided by the net/url-connect library.

Getting the data as a string

If you want to get the downloaded data as a string instead of writing it to a file, use the port->string procedure instead of port->bytes. For example:

#lang racket
(require net/url)

;; Download the data.
(define the-url (string->url "http://www.example.com/mydata.dat"))
(port->string (get-pure-port the-url))  ; Returns a string.

Discussion

I hope that the preceding examples and explanations have been helpful. They illustrate the utility of ports in Racket. If you intend to do lots of input/output in Racket, I would suggest that you get familiar with ports by looking up the relevant section in the Racket Guide, followed by the Racket Reference. Happy downloading!