Skip to content

sikanhe/Spaceship

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

16 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Spaceship

Lightweight Reason http server framework

type context = {userId: option(string)};

module Server = Spaceship.Make(Adapters.NodeHttp);

let handler: Server.handler(context) =
  (conn, ctx) =>
    switch (conn, ctx) {
    | ({method: `GET, path: []}, _ctx) =>
      Server.sendResp(conn, `Text("Hello World"))
    | ({method: `POST, path: ["data"], reqBody: Fetched(data)}, _ctx) =>
      conn
      ->Conn.setStatus(Ok)
      ->Server.sendResp(`Html("Received data: " ++ data ++ ""))

    | ({method: `PUT}, {userId: None}) =>
      conn
      ->Conn.setStatus(Forbidden)
      ->Server.sendResp(`Text("Not logged in"))
    | _ =>
      conn
      ->Conn.setStatus(NotFound)
      ->Server.sendResp(`Text("Page not found"))
    };

/* Middlewares */

[@bs.val] [@bs.scope "process"] external hrtime: unit => (int, int) = "";

let requestLogger = (next, conn, ctx) => {
  Js.log(Method.toStr(conn.Conn.method) ++ " " ++ conn.url);
  let (s1, ns1) = hrtime();

  conn
  ->Conn.registerBeforeSend(conn => {
      let (s2, ns2) = hrtime();
      let (sd, nd): (int, int) = {
        let nsDiff = ns2 - ns1;
        let sDiff = s2 - s1;
        if (nsDiff < 0) {
          (sDiff - 1, nsDiff + int_of_float(1e9));
        } else {
          (sDiff, nsDiff);
        };
      };

      let diffNano = sd * int_of_float(1e9) + nd;
      let diffMicro = diffNano / 1000;
      let diffMilli = diffMicro / 1000;

      let diffStr =
        diffMilli > 1 ?
          string_of_int(diffMilli) ++ "ms" :
          string_of_int(diffMicro) ++ {j|µs|j};

      Js.log("Sent " ++ string_of_int(conn.statusCode) ++ " in " ++ diffStr);
      conn;
    })
  ->next(ctx);
};

let fetchBody = (next, conn, ctx) =>
  Server.fetchBody(conn, body =>
    next({...conn, reqBody: Fetched(body)}, ctx)
  );

/* Simply compose on top of request handler */
let handler' = requestLogger @@ fetchBody @@ handler;

Server.start(handler', ~port=4000, ~createContext=() => {userId: None});

About

Lightweight Reason http server framework

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages