diff --git a/README.md b/README.md index 462ca9b..695db74 100644 --- a/README.md +++ b/README.md @@ -2,16 +2,16 @@ ![Header](https://github.com/Dubzer/silly-cors/assets/18244287/cc653a45-dfd4-4bfe-b5bc-ea1393e91e40) -Hate browsers for CORS errors? Don't care about security and just want your thing to work? Thanks to this project, you can go silly with CORS! +Hate CORS errors? Don't care about security and just want your thing to work? Thanks to this project, you can go silly with CORS! -Silly CORS is a cors-proxy that sits between the browser and the recipient of the request. It automatically adds the necessary headers to satisfy browsers' cross-origin requirements. +Silly CORS is a cors-proxy that sits between the browser and request destination. It automatically adds the necessary headers to satisfy browsers' cross-origin requirements. > Note that CORS was not designed to annoy you, but is actually quite useful when properly configured. You shouldn't use CORS proxies in production. ### Requirements -This project is designed to be used in Docker behind a reverse proxy. If you don't have one, take a look at [traefik](https://traefik.io), using which will allow you to easily get a minimal setup with SSL certificates. +This service is designed to be used in Docker behind a reverse proxy. If you don't have one, take a look at [traefik](https://traefik.io), using which will allow you to easily get a minimal setup with SSL certificates. Architecture: ARM64 or x86_64 (AMD64) @@ -36,7 +36,6 @@ Silly CORS uses **environment variables** for configuration. All of them are opt Everything related to the proxy starts with **Silly**. #### Request headers -- `Silly-Host` - your desired destination host. It's **required**. - `Silly-Secret` - if you've configured `SECRET` env variable, place it's value in this header. #### Handling errors @@ -48,12 +47,13 @@ All errors from Silly CORS will have `Silly-Response=true` header in them. So yo Let's imagine we've started to get tired from all this sillines and want to reduce its amount by calling HTTP method **DELETE** on `https://api.service.example/cats/1`. -To do this, change the URL host to one where Silly CORS is deployed. In this example, it's `https://silly-cors.deployment`. Then, place a real host in the `Silly-Host` header. +To do this, add your destination to the Silly CORS deployment path. In this example, it's `https://silly-cors.deployment/`. And don't forget about trailing slash or you'll end up with an invalid domain! After awaiting a promise, we make sure that no errors has occured in Silly CORS by checking the header `Silly-Response`. ```js -const response = await fetch("https://silly-cors.deployment/cats/1", { +const url = "https://silly-cors.deployment/" + "https://api.service.example/cats/1"; +const response = await fetch(url, { method: "DELETE", headers: {"Silly-Host": "api.service.example"} }); diff --git a/src/handlers.rs b/src/handlers.rs index ce0c160..2eb6bb2 100644 --- a/src/handlers.rs +++ b/src/handlers.rs @@ -2,7 +2,6 @@ use std::str::FromStr; use hyper::{Body, Client, Request, Response, StatusCode, Uri}; use hyper::header::HeaderValue; -use hyper::http::uri::{Authority, Scheme}; use hyper_tls::HttpsConnector; use once_cell::sync::Lazy; @@ -16,21 +15,25 @@ static GLOBAL_CLIENT: Lazy>> .build(HttpsConnector::new())); pub async fn handle(mut req: Request, origin: HeaderValue) -> Result> { - let destination_header = req.headers_mut().remove("silly-host") - .ok_or(HandlerError::new_with_origin("can i hav some of that Silly-host header, pwease? 🥺", StatusCode::BAD_REQUEST, origin.clone()))?; + let path = req.uri().path_and_query() + .ok_or_else(|| Box::new(HandlerError::new_with_origin( + "sowwy, you seem to have forgotten to pass the path 🥺", StatusCode::BAD_REQUEST, origin.clone())))?; + + let path = &path.as_str()[1..]; - let authority = Authority::from_str(destination_header.to_str().unwrap()) - .map_err(|_| HandlerError::new_with_origin("your Silly-host header looks like an invalid domain 🥺", StatusCode::BAD_REQUEST, origin.clone()))?; + let destination_uri = Uri::from_str(path) + .map_err(|_| HandlerError::new_with_origin("sowwy, your destination path seems invalid 🥺", StatusCode::BAD_REQUEST, origin.clone()))?; - let mut uri_parts = req.uri().clone().into_parts(); - uri_parts.authority = Some(authority); - uri_parts.scheme = Some(Scheme::HTTPS); + let destination_host = destination_uri.authority() + .ok_or_else(|| HandlerError::new_with_origin("sowwy, you might forgot host in your destination", StatusCode::BAD_REQUEST, origin.clone()))?; - req.headers_mut().insert("Host", destination_header); - *req.uri_mut() = Uri::from_parts(uri_parts)?; + + req.headers_mut().insert("Host", HeaderValue::from_str(destination_host.as_str()).unwrap()); + *req.uri_mut() = destination_uri; let client_response = GLOBAL_CLIENT.request(req).await - .map_err(|err| HandlerError::new_with_origin(format!("oops, couldn't connect to destination :(\n{}", err), StatusCode::INTERNAL_SERVER_ERROR, origin.clone()))?; + .map_err(|err| HandlerError::new_with_origin( + format!("oops, couldn't connect to destination :(\n{}", err), StatusCode::INTERNAL_SERVER_ERROR, origin.clone()))?; let (mut parts, body) = client_response.into_parts(); parts.headers.extend(get_default_cors(origin.clone())); diff --git a/src/main.rs b/src/main.rs index 3f39445..bbc7f91 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,3 +1,5 @@ +#![allow(clippy::needless_return)] + use std::env; use hyper::{Body, HeaderMap, Method, Request, Response, Server, StatusCode};