Skip to content

Commit

Permalink
Accept destination as path
Browse files Browse the repository at this point in the history
  • Loading branch information
Dubzer committed Oct 6, 2023
1 parent 255edb2 commit 71b116d
Show file tree
Hide file tree
Showing 3 changed files with 22 additions and 17 deletions.
12 changes: 6 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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)

Expand All @@ -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
Expand All @@ -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"}
});
Expand Down
25 changes: 14 additions & 11 deletions src/handlers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand All @@ -16,21 +15,25 @@ static GLOBAL_CLIENT: Lazy<Client<HttpsConnector<hyper::client::HttpConnector>>>
.build(HttpsConnector::new()));

pub async fn handle(mut req: Request<Body>, origin: HeaderValue) -> Result<Response<Body>> {
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()));
Expand Down
2 changes: 2 additions & 0 deletions src/main.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
#![allow(clippy::needless_return)]

use std::env;

use hyper::{Body, HeaderMap, Method, Request, Response, Server, StatusCode};
Expand Down

0 comments on commit 71b116d

Please sign in to comment.