{"id":27391424,"url":"https://github.com/krios2146/erg","last_synced_at":"2025-09-06T14:43:36.918Z","repository":{"id":257896045,"uuid":"871674035","full_name":"krios2146/erg","owner":"krios2146","description":"Erg is a library that implements part of the HTTP/1.1 standard from scratch, offering a lightweight API for clients","archived":false,"fork":false,"pushed_at":"2024-11-17T09:24:56.000Z","size":70,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-04-13T20:45:00.499Z","etag":null,"topics":["http","http-server"],"latest_commit_sha":null,"homepage":"","language":"OCaml","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/krios2146.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2024-10-12T16:11:12.000Z","updated_at":"2024-11-17T09:25:00.000Z","dependencies_parsed_at":"2024-11-07T20:32:22.043Z","dependency_job_id":null,"html_url":"https://github.com/krios2146/erg","commit_stats":null,"previous_names":["krios2146/erg"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/krios2146%2Ferg","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/krios2146%2Ferg/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/krios2146%2Ferg/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/krios2146%2Ferg/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/krios2146","download_url":"https://codeload.github.com/krios2146/erg/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248782277,"owners_count":21160716,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["http","http-server"],"created_at":"2025-04-13T20:45:01.548Z","updated_at":"2025-04-13T20:45:02.238Z","avatar_url":"https://github.com/krios2146.png","language":"OCaml","readme":"# Erg\n\n\u003e Erg - vast area of shifting sand dunes within a desert, also called a sand sea. Ergs are found in places like the Sahara Desert\n\nLibrary that implements part of the [HTTP/1.1 standard](https://datatracker.ietf.org/doc/html/rfc2616) from scratch with practically zero dependencies, offering a lightweight API for clients\n\n![wakatime](https://wakatime.com/badge/user/465e62bb-2db9-4043-9075-8cefadda6d94/project/71533279-e67b-4534-a090-2d54dd788e61.svg)\n\n\u003e [!WARNING]  \n\u003e This project was built to learn OCaml and HTTP, it literally has no tests\n\u003e \n\u003e **Do not use it in any real software**\n\n## Features\n\n- Persistent TCP connections\n- Multithreading\n- Simple routing\n\n## Installation\n\nLibrary is not distributed via [opam](https://opam.ocaml.org/) deliberately\n\n1. This is a learning project, it barely provides any value to anyone, but me\n2. I wouldn't maintain it\n3. Erg is a cool name and I don't want to take it\n\n---\n\nInstead of installing it with opam you'll need to do it manually\n\nAssuming you created have some [dune](https://dune.build/) project, all you need to do is clone the erg to `lib/erg` like so\n\n```bash\ngit clone git@github.com:krios2146/erg.git lib/erg\n```\n\nThen just add it to the dune file under the libraries stanza like so\n\n```\n(executable\n (public_name your_project_name)\n (name main)\n (libraries erg))\n```\n\nYou can access `Erg` module in your code now\n\n## Example\n\nSimple example that shows most of the Erg features:\n\n```ocaml\n(* Define function that transform HTTP request to HTTP resposne *)\nlet process_hello req = \n  (* Read query parameter `name` from the URL *)\n  let name =\n    match Erg.Http_request.get_param req \"name\" with\n    | None -\u003e \"World\"\n    | Some n -\u003e n\n  in\n  Erg.Http_response.empty\n  |\u003e Erg.Http_response.set_status_code Erg.Status_code.OK\n  |\u003e Erg.Http_response.set_header (Erg.Http_header.ContentType \"text/plain\")\n  (* Create response body based on the `name` parameter *)\n  |\u003e Erg.Http_response.set_response_body (\"Hello, \" ^ name ^ \"!\")\n;;\n\n(* Create handler for GET request on the `/hello` URL *)\nlet hello_handler = Erg.create_handler Erg.Http_method.Get \"/hello\" process_hello in\n(* Add `hello_handler` to the Erg handlers *)\nlet handlers = \n  Erg.empty_handlers ()\n  |\u003e Erg.add_handler handler\nin\n(* Start Erg on the port 8080 *)\nErg.start 8080 handlers\n```\n\n## API Reference\n\nContents of the `Erg.mli`\n\n```ocaml\nmodule Http_method : sig\n  type t =\n    | Get\n    | Post\n    | Put\n    | Delete\nend\n\nmodule Http_header : sig\n  type t =\n    (* General Headers *)\n    | CacheControl of string\n    | Connection of string\n    | Date of string\n    | Pragma of string\n    | Trailer of string\n    | TransferEncoding of string\n    | Upgrade of string\n    | Via of string\n    | Warning of string\n    (* Request Headers *)\n    | Accept of string\n    | AcceptCharset of string\n    | AcceptEncoding of string\n    | AcceptLanguage of string\n    | Authorization of string\n    | Expect of string\n    | From of string\n    | Host of string\n    | IfMatch of string\n    | IfModifiedSince of string\n    | IfNoneMatch of string\n    | IfRange of string\n    | IfUnmodifiedSince of string\n    | MaxForwards of string\n    | ProxyAuthorization of string\n    | Range of string\n    | Referer of string\n    | TE of string\n    | UserAgent of string\n    (* Entity Headers *)\n    | Allow of string\n    | ContentEncoding of string\n    | ContentLanguage of string\n    | ContentLength of string\n    | ContentLocation of string\n    | ContentMD5 of string\n    | ContentRange of string\n    | ContentType of string\n    | Expires of string\n    | LastModified of string\nend\n\nmodule Status_code : sig\n  type t =\n    | Continue (** 100 *)\n    | Switching_Protocols (** 101 *)\n    | OK (** 200 *)\n    | Created (** 201 *)\n    | Accepted (** 202 *)\n    | Non_Authoritative_Information (** 203 *)\n    | No_Content (** 204 *)\n    | Reset_Content (** 205 *)\n    | Partial_Content (** 206 *)\n    | Multiple_Choices (** 300 *)\n    | Moved_Permanently (** 301 *)\n    | Found (** 302 *)\n    | See_Other (** 303 *)\n    | Not_Modified (** 304 *)\n    | Use_Proxy (** 305 *)\n    | Temporary_Redirect (** 307 *)\n    | Bad_Request (** 400 *)\n    | Unauthorized (** 401 *)\n    | Payment_Required (** 402 *)\n    | Forbidden (** 403 *)\n    | Not_Found (** 404 *)\n    | Method_Not_Allowed (** 405 *)\n    | Not_Acceptable (** 406 *)\n    | Proxy_Authentication_Required (** 407 *)\n    | Request_Timeout (** 408 *)\n    | Conflict (** 409 *)\n    | Gone (** 410 *)\n    | Length_Required (** 411 *)\n    | Precondition_Failed (** 412 *)\n    | Request_Entity_Too_Large (** 413 *)\n    | Request_URI_Too_Long (** 414 *)\n    | Unsupported_Media_Type (** 415 *)\n    | Requested_Range_Not_Satisfiable (** 416 *)\n    | Expectation_Failed (** 417 *)\n    | Internal_Server_Error (** 500 *)\n    | Not_Implemented (** 501 *)\n    | Bad_Gateway (** 502 *)\n    | Service_Unavailable (** 503 *)\n    | Gateway_Timeout (** 504 *)\n    | HTTP_Version_Not_Supported (** 505 *)\nend\n\nmodule Http_response : sig\n  type t\n\n  (** [empty] Returns \"empty\" HTTP response that must be filled with at least status code *)\n  val empty : t\n\n  (** [set_headers res h_list] Sets specified headers to the response, returns response with headers *)\n  val set_headers : Http_header.t list -\u003e t -\u003e t\n\n  (** [set_header res h] Sets specified header to the response, returns response with header *)\n  val set_header : Http_header.t -\u003e t -\u003e t\n\n  (** [set_response_body res body] Sets response body to the response, returns response with a body *)\n  val set_response_body : string -\u003e t -\u003e t\n\n  (** [set_status_code res code] Sets status code for the response, returns response with specified status code *)\n  val set_status_code : Status_code.t -\u003e t -\u003e t\nend\n\nmodule Http_request : sig\n  type t\n\n  (** [get_param req param] Retrieves the optional GET parameter from the request's query *)\n  val get_param : t -\u003e string -\u003e string option\n\n  (** [get_headers req] Retrieves all headers from the request *)\n  val get_headers : t -\u003e Http_header.t list\n\n  (** [get_body req] Retrieves untrimmed body of the request as a string *)\n  val get_body : t -\u003e string\nend\n\ntype handler\ntype handlers\n\n(** [empty_handlers] Returns empty handlers that should be filled with handlers with [add_handler] *)\nval empty_handlers : unit -\u003e handlers\n\n(** [add_handler h handlers] Adds the specified handler to the handlers *)\nval add_handler : handler -\u003e handlers -\u003e handlers\n\n(** [create_handler m uri req -\u003e res]\n\n    Creates the [handler] for the specified HTTP method on the [uri]\n    with function that transforms [http_request] to [http_response] *)\nval create_handler\n  :  Http_method.t\n  -\u003e string\n  -\u003e (Http_request.t -\u003e Http_response.t)\n  -\u003e handler\n\n(** [start port handlers] Starts the server listening on the specified port with specified handlers *)\nval start : int -\u003e handlers -\u003e unit\n```\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkrios2146%2Ferg","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fkrios2146%2Ferg","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkrios2146%2Ferg/lists"}