v0.5 Upgrade - Upgraded and modified project to support rocket.rs v0.5.1

This commit is contained in:
Camerin Figueroa 2024-07-03 23:34:25 +00:00
parent 00a6d33f4a
commit 29b509b3b4
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] [package]
name = "request-mirror" name = "request-mirror"
version = "0.1.0" version = "0.1.1"
edition = "2021" edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html # 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" chrono = "0.4.34"
diesel = { version = "2.1.4", features = ["postgres", "chrono"] } diesel = { version = "2.1.4", features = ["postgres", "chrono"] }
dotenvy = "0.15.7" 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 = { version = "1.0.197", features = ["derive"] }
serde_json = "1.0.114" serde_json = "1.0.114"
tokio = { version = "1.36.0", features = ["full"] } tokio = { version = "1.36.0", features = ["full"] }
[dependencies.rocket_contrib] [dependencies.rocket_dyn_templates]
version = "0.4.11" version = "0.2.0"
features = ["handlebars_templates", "tera_templates"] features = ["handlebars"]
[dependencies.uuid] [dependencies.uuid]
version = "1.7.0" version = "1.7.0"

View File

@ -1,6 +1,8 @@
FROM rustlang/rust:nightly as builder FROM rustlang/rust:nightly as builder
WORKDIR ./app WORKDIR /app
COPY . . COPY src ./src
COPY Cargo.toml .
COPY Cargo.lock .
RUN cargo install --path . RUN cargo install --path .
FROM rustlang/rust:nightly as runner 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 --from=builder /usr/local/cargo/bin/request-mirror /usr/local/bin/request-mirror
COPY ./templates /templates COPY ./templates /templates
COPY .env.docker /.env COPY .env.docker /.env
ENV ROCKET_ADDRESS=0.0.0.0 COPY Rocket.toml /
ENV ROCKET_PORT=80 ENV ROCKET_PROFILE=docker
ENV ROCKET_ENV=production
EXPOSE 80 EXPOSE 80
ENTRYPOINT diesel migration run --database-url $DATABASE_URL --migration-dir /migrations && request-mirror 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" address = "0.0.0.0"
port = 8000 port = 8000
keep_alive = 5 keep_alive = 5
read_timeout = 5 log_level = "normal"
write_timeout = 5
log = "normal"
limits = { forms = 32768 } limits = { forms = 32768 }
[staging] [release]
address = "0.0.0.0"
port = 8000
keep_alive = 5
read_timeout = 5
write_timeout = 5
log = "normal"
limits = { forms = 32768 }
[production]
address = "0.0.0.0" address = "0.0.0.0"
port = 80 port = 80
keep_alive = 5 keep_alive = 5
read_timeout = 5 log_level = "critical"
write_timeout = 5 limits = { forms = 32768 }
log = "critical"
[docker]
address = "0.0.0.0"
port = 80
keep_alive = 5
log_level = "critical"
limits = { forms = 32768 } limits = { forms = 32768 }
template_dir = "/templates/" template_dir = "/templates/"

View File

