Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
63 changes: 34 additions & 29 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,16 +17,16 @@
<br/>
[![Join our Discord][discord-shield]][discord-url]
[![Contributors Welcome][contributors-shield]][contributors-url]


</p>
</div>

## Overview

Lightbug 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/).
Lightbug is a simple and sweet HTTP framework for [Mojo](https://www.modular.com/max/mojo) that builds on best practices from systems programming, such as the Golang [FastHTTP](https://github.com/valyala/fasthttp/) and Rust [may_minihttp](https://github.com/Xudong-Huang/may_minihttp/).

This 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.
This 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.

Lightbug currently has the following features:
- [x] Pure Mojo! No Python dependencies. Everything is fully typed, with no `def` functions used
Expand All @@ -45,39 +45,44 @@ Lightbug currently has the following features:
<!-- GETTING STARTED -->
## Getting Started

The only hard dependency for `lightbug_http` is Mojo.
Learn how to get up and running with Mojo on the [Modular website](https://www.modular.com/max/mojo).
Once you have a Mojo project set up locally,
The only hard dependency for `lightbug_http` is Mojo. To install Lightbug, we recommend using [pixi](https://pixi.sh/latest/). For other options and to see which systems support Mojo, see the [Mojo installation guide](https://docs.modular.com/mojo/manual/install).

1. Add the `modular-community` channel to your `mojoproject.toml`, e.g:
1. If you don't have pixi, you can install it with this command:

```toml
[project]
channels = ["conda-forge", "https://conda.modular.com/max", "https://repo.prefix.dev/modular-community"]
```bash
curl -fsSL https://pixi.sh/install.sh | sh
```

2. Add `lightbug_http` as a dependency:
2. Navigate to the _parent_ directory where you want to create the project and execute:

```bash
# Initialize project named lightbug: mkdir lightbug and add pixi.toml
pixi init lightbug \
-c conda-forge \
-c https://conda.modular.com/max \
-c https://repo.prefix.dev/mojo-community

cd lightbug

```toml
[dependencies]
lightbug_http = ">=25.4.0"
# Add dependency to pixi.toml
pixi add lightbug_http>=0.25.6
```

3. Run `magic install` at the root of your project, where `mojoproject.toml` is located
3. Run `pixi install` at the root of your project, where `pixi.toml` is located.
4. Lightbug should now be installed as a dependency. You can import all the default imports at once, e.g:

```mojo
from lightbug_http import *
```

or import individual structs and functions, e.g.
or import individual structs and functions, e.g.

```mojo
from lightbug_http.service import HTTPService
from lightbug_http.http import HTTPRequest, HTTPResponse, OK, NotFound
```

there are some default handlers you can play with:
There are also some default handlers you can play with:

```mojo
from lightbug_http.service import Printer # prints request details to console
Expand All @@ -93,7 +98,7 @@ Once you have a Mojo project set up locally,
...
```

For example, to make a `Printer` service that prints some details about the request to console:
For example, to make a `Printer` service that prints some details about the request to the console:

```mojo
from lightbug_http.http import HTTPRequest, HTTPResponse, OK
Expand All @@ -114,7 +119,7 @@ Once you have a Mojo project set up locally,
return OK(req.body_raw)
```

6. Start a server listening on a port with your service like so.
6. Start a server listening on a port with your service like this:

```mojo
from lightbug_http import Welcome, Server
Expand All @@ -127,7 +132,7 @@ Once you have a Mojo project set up locally,

Feel free to change the settings in `listen_and_serve()` to serve on a particular host and port.

Now send a request `localhost:8080`. You should see some details about the request printed out to the console.
Now send a request to `localhost:8080`. You should see some details about the request printed out to the console.

Congrats 🥳 You're using Lightbug!

Expand Down Expand Up @@ -155,14 +160,14 @@ struct ExampleRouter(HTTPService):
return OK(body)
```

We plan to add more advanced routing functionality in a future library called `lightbug_api`, see [Roadmap](#roadmap) for more details.
We plan to add more advanced routing functionality in a future library called `lightbug_api`. See the [Roadmap](#roadmap) for more details.


<p align="right">(<a href="#readme-top">back to top</a>)</p>

### Serving static files

The 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:
The 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 an image from the Lightbug repo into a `static` directory at the root of your repository:

```mojo
from lightbug_http import *
Expand Down Expand Up @@ -190,7 +195,7 @@ struct Welcome(HTTPService):

### Using the client

Create a file, e.g `client.mojo` with the following code. Run `magic run mojo client.mojo` to execute the request to a given URL.
Create a file, e.g., `client.mojo`, with the following code. Run `pixi run mojo client.mojo` to execute the request to a given URL.

```mojo
from lightbug_http import *
Expand Down Expand Up @@ -223,10 +228,10 @@ fn main() -> None:
print(e)
```

Pure Mojo-based client is available by default. This client is also used internally for testing the server.
A pure Mojo-based client is available by default. This client is also used internally for testing the server.

### UDP Support
To get started with UDP, just use the `listen_udp` and `dial_udp` functions, along with `write_to` and `read_from` methods, like below.
To get started with UDP, just use the `listen_udp` and `dial_udp` functions, along with `write_to` and `read_from` methods, as shown below.

On the client:
```mojo
Expand Down Expand Up @@ -285,14 +290,14 @@ We're working on support for the following (contributors welcome!):
- [ ] [Multiple simultaneous connections](https://github.com/saviorand/lightbug_http/issues/5), [parallelization and performance optimizations](https://github.com/saviorand/lightbug_http/issues/6)
- [ ] [HTTP 2.0/3.0 support](https://github.com/saviorand/lightbug_http/issues/8)

The plan is to get to a feature set similar to Python frameworks like [Starlette](https://github.com/encode/starlette), but with better performance.
The plan is to reach a feature set similar to Python frameworks like [Starlette](https://github.com/encode/starlette), but with better performance.

Our vision is to develop three libraries, with `lightbug_http` (this repo) as a starting point:
Our vision is to develop three libraries, with `lightbug_http` (this repo) as a starting point:
- `lightbug_http` - Lightweight and simple HTTP framework, basic networking primitives
- [`lightbug_api`](https://github.com/saviorand/lightbug_api) - Tools to make great APIs fast, with OpenAPI support and automated docs
- `lightbug_web` - (release date TBD) Full-stack web framework for Mojo, similar to NextJS or SvelteKit

The idea is to get to a point where the entire codebase of a simple modern web application can be written in Mojo.
The idea is to get to a point where the entire codebase of a simple modern web application can be written in Mojo.

We 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.

Expand Down Expand Up @@ -324,7 +329,7 @@ Don't forget to give the project a star!
<!-- LICENSE -->
## License

Distributed under the MIT License. See `LICENSE.txt` for more information.
Distributed under the MIT License. See `LICENSE` for more information.

<p align="right">(<a href="#readme-top">back to top</a>)</p>

Expand Down
10 changes: 5 additions & 5 deletions mojoproject.toml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
[project]
[workspace]
authors = ["saviorand"]
channels = ["conda-forge", "https://conda.modular.com/max", "https://repo.prefix.dev/modular-community"]
description = "Simple and fast HTTP framework for Mojo!"
Expand All @@ -9,18 +9,18 @@ version = "0.25.6"
[tasks]
build = { cmd = "rattler-build build --recipe recipes -c https://conda.modular.com/max -c conda-forge --skip-existing=all", env = {MODULAR_MOJO_IMPORT_PATH = "$CONDA_PREFIX/lib/mojo"} }
publish = { cmd = "bash scripts/publish.sh", env = { PREFIX_API_KEY = "$PREFIX_API_KEY" } }
format = { cmd = "magic run mojo format -l 120 lightbug_http" }
format = { cmd = "pixi run mojo format -l 120 lightbug_http" }

[feature.unit-tests.tasks]
test = { cmd = "magic run mojo test -I . tests/lightbug_http" }
test = { cmd = "pixi run mojo test -I . tests/lightbug_http" }

[feature.integration-tests.tasks]
integration_tests_py = { cmd = "bash scripts/integration_test.sh" }
integration_tests_external = { cmd = "magic run mojo test -I . tests/integration" }
integration_tests_external = { cmd = "pixi run mojo test -I . tests/integration" }
integration_tests_udp = { cmd = "bash scripts/udp_test.sh" }

[feature.bench.tasks]
bench = { cmd = "magic run mojo -I . benchmark/bench.mojo" }
bench = { cmd = "pixi run mojo -I . benchmark/bench.mojo" }
bench_server = { cmd = "bash scripts/bench_server.sh" }

[dependencies]
Expand Down
2 changes: 1 addition & 1 deletion scripts/bench_server.sh
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@


magic run mojo build -I . benchmark/bench_server.mojo || exit 1
pixi run mojo build -I . benchmark/bench_server.mojo || exit 1

echo "running server..."
./bench_server&
Expand Down
8 changes: 4 additions & 4 deletions scripts/integration_test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -8,26 +8,26 @@ kill_server() {
}

test_server() {
(magic run mojo build -D LB_LOG_LEVEL=DEBUG -I . --debug-level full tests/integration/integration_test_server.mojo) || exit 1
(pixi run mojo build -D LB_LOG_LEVEL=DEBUG -I . --debug-level full tests/integration/integration_test_server.mojo) || exit 1

echo "[INFO] Starting Mojo server..."
./integration_test_server &

sleep 5

echo "[INFO] Testing server with Python client"
magic run python3 tests/integration/integration_client.py
pixi run python3 tests/integration/integration_client.py

rm ./integration_test_server
kill_server "integration_test_server" || echo "Failed to kill Mojo server"
}

test_client() {
echo "[INFO] Testing Mojo client with Python server"
(magic run mojo build -D LB_LOG_LEVEL=DEBUG -I . --debug-level full tests/integration/integration_test_client.mojo) || exit 1
(pixi run mojo build -D LB_LOG_LEVEL=DEBUG -I . --debug-level full tests/integration/integration_test_client.mojo) || exit 1

echo "[INFO] Starting Python server..."
magic run fastapi run tests/integration/integration_server.py &
pixi run fastapi run tests/integration/integration_server.py &
sleep 5

./integration_test_client
Expand Down
2 changes: 1 addition & 1 deletion scripts/publish.sh
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

# ignore errors because we want to ignore duplicate packages
for file in $CONDA_BLD_PATH/**/*.conda; do
magic run rattler-build upload prefix -c "mojo-community" "$file" || true
pixi run rattler-build upload prefix -c "mojo-community" "$file" || true
done

rm $CONDA_BLD_PATH/**/*.conda
4 changes: 2 additions & 2 deletions scripts/udp_test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ kill_server() {
wait $pid 2>/dev/null
}

(magic run mojo build -D LB_LOG_LEVEL=DEBUG -I . --debug-level full tests/integration/udp/udp_server.mojo)
(magic run mojo build -D LB_LOG_LEVEL=DEBUG -I . --debug-level full tests/integration/udp/udp_client.mojo)
(pixi run mojo build -D LB_LOG_LEVEL=DEBUG -I . --debug-level full tests/integration/udp/udp_server.mojo)
(pixi run mojo build -D LB_LOG_LEVEL=DEBUG -I . --debug-level full tests/integration/udp/udp_client.mojo)

echo "[INFO] Starting UDP server..."
./udp_server &
Expand Down