http_server

The http_server library provides the user-facing facade for starting and stopping HTTP and HTTPS servers. It selects a default transport from the scheme/1 option while still allowing explicit transport selection when an application needs lower-level control.

By default, scheme(http) uses http_socket_transport and scheme(https) uses http_process_transport (selecting a TLS listener). Incompatible scheme, transport, and listener transport combinations are rejected with a consistency_error/3 exception.

API documentation

Open the ../../apis/library_index.html#http_server link in a web browser.

Loading

To load all entities in this library, load the loader.lgt file:

| ?- logtalk_load(http_server(loader)).

Testing

To test this library predicates, load the tester.lgt file:

| ?- logtalk_load(http_server(tester)).

Bounded serving

To serve a given number of connections, use the serve/4 predicate. For example:

| ?- http_server::serve(8080, my_handler, 10, [scheme(http)]).

To inspect or reuse a listener, open it explicitly and close it after serving:

| ?- http_server::open('127.0.0.1', Port, Server, []),
     http_server::serve(Server, my_handler, 1, ClientInfos),
     http_server::close(Server).

Open-ended serving

To serve any number of connections until shutdown, use the serve_until_shutdown/5 predicate. For example:

| ?- http_server::serve_until_shutdown('127.0.0.1', 8080, my_handler, control, []).
...

| ?- http_server::request_shutdown(control).
...

When the Prolog backend supports threads, you can also use the start/4-5 and stop/1 predicates. For example:

| ?- http_server::start(8080, my_handler, Server, []),
     http_server::stop(Server).

HTTPS

For HTTPS, the server must have TLS credentials. The facade selects http_process_transport and a TLS listener when scheme(https) is used, but the transport still needs either explicit certificate and key files or a request to create temporary credentials.

Use tls_certificate_file/1 and tls_key_file/1 for real deployments:

| ?- http_server::serve(
        '127.0.0.1', 8443, my_handler, 10, _ClientInfos,
        [
            scheme(https),
            tls_certificate_file('/path/to/cert.pem'),
            tls_key_file('/path/to/key.pem')
        ]
     ).

Use temporary_tls_credentials/1 for local examples and tests. Its argument is a file name prefix used for temporary certificate and key files. The temporary files are created by the process transport and removed when the listener is closed:

| ?- http_server::serve(
        '127.0.0.1', 8443, my_handler, 10, _ClientInfos,
        [scheme(https), temporary_tls_credentials('logtalk_http_server_')]
     ).

If scheme(https) is used without either temporary_tls_credentials/1 or both tls_certificate_file/1 and tls_key_file/1, the process transport rejects the listener options.

Handling server requests

The handler argument in the examples above, my_handler, is the object that implements http_handler_protocol and receives each accepted HTTP request, building the corresponding HTTP response.

For ordinary HTTP requests, the handler is expected to provide a handle/2 predicate compatible with the http_server_core request/response pipeline. For example, a minimal handler can pattern-match the request and return a plain text response:

:- object(my_handler,
    implements(http_handler_protocol)).

    :- uses(http_core, [
        response/6
    ]).

    handle(Request, Response) :-
        Request = request(_Method, _Target, Version, _Headers, _Body, _Properties),
        response(
            Version, status(200, 'OK'), [],
            content('text/plain', text('Hello!')), [], Response
        ).

:- end_object.

When a server accepts a connection, the selected transport reads the request, calls my_handler::handle(Request, Response), writes the response back to the client, and then follows the selected serving policy. Parametric objects can be used when the handler needs configuration, e.g. static_site_handler(Root).

Options

The predicates that open or start a listener accept the following facade options:

  • scheme(Scheme) controls the URL scheme served by the listener. Valid values: http or https. Default: http.

  • transport(Transport) selects the transport object. Valid values: default or an object implementing http_transport_protocol. Default: default, which resolves to http_socket_transport for scheme(http) and to http_process_transport for scheme(https).

  • listener_options(Options) passes additional listener options directly to the selected transport. Default: [].

  • serve_options(Options) passes additional serving options directly to the selected transport. Default: [].

  • control(Control) names the shutdown control used by start/4-5 and open-ended serving. Valid values: any non-variable term, or default to create a fresh internal control term. Default: default.

For convenience, selected listener and serving options can also be written directly in the facade option list instead of wrapping them in listener_options/1 or serve_options/1:

  • Listener options: backlog/1, type/1, listener_transport/1, listener_helper_executable/1, temporary_tls_credentials/1, tls_certificate_file/1, and tls_key_file/1.

  • Serving options: workers/1 and shutdown/1.

The direct listener options accepted by the facade have the following values: backlog/1 takes a positive integer, type/1 takes binary or text, listener_transport/1 takes tcp or tls, listener_helper_executable/1 takes ncat or socat, and the TLS credential options take file names or a temporary file name prefix as atoms.

The direct serving options accepted by the facade are workers(serial), workers(per_connection), workers(pool(Size)), workers(pool(Size, rolling)), shutdown(keep_open), and shutdown(close).

These direct options are pass-through options. They are checked by the facade for basic shape, but the selected transport still decides whether a particular option is supported and what its transport-specific default is. For example, listener_transport(tls), listener_helper_executable/1, and the TLS credential options are options for the process transport. With scheme(https), the facade adds listener_transport(tls) automatically unless another listener transport is explicitly specified.

When the process transport is selected, these listener defaults apply: backlog(5), type(binary), listener_transport(tcp), and listener_helper_executable(ncat). The facade changes the effective listener transport to tls for scheme(https). The TLS credential options have no default usable certificate: temporary_tls_credentials/1 must be requested explicitly, or both tls_certificate_file/1 and tls_key_file/1 must be provided when opening a TLS listener.

Common serving defaults are inherited from the transports: workers(serial) and shutdown(keep_open). The convenience predicates that open and close a listener around a bounded request loop add shutdown(close) while serving.