webserver - Web/HTTP(S) Server for R
RForge.net

webserver

About webserver
GIT access
Download/Files
News
Check results
Package R docs

News/Changelog

1.0-0
   o    webstart() accepts connections on one or more listeners
        specified by listen=, each a port number (local HTTP),
        "http://<host>:<port>", "https://<host>:<port>" or "unix:<path>"
        (local socket, unix only). <host> can be "localhost" (local
        connections only), "*" (all IPv4 interfaces), a numeric IPv4
        address or an IPv6 address in [] (e.g., "[::1]" or "[::]").
        IPv6 listeners only accept IPv6 connections on all systems, so
        "https://*" and "https://[::]" together serve both. simple()
        passes further arguments (such as threads) on to webstart().

   o    TLS/SSL (HTTPS) support. Listeners using "https://" require a
        server certificate and its private key (PEM format) specified
        with tls.cert and tls.key. The key defaults to tls.cert, so a
        single file with both is sufficient. The minimal configuration
        is

          webstart("https://*:8443", tls.cert="server.crt",
                   tls.key="server.key")

        If the certificate was issued by an intermediate CA, its
        certificate(s) must be sent along with the server certificate:
        either append them to the tls.cert file (after the server
        certificate) or specify a separate file with tls.ca.

        HTTP and HTTPS listeners can be combined, e.g., to serve local
        clients without encryption:

          webstart(c(8080, "https://*:8443"), tls.cert="server.pem")

        The tls.* arguments apply to all HTTPS listeners, but can also
        have one value per HTTPS listener, e.g., to use different
        certificates on different ports.

        Clients can be required to authenticate with a certificate:
        tls.client.ca specifies the CA certificate(s) the client
        certificates must be issued by, connections without a valid
        certificate are rejected. tls.client.cn further restricts the
        allowed common names of the client certificates, a name can
        start or end with * to match a suffix or a prefix:

          webstart("https://*:8443", tls.cert="server.pem",
                   tls.client.ca="corp-ca.pem",
                   tls.client.cn=c("alice", "*.corp.example.com"))

        The client CA should be dedicated to issuing client certificates
        (e.g., the organisation's own CA), since every certificate it
        issued is accepted unless tls.client.cn is used.

        TLS 1.2 or higher is used, encrypted private keys are not
        supported. TLS requires OpenSSL 1.1.0 or higher at build time,
        hasTLS() reports whether TLS is supported.

   o    R handlers receive the headers Request-Proto (http or https,
        depending on the listener) and, if the client presented a valid
        certificate, Request-Client-CN with its common name, so handlers
        can identify clients. Header names starting with Request- are
        reserved for the server, such headers sent by the client
        (including the already present Request-Method) are dropped.

   o    R handlers can decode the request body: addHandler("rfun", ...)
        has a parse.body argument which is either FALSE (default, raw
        body), TRUE (use defaultBodyParsers()) or a named list of
        parsers function(body, content.type) where the names are media
        types, optionally starting or ending with * to match a suffix
        or prefix (e.g., "*+json" or "text/*"). The default
        parsers decode URL encoded forms into a named character vector
        (like the query) and JSON (using jsonlite). If the
        body cannot be parsed, the request is answered with 400 Bad
        Request without calling the handler, e.g.,

          addHandler("rfun", "/api", FUN, parse.body=TRUE)

        simple() uses parse.body=TRUE by default, so its R handler
        receives decoded form and JSON bodies (parse.body=FALSE passes
        the raw body).

   o    folded header lines (obsolete since HTTP/1.1) are rejected with
        400 Bad Request.

   o    TLS support was never enabled on Windows (wrong macro in the
        Windows configuration) and configure enabled it even when no
        OpenSSL was found.

   o    if a listener cannot be started, the error now includes the
        reason (e.g., address already in use).

   o    an existing file at the path of a unix socket is no longer
        removed unless it is a socket.

   o    forked children (fork=TRUE) no longer try to re-seed the
        system RNG (the code was never active). They inherit the R RNG
        state of the parent, see ?webstart for how to get independent
        random streams.

   o    forked children now exit with _exit() and stdio is flushed
        before fork(). Previously a child could emit output buffered
        by the parent again or, when run by Rscript, make the parent
        continue reading its script from the wrong position.

   o    use withVisible() instead of the non-API R_Visible in
        R >= 4.6.0.

   o    support chunked request bodies (Transfer-Encoding: chunked).
        The chunks are collected into the request body, so handlers
        see the same as with Content-Length. Other transfer codings
        are still answered with 501, Transfer-Encoding together with
        Content-Length, in HTTP/1.0 or with GET/HEAD with 400.

   o    reject header fields with whitespace between the name and the
        colon with 400 (RFC 9112, 5.1). Previously such Content-Length
        or Transfer-Encoding fields were ignored, so the body was parsed
        as the next request (request smuggling).

   o    1xx, 204 and 304 responses no longer include a body or
        Content-Length, which broke the framing of keep-alive
        connections.

   o    reject requests with more than one Host: header with 400
        (RFC 9112, 3.2).

   o    Connection: is parsed as a list of tokens, so e.g.
        "Connection: keep-alive, close" closes the connection.

   o    HTTP/1.1 responses include Connection: close if the server
        will close the connection (RFC 9112, 9.6).

   o    fix a crash when the header buffer cannot be allocated.

   o    R handlers can close the connection by including
        Connection: close in their headers.

   o    R handlers evaluated on processing threads (threads > 0) now
        have working C stack checks using the stack of the thread.
        Previously the checks were disabled, so runaway recursion
        could crash the server instead of raising an R error.

   o    fix compilation with the UCRT headers of Rtools 4.x
        (redefinition of timespec_get()).

   o    Windows: fix a possible crash when creating the internal
        socket pair fails (bad format string in the error message).

   o    fix compilation on Linux with gcc 15 (implicit declaration
        of pthread_setname_np()).

   o    Windows: fix a possible crash with threads > 0 where the
        server loop checked for user interrupts while a processing
        thread was evaluating R.