#http-response #request-response #scratch #built #js #express

bin+lib choki

A simple http server built from scratch. Not intended for production uses but a simple website with some query stuff can be made. (can withstand a lot of requests per second)

17 stable releases

new 1.0.16 Nov 30, 2024
1.0.12 Sep 21, 2024
1.0.9 Aug 20, 2024
1.0.5 Jun 6, 2024
1.0.4 May 28, 2024

#309 in HTTP server

Download history 485/week @ 2024-08-16 31/week @ 2024-08-23 136/week @ 2024-08-30 163/week @ 2024-09-06 25/week @ 2024-09-13 212/week @ 2024-09-20 19/week @ 2024-09-27 4/week @ 2024-10-04 11/week @ 2024-10-11 2/week @ 2024-10-18 18/week @ 2024-11-01 9/week @ 2024-11-08 1/week @ 2024-11-15 380/week @ 2024-11-29

392 downloads per month

MIT/Apache

32KB
643 lines

A simple http server library built from scratch.
Using only the threadpool crate and num_cpus. (and ofc the built in std)
Heavily inspired by express.js

https://expressjs.com/

📂・Installation

cargo add choki

or add it in your Cargo.toml

choki = "1.0.11"

💡・Features

  • Create GET and POST endpoints and use them like you are used to in express.js
  • Create Static endpoints

Declare them in your file

use choki::structs::{Request, Response};
use choki::Server;

Create a object from the class called Server

  let mut server: Server<u8> = Server::new(Some(1024),None); // you can also type None if you dont want any restrictions

The number in the () is the max content length of the request or in simple terms the max size of the request sent from the client.

Create GET endpoint

server.get("/".to_string(), |req: Request, mut res: Response, public_var: Option<u8>| {
    res.send_string("HI");
}).unwrap();

Create POST endpoint

server.post("/".to_string(), |req: Request, mut res: Response, public_var: Option<u8>| {
    res.send_string("HI");
}).unwrap();

Create STATIC endpoint

 server.new_static("/images".to_string(), "./tests/images".to_string()).unwrap(); // The first one is the path in the browser for example: example.com/images and the second one is the exposed path from the computer(local)

Create Get/Set endpoint with params

As of 1.0.8 choki supports params

 server.post("/search/[id]".to_string(), |req: Request, mut res: Response, public_var: Option<u8>| {
    println!("{}", req.params.get("id").unwrap()); // if i make request to /search/pizza this will print pizza
    res.send_string("HI");
}).unwrap();

Response

So they are four simple functions

res.send_bytes(&mut self, data: &[u8], content_type: Option<ContentType>) // sends raw bytes with content type you provide (you can provide ContentType::None and let the browser decide)
res.send_string(&mut self, data: &str) // sends string as response
res.send_json(&mut self, data: &str) // sends json as response
res.send_code(&mut self, code: usize) // sends a HTTP response code (404,200...)

as of 1.0.3 you can set or delete cookies and ofc read them.

pub struct Cookie {
    pub name: String,
    pub value: String,
    pub path: String,
    pub expires: String,
}

You can read cookies using req.cookies (stored as a vec)

You can set/delete them using

res.set_cookie(cookie: &Cookie);
res.delete_cookie(name: &str);

as of 1.0.6 you can set or delete headers and ofc read them.

pub struct Header {
    pub name: String,
    pub value: String,
}

You can set/delete them using

res.set_header(header: &Header);
res.delete_cookie(name: &str);

Request

When you create an endpoint you have Request and Response.
The request holds info about the request.

pub struct Request {
    pub query: HashMap<String, String>, // for example in the url www.example.com/?name=Kartof the query will be ["name" => "Kartof"] as hashmap
    pub user_agent: Option<String>, // this is the user agent from which the user accesses the website
    pub content_length: usize, // the length of the request (they are no implementations for multy form thingy so its not so useful)
}

The final

You need to make the server actually 'listen' for requests so use this method:

server.listen(port: u32, address: Option<String>) -> Result<(), HttpServerError>

And finally because you wanna keep the main thread running or else the server will close as soon as the code runs.

Add this at the end of your file

  Server::<i32>::lock();

Also in the src folder there is a main.rs file which can be used as an example.

And thats it enjoy using it and keep in mind THIS IS NOT PRODUCTION READY!!!

Dependencies

~120KB