Skip to content

Commit

Permalink
Merge pull request #40 from Basicprogrammer10/dev
Browse files Browse the repository at this point in the history
afire 2.1.0
  • Loading branch information
connorslade authored Apr 25, 2023
2 parents 95c22c3 + 9f232ed commit 59bf130
Show file tree
Hide file tree
Showing 34 changed files with 1,398 additions and 255 deletions.
2 changes: 1 addition & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 3 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
authors = ["Connor Slade <connor@connorcode.com>"]
edition = "2018"
name = "afire"
version = "2.0.0"
version = "2.1.0"

categories = ["network-programming", "web-programming::http-server"]
description = "🔥 A blazing fast web framework for Rust"
Expand All @@ -19,8 +19,9 @@ name = "afire"
path = "lib/lib.rs"

[features]
default = ["tracing"]
default = ["tracing", "emoji-logging"]

emoji-logging = []
extensions = []
tracing = []

Expand Down
32 changes: 31 additions & 1 deletion Changelog.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,33 @@
# 2.1.0

April 24, 2023

- Added a get_query method on Query
- Changed default log level back to Error
- Response flags (Close & End)
- More built-in encoding systems (base64 & sha-1)
- Change encoding system module format
- Multipart request parsing
- CookieJar struct for holding Cookies in the request
- RealIp extension
- Allow serving an IPv6 addr
- Use a `Headers` struct to hold default headers
- Added a HeaderParams struct
- Impl ToHostAddress for &String
- Add Server::app to get a reference to the app
- Increase ServeStatic compatibility with other middleware
- Custom log formatter support
- Optional emoji in logging
- Fix the Display impl on Query
- Add body_str method to Request
- Impl std::error::Error for afire::Error
- Impl Display for error types
- Don't execute format on lower log-levels
- Fix spelling errors
- Fix Logger middleware always appending `?` to the path
- Don't consider sockets closing to be an error (only printed in debug tracing)
- Mild performance improvements in the path matcher with catch-all routes

# 2.0.0

February 11, 2023
Expand Down Expand Up @@ -111,7 +141,7 @@ Feb 19, 2022

# 0.3.0

Jan 25, 2022 s
Jan 25, 2022

- Add content types
- Update Logger syntax
Expand Down
8 changes: 4 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# 🔥 afire <a href="https://github.com/Basicprogrammer10/afire/actions"><img src="https://github.com/Basicprogrammer10/afire/actions/workflows/rust.yml/badge.svg"></a> <a href="https://crates.io/crates/afire"><img alt="Crates.io" src="https://img.shields.io/crates/v/afire"> <img src="https://img.shields.io/crates/d/afire?label=Downloads"></a>
# 🔥 afire <a href="https://github.com/Basicprogrammer10/afire/actions"><img src="https://github.com/Basicprogrammer10/afire/actions/workflows/rust.yml/badge.svg"></a> <a href="https://crates.io/crates/afire"><img alt="Crates.io" src="https://img.shields.io/crates/v/afire"></a> <a href="https://crates.io/crates/afire"><img src="https://img.shields.io/crates/d/afire?label=Downloads"></a>

afire is a _blazingly fast_ web server micro framework for rust.

Expand All @@ -8,7 +8,7 @@ Just add the following to your `Cargo.toml`:

```toml
[dependencies]
afire = "2.0.0"
afire = "2.1.0"
```

## 📄 Info
Expand All @@ -17,11 +17,11 @@ afire is a simple synchronous multithreaded express.js inspired rust web micro f
wow that was long.
It comes with some built extensions in for Static File Serving, Rate limiting, and more.

Below you can fine links to some afire related resources.
Below you can find links to some afire related resources.

