Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- -- An example HTTP server written in Konjac
- module Rum.Request
- struct [
- method: String;
- path: String;
- headers: Map(String, String);
- ]
- end
- module Rum.Response
- struct [
- statusCode: Int64 = 200;
- headers: Map(String, String) = {};
- body: Binary = Binary { };
- ]
- export function encode(response : Rum.Response) : Binary
- reasonPhrase : String = case response.statusCode
- when 200, do: "OK"
- when 201, do: "Created"
- when 301, do: "Moved Permanently"
- when 400, do: "Bad Request"
- when 404, do: "Not Found"
- when 500, do: "Internal Server Error"
- else do: "Unknown"
- end
- statusLine : String = "HTTP/1.1 " + Int64.toString(response.statusCode) + " " + reasonPhrase + "\r\n"
- updatedHeaders : Map(String, String) = if Map.hasKey(response.headers, "Content-Length")
- response.headers
- else
- Map.put(response.headers, "Content-Length", String.fromInt(Binary.length(response.body)))
- end
- headersString : String = updatedHeaders
- |> Map.toList()
- |> Array.map(function(pair : {String, String}) do
- pair.key + ": " + pair.value + "\r\n"
- end)
- |> String.join()
- |> String.concatenate("\r\n\r\n")
- statusLine
- |> String.concatenate(headersString)
- |> Binary.fromString()
- |> Binary.concatenate(response.body)
- end
- end
- module Rum.Context
- struct [
- request: Rum.Request;
- response: Rum.Response;
- ]
- end
- behaviour Rum.Handler
- abstract function call(handler : Rum.Handler, context : Rum.Context) : Rum.Context
- end
- module Rum.Server
- struct [
- host: String;
- port: UInt16;
- handlers: Array(Rum.Handler);
- ]
- function handleClient(server : Rum.Server, client : TCP.Client) : Nil
- data : Binary = TCP.receive(client)
- [headerSection, messageBody] =
- data
- |> Binary.toString()
- |> String.split("\r\n\r\n")
- [startLine, ...unprocessedHeaders]
- headerSection
- |> String.split("\r\n")
- headers =
- unprocessedHeaders
- |> Array.map(function(header : String) do
- [key, value] = String.split(header)
- {key: value}
- end)
- |> Map.zip()
- [method, path, "HTTP/1.1"] = startLine |> String.split(" ") |> String.stripSuffix()
- context =
- Rum.Context {
- request: Rum.Request {
- method: method,
- path: path,
- headers: headers
- },
- response: Rum.Response { }
- }
- updatedContext =
- server.handlers
- |> Array.reduce(function(handler : Rum.Handler, accumulator : Rum.Context) do
- Rum.handler.call(handler, accumulator)
- end)
- encodedResponse = Rum.Response.encode(updatedContext.response)
- TCP.send(client, encodedResponse)
- end
- export function bind(server : Rum.Server) : Rum.Response
- loop do
- client : TCP.Client? = TCP.accept(server.host, server.port)
- if client do
- Process.spawn do
- handleClient(server, client)
- end
- else
- Process.killSelf()
- end
- end
- end
- end
- module Rum.Application
- export function main(arguments : Array(String)) : Nil
- server = Rum.Server { host: "127.0.0.1", port: 8080 }
- supervisor =
- Supervisor {
- strategy: "OneForOne",
- maximumRestarts: 5,
- restartWindow: 10
- }
- process = Process.spawn do
- Rum.Server.bind(server)
- end
- child = Child {
- id: "worker",
- process: process,
- restart: "Transiet",
- maxRestarts: 3,
- restartWindow: 5
- }
- Supervisor.addChild(supervisor, child)
- end
- end
Advertisement