(net http-client) - Modern HTTP client

Library (net http-client)

Providing, probably, modern HTTP client.

The (net http-client) provides a modern HTTP client, which handles connection pooling, client certificate, redirect and cookie. The client also provides asynchronous calling atop future object of (util concurrent).

The following example shows how to use in a nutshell.

(import (rnrs)
        (net http-client)
        (util concurrent))

(define client (http:client-builder
                (follow-redirects (http:redirect normal))))

(let ((future (http:client-send-async client
                                      (http:request-builder
                                       (uri "http://google.com")))))
  ;; do whatever you need to do during the above HTTP call
  (let ((response (future-get future)))
    (http:response-status response)  ;; -> 200
    (http:response-headers response) ;; -> header object
    (http:response-body response)    ;; -> body as bytevector
    ))

HTTP client

Returns #t if the given o is a HTTP client, otherwise #f.

Sends the given request via the client and returns http:response.

This procedure is synchronous procedure, so it blocks.

Sends the given request via the client and returns a future which returns http:response.

Shutdowns the given client. If the optional argument shutdown-executor? is specified to #f, then the underlying executor won't be shutdown.

If the underlying executor is the default executor, then it won't be shutdown, even if the optional argument is true value.

A constructor macro to build a HTTP client.

The _field_s must be one or more of the following:

follow-redirects

Specifies redirection strategy, the value must be a valid value of http:redirect.

cookie-handler

Specifies a cookie handler. Currently, http:make-default-cookie-handler is the only option.

connection-manager

Specifies a connection manager. See Connection Manager section for more detail.

version

Specifies a HTTP version. The value must be a valid value of http:version. The client handles both HTTP/1.1 and HTTP/2 by default.

executor

Specifies an executor. The the default executor has 5 threads, but it'd be shared by all the client created without this field, so if you want to use the client in a intense situation, it's a good idea to specify own executor.

A macro checks if the given value is a valid supporting HTTP version.

The value must be either http/1.1 or http/2. If the later one is specified, it first tries to connect with HTTP/2, and falls back to HTTP/1.1 if HTTP/2 is not avaiable.

HTTP/2 works only on TLS environment, as the client uses ALPN to detect the version.

A macro checks if the given value is a valid supporting redirect strategy.

The value must be one of never, always or normal. The default value is never.

never

Won't redirect, it is suitable if you want to handle 3xx result manually.

always

Redirects as long as the 3xx status is returned. This means insecure redirection may happen (i.e. HTTPS to HTTP)

normal

Redirects 3xx status if the scheme is the same or more secure.

HTTP request and response

Returns #t if the given o is an HTTP request object, otherwise #f.

Builds a HTTP request object.

The field must be one or more the followings.

uri

The URI of the request, it has to be an URI object of (net uri) or valid URI string. This field is mandatory.

method

A valid HTTP method. Default value is GET.

content-type

A content type header, this is used when the method is allowed to have body. Default value "application/octet-stream".

body

Content of the request. The value must be either a bytevector ot binary input port.

headers

A list of headers or a HTTP header object. If it's a list of header, then the element must contain a pair of name and values.

cookies

A list of cookies. The elements must be cookie object of (rfc cookie)

auth

An authentication provider. Must be a thunk providing the Authorization header value.

Returns #t if the given o is a HTTP headers object, otherwise #f.

Make a HTTP headers object.

A HTTP headers object can contain multiple values on one headers.

Retrieve a list of value of the header name from headers.

If the name doesn't exists, then it returns ().

Retrieve the first value of the header name from headers.

If the name doesn't exists, then it returns #f.

Sets the single value of value into the headers with header name of name.

Adds the value in the headers to the header value list of name.

If the name doesn't exist, then it works the same as http:headers-set!.

Returns a list of header names of the given headers

Returns #t if the given o is an HTTP response object, otherwise #f.

Returns the response HTTP status code.

The code is a string.

Returns the response HTTP headers object.

Returns a list of the response cookie, if exists.

The element of the list is a cookie object of (rfc cookie).

Returns the body of the response. The value is bytevector.

Authorization header value providers

Authorization header value providers can be used for auth field of the HTTP request.

Provides basic auth value provider of the given username and password.

Provides bearer auth value provider of the given token.

Connection Manager

A connection manager manages the connections of a HTTP client. By default, we support these three types of connection managers; ephemeral, pooling, and logging.

The ephemeral connection manager creates a connection per request and discards it. This connection manager should only be used in disposable scripts.

The pooling connection manager pools the created connection and try to reuse if possible.

Below example shows how to create a HTTP client with pooling connection manager.

(define pool-config
  (http-pooling-connection-config-builder
    (connection-timeout 1000)     ;; 1 sec, connection timeout
    (max-connection-per-route 20) ;; pooling connection number per route
    (read-timeout 3000)           ;; 3 sec, read timeout
    (dns-timeout 1000)            ;; 1 sec, DNS lookup timeout
    (time-to-live 120)            ;; 120 sec, expiration time of a connection
	))
(define http-client
  (http:client-builder
    (connection-manager (make-http-pooling-connection-manager pool-config))))

Creates a default connection manager. This is at this moment an ephemeral connection manager without any timeout or key configuration.

Ephemeral Connection Manager

Returns #t if the obj is an instance of http-connection-config, otherwise #f.

A constructor macro to build a http-connection-config record.

The _field_s must be one or more of the following:

connection-timeout

Specifies connection timeout in milli second.

read-timeout

Specifies read timeout in milli second.

key-manager

Specifies a key manager. See Key Manager section for more detail.

Returns #t if the obj is an ephemeral connection manager, otherwise #f.

Config must be a http-connection-config record instance.

Creates an ephemeral connection manager.

Pooling Connection Manager

Returns #t if the obj is an instance of http-pooling-connection-config, otherwise #f.

The http-pooling-connection-config record is a child record of http-connection-config.

A constructor macro to build a http-pooling-connection-configrecord.

The _field_s must be one or more of the following and the ones from http-connection-config-builder:

connection-request-timeout

Specifies connection request timeout in milli second. The timeout is only for the waiting time of the connection retrieval from the pool.

max-connection-per-route

Specifies pool size per route. A route is defined with the combination of hostname and port. Default value is 5.

time-to-live

Specifies the life time of the pooled connection in seconds

delegate-provider

Specifies connection manager delegate provider. Default value is default-delegate-connection-manager-provider

A delegate connection manager is an underlying connection manager of the pooling connection manager. The delegate creates and closes the actual connection.

Returns #t if the obj is a pooling connection manager, otherwise #f.

Config must be a http-pooling-connection-configrecord instance.

Creates a pooling connection manager.

Delegate Connection Manager providers

A delegate connection provider is a procedure which accepts one argument config and returns a connection manager.

Synonym of make-http-ephemeral-connection-manager.

Key Manager

Key manager manages client certificate of HTTP connections. A key manager may contain multiple of key providers. A key provider should provide a list whose the first element is a private key and the rest are certificate chain.

The following example shows how to make a key manager with multiple key providers.

(import (rnrs)
        (net http-client)
        (rfc base64)
        (security keystore))
(define (host-a p)
  (define node (socket-parameter-socket-node p))
  (cond ((string=? node "host-a.com") "host-a-key-alias")
        (else #f)))
(define (host-b p)
  (define node (socket-parameter-socket-node p))
  (and (string-suffix? ".host-b.com" node) "host-b-key-alias"))
(define keystores
  ;; keystore file (PKCS12 base64 encoded), store pass, key pass, alias selector
  `(("host-a.b64" "password0" "password0a" ,host-a)
    ("host-b.b64" "password1" "password1a" ,host-b)))

(define (->keystore-key-provider keystore-info)
  (let ((file (car keystore-info))
        (storepass (cadr keystore-info))
        (keypass (caddr keystore-info))
        (strategy (cadddr keystore-info)))
    (make-keystore-key-provider
     (call-with-input-file file
       (lambda (in)
         (let ((bin (open-base64-decode-input-port in)))
           (load-keystore 'pkcs12 bin storepass)))
       :transcoder #f)
     keypass
     strategy)))

(make-key-manager (map ->keystore-key-provider keystores))

Returns #t if the obj is a key manager, otherwise #f.

Key-providers must be a list of key provider.

Creates a key manager.

Key-provider must be a provider.

Creates a key manager.

Key Provider

Key provider provides keys. The key can be retrieved from anywhere but must be a format of a list of private key and certificate chain.

We provide keystore key provider by default. If you need other key provider, you need to create a custom one.

Record Type <key-provider>

An abstruct record type of key provider. Users must inherit this record type to create a custom key provider.

This record type has a filed named key-retrievers.

Returns #t if the obj is a key provider otherwise #f.

key-obtainer must be a procedure which receives one argument, socket-parameter.

Creates a key provider.

Returns the value of field key-retrievers of the key provider key-provider.

This procedure is not meant to be used by a user of HTTP client.

Returns #t if the obj is a keystore key provider otherwise #f.

Keystore must be a keystore object of (security keystore). password must be a string of valid key password. alias-provider must be a procedure which accepts one argument, socket parameter, and returns either string of key alias or #f.

Creates a key provider with one key retriever.

Add a key retriever to the keystore-key-provider and returns keystore-key-provider.

This procedure is convenient if you have multiple keys in one keystore.

Socket parameter

Socket parameter is used to determine which private key to be used. The object contains basic socket information.

Returns #t if the given obj is a socket parameter, otherwise #f.

Returns hostname, ip-address, node and service respectively.

The first 2 values are peer information, the latter 2 are local information.