{"id":13639044,"url":"https://github.com/Lightbug-HQ/lightbug_http","last_synced_at":"2025-04-19T21:35:25.119Z","repository":{"id":214856559,"uuid":"732793747","full_name":"saviorand/lightbug_http","owner":"saviorand","description":"Simple and fast HTTP framework for Mojo! 🔥","archived":false,"fork":false,"pushed_at":"2024-04-13T12:02:27.000Z","size":1035,"stargazers_count":230,"open_issues_count":10,"forks_count":16,"subscribers_count":7,"default_branch":"main","last_synced_at":"2024-04-14T05:44:29.966Z","etag":null,"topics":["api","client","http","mojo","server","web"],"latest_commit_sha":null,"homepage":"","language":"HTML","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/saviorand.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null}},"created_at":"2023-12-17T20:56:41.000Z","updated_at":"2024-04-16T18:41:10.909Z","dependencies_parsed_at":"2024-01-16T12:01:49.035Z","dependency_job_id":"15d6b34f-4efb-49f5-90dc-eb8dcacbd20c","html_url":"https://github.com/saviorand/lightbug_http","commit_stats":null,"previous_names":["saviorand/lightbug_http"],"tags_count":4,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/saviorand%2Flightbug_http","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/saviorand%2Flightbug_http/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/saviorand%2Flightbug_http/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/saviorand%2Flightbug_http/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/saviorand","download_url":"https://codeload.github.com/saviorand/lightbug_http/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":223810248,"owners_count":17206722,"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":["api","client","http","mojo","server","web"],"created_at":"2024-08-02T01:00:57.027Z","updated_at":"2025-04-19T21:35:25.103Z","avatar_url":"https://github.com/saviorand.png","language":"HTML","readme":"\u003ca name=\"readme-top\"\u003e\u003c/a\u003e\n\n\u003c!-- PROJECT LOGO --\u003e\n\u003cbr /\u003e\n\u003cdiv align=\"center\"\u003e\n    \u003cimg src=\"static/logo.png\" alt=\"Logo\" width=\"250\" height=\"250\"\u003e\n\n  \u003ch3 align=\"center\"\u003eLightbug\u003c/h3\u003e\n\n  \u003cp align=\"center\"\u003e\n    🐝 A Mojo HTTP framework with wings 🔥\n    \u003cbr/\u003e\n\n   ![Written in Mojo][language-shield]\n   [![MIT License][license-shield]][license-url]\n   ![Build status][build-shield]\n   \u003cbr/\u003e\n   [![Join our Discord][discord-shield]][discord-url]\n   [![Contributors Welcome][contributors-shield]][contributors-url]\n   \n\n  \u003c/p\u003e\n\u003c/div\u003e\n\n## Overview\n\nLightbug is a simple and sweet HTTP framework for Mojo that builds on best practice from systems programming, such as the Golang [FastHTTP](https://github.com/valyala/fasthttp/) and Rust [may_minihttp](https://github.com/Xudong-Huang/may_minihttp/). \n\nThis is not production ready yet. We're aiming to keep up with new developments in Mojo, but it might take some time to get to a point when this is safe to use in real-world applications.\n\nLightbug currently has the following features:\n - [x] Pure Mojo! No Python dependencies. Everything is fully typed, with no `def` functions used\n - [x] HTTP Server and Client implementations\n - [x] TCP and UDP support\n - [x] Cookie support\n\n ### Check Out These Mojo Libraries:\n\n- Logging - [@toasty/stump](https://github.com/thatstoasty/stump)\n- CLI and Terminal - [@toasty/prism](https://github.com/thatstoasty/prism), [@toasty/mog](https://github.com/thatstoasty/mog)\n- Date/Time - [@mojoto/morrow](https://github.com/mojoto/morrow.mojo) and [@toasty/small_time](https://github.com/thatstoasty/small_time)\n\n\u003cp align=\"right\"\u003e(\u003ca href=\"#readme-top\"\u003eback to top\u003c/a\u003e)\u003c/p\u003e\n\n\u003c!-- GETTING STARTED --\u003e\n## Getting Started\n\nThe only hard dependency for `lightbug_http` is Mojo. \nLearn how to get up and running with Mojo on the [Modular website](https://www.modular.com/max/mojo).\nOnce you have a Mojo project set up locally,\n\n1. Add the `mojo-community` channel to your `mojoproject.toml`, e.g:\n\n   ```toml\n   [project]\n   channels = [\"conda-forge\", \"https://conda.modular.com/max\", \"https://repo.prefix.dev/mojo-community\"]\n   ```\n\n2. Add `lightbug_http` as a dependency:\n\n   ```toml\n   [dependencies]\n   lightbug_http = \"\u003e=0.1.17\"\n   ```\n\n3. Run `magic install` at the root of your project, where `mojoproject.toml` is located\n4. Lightbug should now be installed as a dependency. You can import all the default imports at once, e.g:\n\n    ```mojo\n    from lightbug_http import *\n    ```\n\n    or import individual structs and functions, e.g. \n\n    ```mojo\n    from lightbug_http.service import HTTPService\n    from lightbug_http.http import HTTPRequest, HTTPResponse, OK, NotFound\n    ```\n\n    there are some default handlers you can play with:\n\n    ```mojo\n    from lightbug_http.service import Printer # prints request details to console\n    from lightbug_http.service import Welcome # serves an HTML file with an image (currently requires manually adding files to static folder, details below)\n    from lightbug_http.service import ExampleRouter # serves /, /first, /second, and /echo routes\n    ```\n\n5. Add your handler in `lightbug.🔥` by passing a struct that satisfies the following trait:\n\n   ```mojo\n   trait HTTPService:\n    fn func(mut self, req: HTTPRequest) raises -\u003e HTTPResponse:\n        ...\n   ```\n\n   For example, to make a `Printer` service that prints some details about the request to console:\n\n   ```mojo\n    from lightbug_http.http import HTTPRequest, HTTPResponse, OK\n    from lightbug_http.strings import to_string\n    from lightbug_http.header import HeaderKey\n\n    @value\n    struct Printer(HTTPService):\n        fn func(mut self, req: HTTPRequest) raises -\u003e HTTPResponse:\n            print(\"Request URI:\", req.uri.request_uri)\n            print(\"Request protocol:\", req.protocol)\n            print(\"Request method:\", req.method)\n            if HeaderKey.CONTENT_TYPE in req.headers:\n                print(\"Request Content-Type:\", req.headers[HeaderKey.CONTENT_TYPE])\n            if req.body_raw:\n                print(\"Request Body:\", to_string(req.body_raw))\n\n            return OK(req.body_raw)\n   ```\n\n6. Start a server listening on a port with your service like so.\n\n    ```mojo\n    from lightbug_http import Welcome, Server\n\n    fn main() raises:\n        var server = Server()\n        var handler = Welcome()\n        server.listen_and_serve(\"localhost:8080\", handler)\n    ```\n\nFeel free to change the settings in `listen_and_serve()` to serve on a particular host and port.\n\nNow send a request `localhost:8080`. You should see some details about the request printed out to the console.\n\nCongrats 🥳 You're using Lightbug!\n\n\nRouting is not in scope for this library, but you can easily set up routes yourself:\n\n```mojo\nfrom lightbug_http import *\n\n@value\nstruct ExampleRouter(HTTPService):\n    fn func(mut self, req: HTTPRequest) raises -\u003e HTTPResponse:\n        var body = req.body_raw\n        var uri = req.uri\n\n        if uri.path == \"/\":\n            print(\"I'm on the index path!\")\n        if uri.path == \"/first\":\n            print(\"I'm on /first!\")\n        elif uri.path == \"/second\":\n            print(\"I'm on /second!\")\n        elif uri.path == \"/echo\":\n            print(to_string(body))\n\n        return OK(body)\n```\n\nWe plan to add more advanced routing functionality in a future library called `lightbug_api`, see [Roadmap](#roadmap) for more details.\n\n\n\u003cp align=\"right\"\u003e(\u003ca href=\"#readme-top\"\u003eback to top\u003c/a\u003e)\u003c/p\u003e\n\n### Serving static files\n\nThe default welcome screen shows an example of how to serve files like images or HTML using Lightbug. Mojo has built-in `open`, `read` and `read_bytes` methods that you can use to read files and serve them on a route. Assuming you copy an html file and image from the Lightbug repo into a `static` directory at the root of your repo:\n\n```mojo\nfrom lightbug_http import *\n\n@value\nstruct Welcome(HTTPService):\n    fn func(mut self, req: HTTPRequest) raises -\u003e HTTPResponse:\n        var uri = req.uri\n\n        if uri.path == \"/\":\n            var html: Bytes\n            with open(\"static/lightbug_welcome.html\", \"r\") as f:\n                html = f.read_bytes()\n            return OK(html, \"text/html; charset=utf-8\")\n\n        if uri.path == \"/logo.png\":\n            var image: Bytes\n            with open(\"static/logo.png\", \"r\") as f:\n                image = f.read_bytes()\n            return OK(image, \"image/png\")\n\n        return NotFound(uri.path)\n```\n\n### Using the client\n\nCreate a file, e.g `client.mojo` with the following code. Run `magic run mojo client.mojo` to execute the request to a given URL.\n\n```mojo\nfrom lightbug_http import *\nfrom lightbug_http.client import Client\n\nfn test_request(mut client: Client) raises -\u003e None:\n    var uri = URI.parse(\"google.com\")\n    var headers = Headers(Header(\"Host\", \"google.com\"))\n    var request = HTTPRequest(uri, headers)\n    var response = client.do(request^)\n\n    # print status code\n    print(\"Response:\", response.status_code)\n\n    print(response.headers)\n\n    print(\n        \"Is connection set to connection-close? \", response.connection_close()\n    )\n\n    # print body\n    print(to_string(response.body_raw))\n\n\nfn main() -\u003e None:\n    try:\n        var client = Client()\n        test_request(client)\n    except e:\n        print(e)\n```\n\nPure Mojo-based client is available by default. This client is also used internally for testing the server.\n\n### UDP Support\nTo get started with UDP, just use the `listen_udp` and `dial_udp` functions, along with `write_to` and `read_from` methods, like below.\n\nOn the client:\n```mojo\nfrom lightbug_http.connection import dial_udp\nfrom lightbug_http.address import UDPAddr\nfrom utils import StringSlice\n\nalias test_string = \"Hello, lightbug!\"\n\nfn main() raises:\n    print(\"Dialing UDP server...\")\n    alias host = \"127.0.0.1\"\n    alias port = 12000\n    var udp = dial_udp(host, port)\n\n    print(\"Sending \" + str(len(test_string)) + \" messages to the server...\")\n    for i in range(len(test_string)):\n        _ = udp.write_to(str(test_string[i]).as_bytes(), host, port)\n\n        try:\n            response, _, _ = udp.read_from(16)\n            print(\"Response received:\", StringSlice(unsafe_from_utf8=response))\n        except e:\n            if str(e) != str(\"EOF\"):\n                raise e\n\n```\n\nOn the server:\n```mojo\nfn main() raises:\n    var listener = listen_udp(\"127.0.0.1\", 12000)\n\n    while True:\n        response, host, port = listener.read_from(16)\n        var message = StringSlice(unsafe_from_utf8=response)\n        print(\"Message received:\", message)\n\n        # Response with the same message in uppercase\n        _ = listener.write_to(String.upper(message).as_bytes(), host, port)\n\n```\n\n\u003c!-- ROADMAP --\u003e\n## Roadmap\n\n\u003cdiv align=\"center\"\u003e\n    \u003cimg src=\"static/roadmap.png\" alt=\"Logo\" width=\"695\" height=\"226\"\u003e\n\u003c/div\u003e\n\nWe're working on support for the following (contributors welcome!):\n\n - [ ] [JSON support](https://github.com/saviorand/lightbug_http/issues/4)\n - [ ] Complete HTTP/1.x support compliant with RFC 9110/9112 specs (see issues)\n - [ ] [SSL/HTTPS support](https://github.com/saviorand/lightbug_http/issues/20)\n - [ ] [Multiple simultaneous connections](https://github.com/saviorand/lightbug_http/issues/5), [parallelization and performance optimizations](https://github.com/saviorand/lightbug_http/issues/6)\n - [ ] [HTTP 2.0/3.0 support](https://github.com/saviorand/lightbug_http/issues/8)\n\nThe plan is to get to a feature set similar to Python frameworks like [Starlette](https://github.com/encode/starlette), but with better performance.\n\nOur vision is to develop three libraries, with `lightbug_http` (this repo) as a starting point: \n - `lightbug_http` - Lightweight and simple HTTP framework, basic networking primitives\n - [`lightbug_api`](https://github.com/saviorand/lightbug_api) - Tools to make great APIs fast, with OpenAPI support and automated docs\n - `lightbug_web` - (release date TBD) Full-stack web framework for Mojo, similar to NextJS or SvelteKit\n\nThe idea is to get to a point where the entire codebase of a simple modern web application can be written in Mojo. \n\nWe don't make any promises, though -- this is just a vision, and whether we get there or not depends on many factors, including the support of the community.\n\n\nSee the [open issues](https://github.com/saviorand/lightbug_http/issues) and submit your own to help drive the development of Lightbug.\n\n\u003cp align=\"right\"\u003e(\u003ca href=\"#readme-top\"\u003eback to top\u003c/a\u003e)\u003c/p\u003e\n\n\n\n\u003c!-- CONTRIBUTING --\u003e\n## Contributing\n\nContributions are what make the open source community such an amazing place to learn, inspire, and create. Any contributions you make are **greatly appreciated**. See [CONTRIBUTING.md](./CONTRIBUTING.md) for more details on how to contribute.\n\nIf you have a suggestion that would make this better, please fork the repo and create a pull request. You can also simply open an issue with the tag \"enhancement\".\nDon't forget to give the project a star!\n\n1. Fork the Project\n2. Create your Feature Branch (`git checkout -b feature/AmazingFeature`)\n3. Commit your Changes (`git commit -m 'Add some AmazingFeature'`)\n4. Push to the Branch (`git push origin feature/AmazingFeature`)\n5. Open a Pull Request\n\n\u003cp align=\"right\"\u003e(\u003ca href=\"#readme-top\"\u003eback to top\u003c/a\u003e)\u003c/p\u003e\n\n\n\n\u003c!-- LICENSE --\u003e\n## License\n\nDistributed under the MIT License. See `LICENSE.txt` for more information.\n\n\u003cp align=\"right\"\u003e(\u003ca href=\"#readme-top\"\u003eback to top\u003c/a\u003e)\u003c/p\u003e\n\n\n\n\u003c!-- CONTACT --\u003e\n## Contact\n\n[Valentin Erokhin](https://www.valentin.wiki/)\n\nProject Link: [https://github.com/saviorand/mojo-web](https://github.com/saviorand/mojo-web)\n\n\u003cp align=\"right\"\u003e(\u003ca href=\"#readme-top\"\u003eback to top\u003c/a\u003e)\u003c/p\u003e\n\n\n\n\u003c!-- ACKNOWLEDGMENTS --\u003e\n## Acknowledgments\n\nWe were drawing a lot on the following projects:\n\n* [FastHTTP](https://github.com/valyala/fasthttp/) (Golang)\n* [may_minihttp](https://github.com/Xudong-Huang/may_minihttp/) (Rust)\n* [FireTCP](https://github.com/Jensen-holm/FireTCP) (One of the earliest Mojo TCP implementations!)\n\n\n\u003cp align=\"right\"\u003e(\u003ca href=\"#readme-top\"\u003eback to top\u003c/a\u003e)\u003c/p\u003e\n\n## Contributors\nWant your name to show up here? See [CONTRIBUTING.md](./CONTRIBUTING.md)!\n\n\u003ca href=\"https://github.com/saviorand/lightbug_http/graphs/contributors\"\u003e\n  \u003cimg src=\"https://contrib.rocks/image?repo=saviorand/lightbug_http\u0026max=100\" /\u003e\n\u003c/a\u003e\n\n\u003csub\u003eMade with [contrib.rocks](https://contrib.rocks).\u003c/sub\u003e\n\n\u003c!-- MARKDOWN LINKS \u0026 IMAGES --\u003e\n\u003c!-- https://www.markdownguide.org/basic-syntax/#reference-style-links --\u003e\n[build-shield]: https://img.shields.io/github/actions/workflow/status/saviorand/lightbug_http/.github%2Fworkflows%2Fpackage.yml\n[language-shield]: https://img.shields.io/badge/language-mojo-orange\n[license-shield]: https://img.shields.io/github/license/saviorand/lightbug_http?logo=github\n[license-url]: https://github.com/saviorand/lightbug_http/blob/main/LICENSE\n[contributors-shield]: https://img.shields.io/badge/contributors-welcome!-blue\n[contributors-url]: https://github.com/saviorand/lightbug_http#contributing\n[discord-shield]: https://img.shields.io/discord/1192127090271719495?style=flat\u0026logo=discord\u0026logoColor=white\n[discord-url]: https://discord.gg/VFWETkTgrr\n","funding_links":[],"categories":["Why is it called Mojo?","HTTP Framework","🗂️ Libraries\u003ca id='libraries'\u003e\u003c/a\u003e"],"sub_categories":["Web"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FLightbug-HQ%2Flightbug_http","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FLightbug-HQ%2Flightbug_http","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FLightbug-HQ%2Flightbug_http/lists"}