# Cohttp-eio
Note: `Cohttp` is the proper module name and `cohttp` is the opam package/library.
All further changes to be made in this PR.
----
---
author: Bikal Gurung
title: "Cohttp-eio in OCaml 5"
kind: article
image: ../images/cohttp.jpg
date: "2023-01-17"
---
`cohttp-eio` is a HTTP/1.1 based web programming library for OCaml 5.0 and onwards. It is designed from the ground up to benefit from OCaml 5's headline feature - domains-based parallelism - and `eio,` an effects-based I/O concurrency library.
One notable feature of the library is the absence of an I/O (Input/Output) monad in its API. Due to this, the ergonomics of the API matches that of the OCaml `stdlib`. Both seasoned and beginner OCaml developers will find that the API is inviting, approachable, and productive.
## Installing the `cohttp-eio` Package
`cohttp-eio` needs a working opam environment and an OCaml 5.0 compiler. The OCaml 5.0 compiler can be installed in a working opam environment as such:
```
opam update
opam switch create 5.0.0
```
The current released version of `cohttp-eio` is `alpha0`. It can be installed as follows:
`opam install cohttp-eio.6.0.0~alpha0`
An OCaml executable program using `cohttp-eio` then declares the dependencies as such:
```
$ cat dune
(executable
(name hello_world)
(libraries cohttp-eio eio eio_main))
```
## `cohttp-eio` API
`cohttp-eio` provides modules `Server` and `Client` under the `Cohttp_eio` module. They implement an HTTP/1.1 server and client functionality, respectively.
For the sake of brevity, assume that there is an `open Cohttp_eio` statement in the code fragments presented below and throughout the rest of the article.
### `Server.handler`
`Server.handler` is an OCaml function which expects a HTTP/1.1 `Server.request` and produces a HTTP/1.1 `Server.response`. It is formally defined as:
```
type handler = Server.request -> Server.response
```
`cohttp-eio` provides a few convenient functions that can be used in a handler. These functions encapsulate adding/creating correct HTTP/1.1 response headers and bodies. A couple of these are as follows:
`Server.text_response`, used to respond with plain text response in a handler.
`Server.html_response`, used to respond with a HTML response in a handler.
### `Server.run`
`Server.run` runs HTTP/1.1 server configured to execute a given handler. Optionally, we can specify the number of domains the server can use via the `~domains` parameter.
Domain is a unit of parallelism in OCaml 5.0 and beyond. Semantically, it roughly corresponds to a CPU core in a computer. Though there is no hard, upper limit to number of domains, it is generally recommended that `~domains` matches the total number of CPU cores in the machine. The default value of `domains` is 1.
Lastly, we specify the TCP/IP port of the listening server. A typical usage of `Server.run` looks like below:
```
let () =
Eio_main.run @@ fun env ->
Server.run ~domains:12 ~port:8080 env handler
```
### Hello World Server
A small demonstration of what a `cohttp-eio` server looks like is as follows:
```
$ cat hello_world.ml
open Cohttp_eio
let app : Server.handler =
fun ((req, _,_) : Server.request) ->
match Http.Request.resource req with
| "/" -> Server.text_response "Hello world!"
| "/html" -> Server.html_response "<h1>Hello world!</h1>"
| _ -> Server.not_found_response
let () =
Eio_main.run @@ fun env ->
Server.run ~port:8080 env app
```
`hello_world.ml` can be built with the `dune` file excerpt given above. A terminal shell session might look like this:
```
$ ls
dune
hello_world.ml
$ dune b && dune exec ./hello_world.exe
```
### Client
`cohttp-eio` provides a `Cohttp_eio.Client` module, which implements HTTP/1.1 client functionality. Similarly to `Cohttp_eio.Server`, a client sends an HTTP request and expects an HTTP response. Broadly, HTTP client executions are categorised into two types:
```
type 'a body_disallowed_call =
?pipeline_requests:bool ->
?version:Http.Version.t ->
?headers:Http.Header.t ->
conn:(#Eio.Flow.two_way as 'a) ->
host ->
resource_path ->
response
```
and
```
type 'a body_allowed_call =
?pipeline_requests:bool ->
?version:Http.Version.t ->
?headers:Http.Header.t ->
?body:Body.t ->
conn:(#Eio.Flow.two_way as 'a) ->
host ->
resource_path ->
response
```
The main difference between the two call types, as the names respectively suggest, are that the first doesn't allow for including a request `body` in the call, but the second one does allow it.
`Client.get/head/delete` are examples of the first, while `Client.post/put/patch` are examples of the second.
An example of a `Cohtto_eio.Client` usage is as follows:
```
open Cohttp_eio
let () =
let host, port = ("www.example.org", 80) in
Eio_main.run @@ fun env ->
Eio.Net.with_tcp_connect ~host ~service:(string_of_int port) env#net
(fun conn ->
let host = (host, Some port) in
let res = Client.get ~conn host "/" in
print_string @@ Client.read_fixed res)
```
## Summary
`cohttp-eio` aims to implement HTTP Servers and Clients which are compliant to [RFC 9110 - HTTP Semantics](https://www.rfc-editor.org/rfc/rfc9110#section-6.6.1) specification. Although not discussed in this article, this includes full HTTP chunk encoding support.