# \[ANN\] Shuttle 0.9.1 released

**URL:** <https://discuss.ocaml.org/t/ann-shuttle-0-9-1-released/11292>\
**Category:** Community\
**Tags:** announce\
**Created:** [February 2, 2023, 2:59am UTC](https://discuss.ocaml.org/t/ann-shuttle-0-9-1-released/11292 "2023-02-02T02:59:21Z")\
**Posts on this page:** 2\
**Page:** 1

<div class="post-metadata">

**Author:** ![anuragsoni](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/anuragsoni/32/1107_2.png) [@anuragsoni](https://discuss.ocaml.org/u/anuragsoni)\
**Post date:** [February 2, 2023, 2:59am UTC](https://discuss.ocaml.org/t/ann-shuttle-0-9-1-released/11292/1 "2023-02-02T02:59:21Z")

</div>

Hi,

I’d like to announce a new point release (0.9.1) for `shuttle` and its companion libraries. They are available to install via opam:

```auto
opam install shuttle shuttle_ssl shuttle_http

```

The code is hosted on [github](https://github.com/anuragsoni/shuttle), and the documentation can be seen online on [ocaml’s package registry](https://ocaml.org/p/shuttle_http/0.9.1/doc/index.html).

**Shuttle** is a small library that is a wrapper around file descriptors that provides an API for buffered channels using [async](https://opensource.janestreet.com/async/).

**Shuttle\_ssl** provides ssl support for `shuttle` and is built on top of `async_ssl` (async bindings for OpenSSL).

**Shuttle\_http** is a library that implements to help write HTTP/1.1 servers and clients.

Shuttle\_http is the library that has seen the most changes in this release:

- Improved streaming response body handling. The library will reliably schedule a cleanup action that will run if the underlying socket is closed before the entire response body was consumed.
- Support for one-shot HTTP/1.1 clients. These don’t support keep-alives and the underlying socket will be closed after one request → response cycle.
- Support for HTTP/1.1 clients that support keep-alives. Client connection will be kept open if both client and server indicate that the connection supports keep-alive. This allows the same connection to be re-used for multiple request → response cycles. The connection object ensures that outgoing requests are serialized to respect that HTTP/1.1 doesn’t support multiplexing.
- Support for persistent HTTP clients. Not to be confused with `HTTP persistent connection`. Persistent in this case refers to durable clients that will always hand the user an open connection, and attempts to reconnect if the underlying connection is lost. This leverages Async’s persistent module to provide an HTTP flavored persistent connection.

# Uses and examples

**A hello world http server**

```ocaml
open! Core
open Async
open Shuttle_http

let hello_world (address : Socket.Address.Inet.t) (request : Request.t) =
  Log.Global.info !"%{sexp: Socket.Address.Inet.t} - %s" address (Request.path request);
  return (Response.create ~body:(Body.string "Hello World") `Ok)
;;

```

**An example of a http handler that responds with a streaming body**

```ocaml
open! Core
open Async
open Shuttle_http

let my_service (address : Socket.Address.Inet.t) (request : Request.t) =
  let%map reader =
    (* This an example to show a stream that works with an external resource. *)
    Reader.open_file "<some file path>"
  in
  (* Create a pipe from the reader that we will use as a streaming response body. *)
  let reader_pipe = Reader.pipe reader in
  (* Create a response from the reader's pipe. If the server is closed before the full
     response was served, the pipe will be closed which in-turn will close the reader and
     the underlying file descriptor. *)
  Response.create ~body:(Body.of_pipe `Chunked reader_pipe) `Ok
;;

```

**A one-shot http client**

```ocaml
let run () =
  let address =
    Client.Address.of_host_and_port (Host_and_port.create ~host:"httpbin.org" ~port:443)
  in
  Client.Oneshot.call ~ssl:(Client.Ssl.create ()) address (Request.create `GET "/get")
;;

```

**Client supporting keep-alive**

```ocaml
let run () =
  let stdout = Lazy.force Writer.stdout in
  let%bind httpbin =
    Deferred.Or_error.ok_exn
      (Client.create
         ~ssl:(Client.Ssl.create ())
         (Client.Address.of_host_and_port
            (Host_and_port.create ~host:"httpbin.org" ~port:443)))
  in
  Monitor.protect
    ~finally:(fun () -> Client.close httpbin)
    (fun () ->
      let%bind response = Client.call httpbin (Request.create `GET "/stream/20") in
      Log.Global.info !"Headers: %{sexp: Headers.t}" (Response.headers response);
      let log_body response =
        Body.Stream.iter
          (Body.to_stream (Response.body response))
          ~f:(fun chunk ->
            Writer.write stdout chunk;
            Writer.flushed stdout)
      in
      let%bind () = log_body response in
      let%bind response = Client.call httpbin (Request.create `GET "/get") in
      Log.Global.info !"Headers: %{sexp: Headers.t}" (Response.headers response);
      log_body response)
;;

```

---

<div class="post-metadata">

**Author:** ![anuragsoni](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/anuragsoni/32/1107_2.png) [@anuragsoni](https://discuss.ocaml.org/u/anuragsoni)\
**Post date:** [August 9, 2023, 1:17am UTC](https://discuss.ocaml.org/t/ann-shuttle-0-9-1-released/11292/2 "2023-08-09T01:17:49Z")

</div>

Some new updates since the last release:

- `shuttle_http` now supports HTTP/1.1 servers that use `async_ssl` based encrypted connections.
- A server context is forwarded to http services. This context can be used to lookup peer client’s address, check if the http service is running on a SSL encrypted server, and if SSL is used lookup peer client’s SSL certificates.
- HTTP servers support web socket upgrades now. The implementation is based on Janestreet’s web socket library ([GitHub - janestreet/async\_websocket: A library that implements the websocket protocol on top of Async](https://github.com/janestreet/async_websocket)), and shuttle has a companion library `shuttle_websocket` that provides the web socket upgrade negotiation for servers, and allows converting a web socket handler to a `request -> response promise` based http service that can be used by `shuttle_http`.

Example for a http service that serves web socket traffic on some requests:

```ocaml
open! Core
open! Async
open Shuttle_http

let websocket_handler =
  Shuttle_websocket.create (fun ws ->
    let rd, wr = Websocket.pipes ws in
    Pipe.transfer_id rd wr)
;;

let service context request =
  Log.Global.info "Peer address: %s" (Socket.Address.to_string (Server.peer_addr context));
  match Request.path request with
  | "/websocket"-> websocket_handler request
  | "/" -> return (Response.create ~body:(Body.string "Hello World") `Ok)
  | _ -> return (Response.create `Not_found)
;;

```

The latest release has been published to the opam package repository, and can be installed via opam:

```auto
opam install shuttle_http
opam install shuttle_websocket

```

- Git repository: [~soni/shuttle\_http - Asynchronous HTTP server and client implementation for OCaml - sourcehut git](https://git.sr.ht/~soni/shuttle_http)
