Merge pull request #3 from RaspberryProgramming/v0.5-upgrade

v0.5 Upgrade - Upgraded and modified project to support rocket.rs v0.5.1
This commit is contained in:
Camerin Figueroa 2024-07-03 21:08:38 -04:00 committed by GitHub
commit 5d5f46f1e3
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
10 changed files with 1079 additions and 862 deletions

1808
Cargo.lock generated

File diff suppressed because it is too large Load Diff

10
Cargo.toml Normal file → Executable file
View File

@ -1,6 +1,6 @@
[package]
name = "request-mirror"
version = "0.1.0"
version = "0.1.1"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
@ -9,14 +9,14 @@ edition = "2021"
chrono = "0.4.34"
diesel = { version = "2.1.4", features = ["postgres", "chrono"] }
dotenvy = "0.15.7"
rocket = { version = "0.4.11", features = ["tls"] }
rocket = { version = "0.5.1", features = ["tls"] }
serde = { version = "1.0.197", features = ["derive"] }
serde_json = "1.0.114"
tokio = { version = "1.36.0", features = ["full"] }
[dependencies.rocket_contrib]
version = "0.4.11"
features = ["handlebars_templates", "tera_templates"]
[dependencies.rocket_dyn_templates]
version = "0.2.0"
features = ["handlebars"]
[dependencies.uuid]
version = "1.7.0"

View File

@ -1,6 +1,8 @@
FROM rustlang/rust:nightly as builder
WORKDIR ./app
COPY . .
WORKDIR /app
COPY src ./src
COPY Cargo.toml .
COPY Cargo.lock .
RUN cargo install --path .
FROM rustlang/rust:nightly as runner
@ -10,8 +12,7 @@ RUN apt update && apt install -y libpq-dev libc6
COPY --from=builder /usr/local/cargo/bin/request-mirror /usr/local/bin/request-mirror
COPY ./templates /templates
COPY .env.docker /.env
ENV ROCKET_ADDRESS=0.0.0.0
ENV ROCKET_PORT=80
ENV ROCKET_ENV=production
COPY Rocket.toml /
ENV ROCKET_PROFILE=docker
EXPOSE 80
ENTRYPOINT diesel migration run --database-url $DATABASE_URL --migration-dir /migrations && request-mirror

View File

@ -1,27 +1,21 @@
[development]
[default]
address = "0.0.0.0"
port = 8000
keep_alive = 5
read_timeout = 5
write_timeout = 5
log = "normal"
log_level = "normal"
limits = { forms = 32768 }
[staging]
address = "0.0.0.0"
port = 8000
keep_alive = 5
read_timeout = 5
write_timeout = 5
log = "normal"
limits = { forms = 32768 }
[production]
[release]
address = "0.0.0.0"
port = 80
keep_alive = 5
read_timeout = 5
write_timeout = 5
log = "critical"
log_level = "critical"
limits = { forms = 32768 }
[docker]
address = "0.0.0.0"
port = 80
keep_alive = 5
log_level = "critical"
limits = { forms = 32768 }
template_dir = "/templates/"

View File