@ -27,7 +27,7 @@ pub fn establish_connection() -> PgConnection {
let database_url: String; let database_url: String;
match env::var(key) { match env::var(key) {
Ok(val) => database_url = val, Ok(val) => database_url = val,
Err(e) => { Err(_e) => {
dotenv().ok(); dotenv().ok();
database_url = env::var(key).expect("DATABASE_URL must be set"); 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] #[macro_use]
extern crate rocket; extern crate rocket;
use request_mirror::schema::{history, pair_records}; use request_mirror::schema::{history, pair_records};
use rocket::{data, request, Outcome, Request, Data}; use rocket::data::{FromData, ToByteUnit};
use rocket::data::FromDataSimple; use rocket::{data, Data};
use rocket::request::FromRequest; use rocket::request::{self, Request, FromRequest};
use rocket_contrib::templates::Template; use rocket::outcome::Outcome;
use rocket_dyn_templates::Template;
use serde::Serialize; use serde::Serialize;
use rocket::http::{Cookie, Cookies, Status}; use rocket::http::{Cookie, CookieJar, Status};
use uuid::Uuid; use uuid::Uuid;
use std::io::Read;
use request_mirror::models::*; use request_mirror::models::*;
use diesel::prelude::*; use diesel::prelude::*;
use request_mirror::*; use request_mirror::*;
@ -24,7 +22,9 @@ struct RequestInfo {
} }
#[derive(Debug)] #[derive(Debug)]
enum ApiError { enum Error {
TooLarge,
Io(std::io::Error),
} }
#[derive(Serialize, Debug, Clone)] #[derive(Serialize, Debug, Clone)]
@ -33,13 +33,14 @@ struct RequestBody(String);
// Always use a limit to prevent DoS attacks. // Always use a limit to prevent DoS attacks.
const LIMIT: u64 = 256; const LIMIT: u64 = 256;
impl<'a, 'r> FromRequest<'a, 'r> for RequestInfo { #[rocket::async_trait]
type Error = ApiError; impl<'r> FromRequest<'r> for RequestInfo {
type Error = Error;
/// Used for parsing request information and making it available for request functions to access /// 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 /// 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> { async fn from_request(req: &'r Request<'_>) -> request::Outcome<Self, Self::Error> {
let mut req_cookies = request.cookies(); let req_cookies: &CookieJar = req.cookies();
// Initially set cookie // Initially set cookie
if req_cookies.get(&"mirror-id").is_none() { 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 // 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. // one in the database and send it back to the client.
let new_uuid = Uuid::new_v4().to_string(); let new_uuid = Uuid::new_v4().to_string();
println!("Creating new cookie"); println!("Creating new cookie");
req_cookies.add(Cookie::new("mirror-id", new_uuid.clone())); req_cookies.add(Cookie::new("mirror-id", new_uuid.clone()));
let address = if request.client_ip().is_some() { let address = if req.client_ip().is_some() {
request.client_ip().unwrap().to_string() req.client_ip().unwrap().to_string()
} else { } else {
"Unknown".to_string() "Unknown".to_string()
}; };
@ -71,7 +71,7 @@ impl<'a, 'r> FromRequest<'a, 'r> for RequestInfo {
let mut query: Vec<Pair> = vec![]; let mut query: Vec<Pair> = vec![];
// Compile header // 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 key: String = row.name().to_string();
let value: String = row.value().to_string(); let value: String = row.value().to_string();
@ -87,15 +87,14 @@ impl<'a, 'r> FromRequest<'a, 'r> for RequestInfo {
} }
// Compile query // Compile query
let request_query = request.raw_query_items(); let request_query = req.query_fields();
if request_query.is_some() { for field in request_query {
for row in request_query.unwrap() {
let (key, value) = row.key_value_decoded();
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 // Send the Request Info as successful outcome
Outcome::Success(RequestInfo { Outcome::Success(RequestInfo {
header: header, header: header,
@ -105,19 +104,24 @@ impl<'a, 'r> FromRequest<'a, 'r> for RequestInfo {
} }
} }
impl FromDataSimple for RequestBody { #[rocket::async_trait]
type Error = String; impl<'r> FromData<'r> for RequestBody {
type Error = Error;
/// Used to extract the body of a request and make it available to request functions /// 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. // Read the data into a String.
let mut string = String::new(); let string = match data.open(LIMIT.mebibytes()).into_string().await {
if let Err(e) = data.open().take(LIMIT).read_to_string(&mut string) { Ok(string) if string.is_complete() => string.into_inner(),
return Outcome::Failure((Status::InternalServerError, format!("{:?}", e))); Ok(_) => return Outcome::Error((Status::PayloadTooLarge, crate::Error::TooLarge)),
} Err(e) => return Outcome::Error((Status::InternalServerError, crate::Error::Io(e))),
};
// Return successfully. // 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 /// 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 /// This function also stores information from the request in the database
#[get("/test")] #[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"); 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 /// 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 /// This function also stores information from the request in the database
#[post("/test", data = "<body>")] #[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"); 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 /// 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 /// The user can click a history_id and view the request itself
#[get("/history")] #[get("/history")]
fn history_req(cookies: Cookies) -> Template { fn history_req(cookies: &CookieJar<'_>) -> Template {
// Get the client_id from the cookies // Get the client_id from the cookies
let client_id = cookies.get("mirror-id").unwrap().value(); 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. /// request that was recorded to the database.
/// This includes the body of a post request, headers, cookies and query parameters. /// This includes the body of a post request, headers, cookies and query parameters.
#[get("/history/<history_id>")] #[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(); let client_id = cookies.get("mirror-id").unwrap().value();
@ -388,9 +392,9 @@ fn not_found(req: &Request) -> Template {
) )
} }
fn main() { #[launch]
rocket::ignite() fn rocket() -> _ {
.register(catchers![not_found]) rocket::build()
.mount( .mount(
"/", "/",
routes![ routes![
@ -401,6 +405,6 @@ fn main() {
history_details history_details
] ]
) )
.register("/", catchers![not_found])
.attach(Template::fairing()) .attach(Template::fairing())
.launch();
} }