- [Homepage](https://connorcode.com/writing/afire)
- [Crates.io page](https://crates.io/crates/afire)
- [API Docs](https://docs.rs/afire/latest/afire/)
- [API Docs](https://docs.rs/afire/latest/afire)

## 💥 Example

Expand Down
6 changes: 3 additions & 3 deletions examples/application_paste_bin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
use std::time::Instant;
use std::{borrow::Borrow, sync::RwLock};

use afire::internal::encoding::decode_url;
use afire::internal::encoding::url;
use afire::{Content, HeaderType, Method, Query, Response, Server, Status};

const DATA_LIMIT: usize = 10_000;
Expand Down Expand Up @@ -74,8 +74,8 @@ fn main() {
server.stateful_route(Method::POST, "/new-form", |app, req| {
// Get data from response
let query = Query::from_body(String::from_utf8_lossy(&req.body).borrow());
let name = decode_url(query.get("name").unwrap_or("Untitled")).expect("Invalid name");
let body = decode_url(query.get("body").expect("No body supplied")).expect("Invalid body");
let name = url::decode(query.get("name").unwrap_or("Untitled")).expect("Invalid name");
let body = url::decode(query.get("body").expect("No body supplied")).expect("Invalid body");

// Make sure paste data isn't too long
if body.len() > DATA_LIMIT {
Expand Down
14 changes: 7 additions & 7 deletions examples/application_quote_book.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ use std::{

use afire::{
extension::date::imp_date,
internal::encoding::{decode_url, encode_url},
internal::encoding::url,
trace,
trace::{set_log_level, Level},
Content, HeaderType, Method, Query, Response, Server, Status,
Expand Down Expand Up @@ -50,9 +50,9 @@ fn main() {
server.stateful_route(Method::POST, "/api/new", |app, req| {
let form = Query::from_body(&String::from_utf8_lossy(&req.body));
let name =
decode_url(form.get("author").expect("No author supplied")).expect("Invalid author");
url::decode(form.get("author").expect("No author supplied")).expect("Invalid author");
let body =
decode_url(form.get("quote").expect("No quote supplied")).expect("Invalid quote");
url::decode(form.get("quote").expect("No quote supplied")).expect("Invalid quote");

let quote = Quote {
name,
Expand Down Expand Up @@ -167,16 +167,16 @@ impl Quote {
fn save(&self) -> String {
format!(
"{}:{}:{}",
encode_url(&self.name),
encode_url(&self.value),
url::encode(&self.name),
url::encode(&self.value),
self.date
)
}

fn load(line: &str) -> Option<Self> {
let mut parts = line.split(':');
let name = decode_url(parts.next()?).unwrap();
let value = decode_url(parts.next()?).unwrap();
let name = url::decode(parts.next()?).unwrap();
let value = url::decode(parts.next()?).unwrap();
let date = parts.next()?.parse().ok()?;

Some(Self { name, value, date })
Expand Down
2 changes: 1 addition & 1 deletion examples/basic/cookie.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ impl Example for Cookie {
html.push_str("<style>table, th, td {border:1px solid black;}</style>");
html.push_str("<table>");
html.push_str("<tr><th>Name</th><th>Value</th></tr>");
for cookie in &req.cookies {
for cookie in &*req.cookies {
html.push_str("<tr><td>");
html.push_str(&cookie.name);
html.push_str("</td><td>");
Expand Down
128 changes: 126 additions & 2 deletions examples/tmp.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,31 @@
use std::fs::{self, File};
// Note: This module is intended for internal testing only

use afire::{extension::Date, extension::Logger, prelude::*, trace::set_log_level, trace::Level};
use std::{
collections::HashMap,
convert::TryFrom,
fs::{self, File},
io::{self, Read},
sync::Arc,
time::Instant,
};

use afire::{
extension::{Date, Logger},
internal::encoding::{base64, sha1},
multipart::MultipartData,
prelude::*,
trace,
trace::DefaultFormatter,
trace::{set_log_formatter, set_log_level, Formatter, Level},
};

// File to download
const PATH: &str = r#"..."#;

fn main() {
let mut server = Server::<()>::new("localhost", 8080);
set_log_level(Level::Debug);
set_log_formatter(LogFormatter);
Logger::new().attach(&mut server);

server.route(Method::POST, "/upload", |req| {
Expand All @@ -26,12 +44,86 @@ fn main() {
});

server.route(Method::GET, "/", |req| {
let mango = req.socket.lock().unwrap();
let user_agent = req.headers.get(HeaderType::UserAgent).unwrap();
println!("{}", mango.peer_addr().unwrap());
Response::new().text(user_agent).content(Content::TXT)
});

server.route(Method::ANY, "/panic", |_| panic!("panic!"));

server.route(Method::POST, "/file-upload", |req| {
let multipart = MultipartData::try_from(req).unwrap();
let entry = multipart.get("file").unwrap();

Response::new().bytes(entry.data).content(Content::Custom(
entry.headers.get(HeaderType::ContentType).unwrap(),
))
});

// No-copy file echo
server.route(Method::POST, "/raw-upload", |req| {
let body = req.body.clone();
Response::new()
.stream(Cursor::new(body))
.content(Content::Custom(
req.headers.get(HeaderType::ContentType).unwrap(),
))
});

server.route(Method::GET, "/header-stat", |req| {
let headers = req.headers.to_vec();
let mut head_map = HashMap::new();

for i in headers.iter() {
head_map.insert(i.name.clone(), i);
}

let mut res = String::new();
let start = Instant::now();
for _ in 0..100000 {
head_map.get(&HeaderType::UserAgent).unwrap();
}
let end = Instant::now();
res.push_str(&format!(
"HashMap: {}ns\n",
end.duration_since(start).as_nanos()
));

let start = Instant::now();
for _ in 0..100000 {
headers
.iter()
.find(|i| i.name == HeaderType::UserAgent)
.unwrap();
}
let end = Instant::now();
res.push_str(&format!(
"Vec: {}ns",
end.duration_since(start).as_nanos()
));

Response::new().text(res)
});

const WS_GUID: &str = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
server.route(Method::GET, "/ws", |req| {
let ws_key = req.headers.get("Sec-WebSocket-Key").unwrap().to_owned();
trace!("WS Key: {}", ws_key);
let accept = base64::encode(&sha1::hash((ws_key + WS_GUID).as_bytes()));
trace!("WS Accept: {}", accept);

let mut upgrade = Response::new()
.status(Status::SwitchingProtocols)
.header(HeaderType::Upgrade, "websocket")
.header(HeaderType::Connection, "Upgrade")
.header("Sec-WebSocket-Accept", &accept)
.header("Sec-WebSocket-Version", "13");
upgrade.write(req.socket.clone(), &[]).unwrap();

Response::end()
});

Test.attach(&mut server);
Date.attach(&mut server);
server.start_threaded(5).unwrap();
Expand Down Expand Up @@ -63,3 +155,35 @@ impl Middleware for Test {
}
}
}

struct LogFormatter;

impl Formatter for LogFormatter {
fn format(&self, level: Level, color: bool, msg: String) {
DefaultFormatter.format(level, color, msg);
}
}

struct Cursor {
inner: Arc<Vec<u8>>,
index: u64,
}

impl Cursor {
fn new(inner: Arc<Vec<u8>>) -> Self {
Self { inner, index: 0 }
}

fn remaining_slice(&self) -> &[u8] {
let len = self.index.min(self.inner.as_ref().len() as u64);
&self.inner.as_ref()[(len as usize)..]
}
}

impl Read for Cursor {
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
let n = Read::read(&mut self.remaining_slice(), buf)?;
self.index += n as u64;
Ok(n)
}
}
Loading

0 comments on commit 59bf130

Please sign in to comment.