immutant.web

Serve web requests using Ring handlers, Servlets, or Undertow HttpHandlers

run

(run handler & options)

Runs handler with the given options.

handler can be a Ring handler function, a Servlet, or an Undertow HttpHandler. Can be called multiple times - if given the same options, any prior handler with those options will be replaced. Returns the given options with any missing defaults filled in.

options can be a map or kwargs, with these valid keys [default]:

  • :host The interface bind address [“localhost”]
  • :port The port listening for requests [8080]
  • :path Maps the handler to a prefix of the url path [“/”]
  • :virtual-host Virtual host name[s] (a String or a List of Strings) [nil]
  • :dispatch? Invoke handlers in worker thread pool [true]

When handler is a Servlet, the following options are also supported:

  • :servlet-name The servlet’s registered name [the :path]
  • :filter-map An insertion-order-preserving mapping, e.g. array-map or LinkedHashMap, of names to Filter instances [nil]

Note the web server only binds to the loopback interface, by default. To expose your handler to the network, set :host to an external IP address, or use “0.0.0.0” to bind it to all interfaces.

The :virtual-host option enables name-based virtual hosting which, along with the :path option, distinguishes the handlers on a single server. That is, multiple handlers can run on the same :host and :port as long as each has a unique combination of :virtual-host and :path.

Run calls may be threaded together:

(-> (run ello) (assoc :path "/owdy") (->> (run owdy)) (merge {:path "/" :port 8081}) (->> (run ola)))

The above actually creates two web server instances, one listening for ello and owdy requests on port 8080, and another listening for ola requests on 8081.

For ring handlers, the actual writing of the response happens after your hander returns. If an exception occurs on the write (the most common case being an IOException because the client has gone away), the default behavior is to log the exception. If you would like to be able to handle that exception yourself, you can return a function in the ring response under :write-error-handler. This function will be called with the exception, the request map, and the response map if an exception occurs when writing the response. Note that this handler can’t actually affect the response. If you would prefer a global handler, see immutant.web.middleware/wrap-write-error-handling.

The underlying web server for Immutant is Undertow, which supports more advanced options than the above. These can be configured by passing an Undertow$Builder via the :configuration option, an instance of which is easily constructed from a map of valid keywords using the immutant.web.undertow/options function. For convenience, all of its option keywords are valid for run, too: if present, an Undertow$Builder will be returned in the result.

If your handlers are compute-bound, you may be able to gain some performance by setting :dispatch? to false. This causes the handlers to run on Undertow’s I/O threads, avoiding the context switch of dispatching them to the worker thread pool, at the risk of refusing client requests under load. Note that when :dispatch? is false, returning a seq, File, or InputStream as a ring body will cause that request to be dispatched to a worker thread at write time to prevent blocking an I/O thread.

Inside WildFly, the :host, :port, :configuration, and :dispatch? options are ignored, since all handlers are mounted as servlets contained within WildFly’s own Undertow instance. Further, all invocations of run must be within the initialization function for your application, i.e. your -main.

run-dmc

macro

(run-dmc handler & options)

Run in Development Mode (the ‘C’ is silent).

This macro invokes run after ensuring the passed handler is var-quoted, with reload and stacktrace middleware applied, and then opens the app in a browser. Supports the same options as run.

server

(server & options)

Returns the web server instance associated with a particular set of options, typically the map returned from a run call. The web server provides start, stop and isRunning methods, allowing you to, for example, temporarily stop serving requests for all the handlers running on a particular server.

  (let [srv (server (run hello :auto-start false))]
    (.isRunning srv)   ;=> false
    (.start srv)
    (.isRunning srv)   ;=> true
    (.stop srv))

The return value is either a single server instance or a list of servers if passed the result from threaded run calls that would cause multiple servers to be created.

stop

(stop & options)

Stops a running handler.

options can be passed as a map or kwargs, but is typically the map returned from a run call. If that return value is not available, you can pass the same options map passed to run for the handler you want to stop. If options isn’t provided, the handler at the root context path (“/”) of the default server will be stopped. If there are no handlers remaining on the server, the server itself is stopped. Returns true if a handler was actually removed.