@ -27,7 +27,7 @@ pub fn establish_connection() -> PgConnection {
let database_url: String;
match env::var(key) {
Ok(val) => database_url = val,
Err(e) => {
Err(_e) => {
dotenv().ok();
database_url = env::var(key).expect("DATABASE_URL must be set");

View File

@ -1,17 +1,15 @@
#![feature(proc_macro_hygiene, decl_macro)]
#[macro_use]
extern crate rocket;
use request_mirror::schema::{history, pair_records};
use rocket::{data, request, Outcome, Request, Data};
use rocket::data::FromDataSimple;
use rocket::request::FromRequest;
use rocket_contrib::templates::Template;
use rocket::data::{FromData, ToByteUnit};
use rocket::{data, Data};
use rocket::request::{self, Request, FromRequest};
use rocket::outcome::Outcome;
use rocket_dyn_templates::Template;
use serde::Serialize;
use rocket::http::{Cookie, Cookies, Status};
use rocket::http::{Cookie, CookieJar, Status};
use uuid::Uuid;
use std::io::Read;
use request_mirror::models::*;
use diesel::prelude::*;
use request_mirror::*;
@ -24,7 +22,9 @@ struct RequestInfo {
}
#[derive(Debug)]
enum ApiError {
enum Error {
TooLarge,
Io(std::io::Error),
}
#[derive(Serialize, Debug, Clone)]
@ -33,13 +33,14 @@ struct RequestBody(String);
// Always use a limit to prevent DoS attacks.
const LIMIT: u64 = 256;
impl<'a, 'r> FromRequest<'a, 'r> for RequestInfo {
type Error = ApiError;
#[rocket::async_trait]
impl<'r> FromRequest<'r> for RequestInfo {
type Error = Error;
/// Used for parsing request information and making it available for request functions to access
/// Also handles creating cookies when the client doesn't send one in the request
fn from_request(request: &'a Request<'r>) -> request::Outcome<Self, Self::Error> {
let mut req_cookies = request.cookies();
async fn from_request(req: &'r Request<'_>) -> request::Outcome<Self, Self::Error> {
let req_cookies: &CookieJar = req.cookies();
// Initially set cookie
if req_cookies.get(&"mirror-id").is_none() {
@ -47,13 +48,12 @@ impl<'a, 'r> FromRequest<'a, 'r> for RequestInfo {
// When the client doesn't send the mirror-id cookie, from_request will create
// one in the database and send it back to the client.
let new_uuid = Uuid::new_v4().to_string();
println!("Creating new cookie");
req_cookies.add(Cookie::new("mirror-id", new_uuid.clone()));
let address = if request.client_ip().is_some() {
request.client_ip().unwrap().to_string()
let address = if req.client_ip().is_some() {
req.client_ip().unwrap().to_string()
} else {
"Unknown".to_string()
};
@ -71,7 +71,7 @@ impl<'a, 'r> FromRequest<'a, 'r> for RequestInfo {
let mut query: Vec<Pair> = vec![];
// Compile header
for row in request.headers().clone().into_iter() {
for row in req.headers().clone().into_iter() {
let key: String = row.name().to_string();
let value: String = row.value().to_string();
@ -87,15 +87,14 @@ impl<'a, 'r> FromRequest<'a, 'r> for RequestInfo {
}
// Compile query
let request_query = request.raw_query_items();
if request_query.is_some() {
for row in request_query.unwrap() {
let (key, value) = row.key_value_decoded();
let request_query = req.query_fields();
for field in request_query {
query.push(Pair{key:key, value:value});
}
query.push(Pair{key:field.name.to_string(), value:field.value.to_string()});
}
// Send the Request Info as successful outcome
Outcome::Success(RequestInfo {
header: header,
@ -105,19 +104,24 @@ impl<'a, 'r> FromRequest<'a, 'r> for RequestInfo {
}
}
impl FromDataSimple for RequestBody {
type Error = String;
#[rocket::async_trait]
impl<'r> FromData<'r> for RequestBody {
type Error = Error;
/// Used to extract the body of a request and make it available to request functions
fn from_data(_req: &Request, data: Data) -> data::Outcome<Self, String> {
async fn from_data(_req: &'r Request<'_>, data: Data<'r>) -> data::Outcome<'r, Self> {
// Read the data into a String.
let mut string = String::new();
if let Err(e) = data.open().take(LIMIT).read_to_string(&mut string) {
return Outcome::Failure((Status::InternalServerError, format!("{:?}", e)));
}
let string = match data.open(LIMIT.mebibytes()).into_string().await {
Ok(string) if string.is_complete() => string.into_inner(),
Ok(_) => return Outcome::Error((Status::PayloadTooLarge, crate::Error::TooLarge)),
Err(e) => return Outcome::Error((Status::InternalServerError, crate::Error::Io(e))),
};
// Return successfully.
Outcome::Success(RequestBody(string))
Outcome::Success(
RequestBody(string)
)
}
}
@ -135,7 +139,7 @@ fn index(_info: RequestInfo) -> Template {
/// Processes /test get request and responds with some of the contents of the request
/// This function also stores information from the request in the database
#[get("/test")]
fn test_get(request: RequestInfo, cookies: Cookies) -> Template {
fn test_get(request: RequestInfo, cookies: &CookieJar<'_>) -> Template {
let client_id = cookies.get("mirror-id");
@ -187,7 +191,7 @@ fn test_get(request: RequestInfo, cookies: Cookies) -> Template {
/// Processes /test post request and responds with some of the contents of the request
/// This function also stores information from the request in the database
#[post("/test", data = "<body>")]
fn test_post(body: RequestBody, request: RequestInfo, cookies: Cookies) -> Template {
fn test_post(body: RequestBody, request: RequestInfo, cookies: &CookieJar<'_>) -> Template {
let client_id = cookies.get("mirror-id");
@ -245,7 +249,7 @@ fn test_post(body: RequestBody, request: RequestInfo, cookies: Cookies) -> Templ
/// Request function that returns a history of requests that the current client has made
/// The user can click a history_id and view the request itself
#[get("/history")]
fn history_req(cookies: Cookies) -> Template {
fn history_req(cookies: &CookieJar<'_>) -> Template {
// Get the client_id from the cookies
let client_id = cookies.get("mirror-id").unwrap().value();
@ -294,7 +298,7 @@ fn history_req(cookies: Cookies) -> Template {
/// request that was recorded to the database.
/// This includes the body of a post request, headers, cookies and query parameters.
#[get("/history/<history_id>")]
fn history_details(history_id: i64, cookies: Cookies) -> Template {
fn history_details(history_id: i64, cookies: &CookieJar<'_>) -> Template {
let client_id = cookies.get("mirror-id").unwrap().value();
@ -388,9 +392,9 @@ fn not_found(req: &Request) -> Template {
)
}
fn main() {
rocket::ignite()
.register(catchers![not_found])
#[launch]
fn rocket() -> _ {
rocket::build()
.mount(
"/",
routes![
@ -401,6 +405,6 @@ fn main() {
history_details
]
)
.register("/", catchers![not_found])
.attach(Template::fairing())
.launch();
}