Crates.io | blazing_agi |
lib.rs | blazing_agi |
version | 0.3.0 |
source | src |
created_at | 2024-08-31 19:23:23.134761 |
updated_at | 2024-09-19 15:21:48.223802 |
description | blazing_agi is a FastAGI server focusing on ergonomics and correctness. |
homepage | |
repository | https://github.com/curatorsigma/blazing_agi |
max_upload_size | |
id | 1359163 |
size | 133,130 |
blazing_agi
is a fast, ergonomic and correct FastAGI Server, written in 100% safe Rust.
To get started, consider this "Hello World" example:
use blazing_agi::{command::{verbose::Verbose}, router::Router, serve};
use blazing_agi_macros::create_handler;
use tokio::net::TcpListener;
// The create_handler macro is used to turn an async fn into a handler.
// Make sure to use the same signature as here (including the variable names, but not the function
// name)
#[create_handler]
async fn foo(connection: &mut Connection, request: &AGIRequest) -> Result<(), AGIError> {
connection.send_command(Verbose::new("Hello There".to_string())).await?;
Ok(())
}
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
// Create the router from the handlers you have defined
let router = Router::new()
.route("/script", foo);
let listener = TcpListener::bind("0.0.0.0:4573").await?;
// Start serving the Router
serve::serve(listener, router).await?;
Ok(())
}
You can find a more elaborate example in examples/layer-agi-digest.rs
.
There, we use layering to add a Digest-Authentication Layer on top of a normal asterisk stream,
which requires minimal setup on the asterisk side, allowing secure authentication for endpoints
that should not be accessible by anyone.
In general, blazing_agi works by defining AGIHandler
(read: scripts). You then combine them
into Router
s. They define which requested uri is handled by which
handler.
An AGIHandler
takes:
Connection
- this is a wrapper around a tokio TcpStream
, which handles sending
Commands and parsing the responseAGIRequest
- this contains the data send in the initial request made by the client
(asterisk).An AGIHandler
can then use the Connection::send_command
function to send commands to
the client.
When it is done, the Handler simply returns Ok(())
to signal that the
execution was successful and the stream can be terminated.
If an error is encountered that the Handler does not want to handle, it can be bubbled up as
AGIError
, which tells the runtime that something went wrong - the stream is also closed.
blazing_agi
requires the use of tokio. Executor independence is currently not a goal.
blazing_agi
does not currently contain definitions for all AGI commands.
Please file an issue or a PR if you want one added.
In the meantime, you can use the RawCommand
to send literal strings into Asterisk and do no special parsing on return types.
blazing_agi
is currently pre-1.0. Consider pinning the exact version you use to ensure you get smooth cargo update
s.
I will promise the following SemVer during pre-1.0:
MSRV is rustc 1.80
. The code may work on earlier versions, but I have not tested them.
You can find the changelog in CHANGELOG.md
.
I am very grateful for your help in improving blazing_agi
!
If you need a feature, or have another suggestion for improving this project, please file an issue.
PRs are of course highly appreciated. As a rule:
#![forbid(unsafe_code)]
)unwrap
. If a condition cannot fail, please use except
with a good explanation.cargo test
passes.cargo fmt
and consider using cargo fix
before creating a PR.You can find examples on the approach in src/command/*.rs
.
Each command should get its own file in that directory and be re-exported by crate::command
.
Each command should contain a way to construct itself (new
, builderpattern where useful).
Each command must implement crate::command::AGICommand
.
Here is a list of commands not currently implemented:
I personally do not have use cases for most of the AGI commands, and not enough free time to dedicate to these integration tests.
If you use blazing_agi
and find any bugs while integrating with asterisk, please file an issue.
Reach out to me, I would love to chat!
This project is licensed under MIT-0 (MIT No Attribution). By contributing to this repositry, you agree that your code will be licensed as MIT-0.
For my rationale for using MIT-0 instead of another more common license, please see https://copy.church/objections/attribution/#why-not-require-attribution .