thruster-rs / Thruster

A fast, middleware based, web framework written in Rust
MIT License
1.07k stars 47 forks source link

How to set CORS with thruster? #215

Closed rts-gordon closed 2 years ago

rts-gordon commented 2 years ago

Hi @trezm I run a thruster-socketio server, need to set some special domains, but I didn't find any examples to show how to set CORS. May I know how to set CORS with Thruster?

Thanks a lot.

    use thruster::middleware::cors::cors;
    ...
    app.use_middleware("/", async_middleware!(Ctx, [cors]));
    ...
trezm commented 2 years ago

That looks like it should work, does it not?

This CORS opens up everything though, the code for a more specific one is pretty simple if you'd like to update it:

#[middleware_fn]
pub async fn cors<T: 'static + Context + Send>(
    mut context: T,
    next: MiddlewareNext<T>,
) -> MiddlewareResult<T> {
    context.set("Access-Control-Allow-Origin", "*");
    context.set("Access-Control-Allow-Headers", "*");
    context.set(
        "Access-Control-Allow-Methods",
        "GET, POST, PUT, DELETE, OPTIONS",
    );

    next(context).await
}

You'd adjust the fields as necessary.

rts-gordon commented 2 years ago

Thanks @trezm I update the code a little follow as yours, but it did not work. I can still access mydomain.com from other address, like wss://bridge.otherdomain.com.

#[middleware_fn]
async fn cors(mut context: Ctx, next: MiddlewareNext<Ctx>) -> MiddlewareResult<Ctx> {
    context.set("Access-Control-Allow-Origin", "wss://bridge.mydomain.com");
    context.set("Access-Control-Allow-Headers", "*");
    context.set(
        "Access-Control-Allow-Methods",
        "GET, POST, PUT, DELETE, OPTIONS",
    );

    next(context).await
}
rts-gordon commented 2 years ago

I add some conditions, and test with https://bridge.mydomain.com, but it still did not work.

    context.set("Access-Control-Allow-Credentials", "true");
trezm commented 2 years ago

what's the response look like if you curl that endpoint? Testing the builtin cors middleware I see all of the correct cors headers:

curl -v http://localhost:4321/plaintext
*   Trying ::1:4321...
* connect to ::1 port 4321 failed: Connection refused
*   Trying 127.0.0.1:4321...
* Connected to localhost (127.0.0.1) port 4321 (#0)
> GET /plaintext HTTP/1.1
> Host: localhost:4321
> User-Agent: curl/7.77.0
> Accept: */*
> 
* Mark bundle as not supporting multiuse
< HTTP/1.1 200 OK
< server: thruster
< access-control-allow-origin: *
< access-control-allow-headers: *
< access-control-allow-methods: GET, POST, PUT, DELETE, OPTIONS
< content-length: 13
< date: Fri, 25 Mar 2022 16:23:28 GMT
< 
* Connection #0 to host localhost left intact
Hello, World!%  

Is the context perhaps getting overwritten in some downstream middleware?

rts-gordon commented 2 years ago

I set the allow-origin to "https://bridge.mydomain.com", so if someone access from other domain, the access will be refused, is this correct? But I found that still can access this domain from other domains.

The curl response as follows:

$ curl -v http://localhost:3101/plaintext
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
  0     0    0     0    0     0      0      0 --:--:-- --:--:-- --:--:--     0*   Trying ::1:3101...
*   Trying 127.0.0.1:3101...
* Connected to localhost (127.0.0.1) port 3101 (#0)
  0     0    0     0    0     0      0      0 --:--:-- --:--:-- --:--:--     0> GET /plaintext HTTP/1.1
> Host: localhost:3101
> User-Agent: curl/7.73.0
> Accept: */*
>
* Mark bundle as not supporting multiuse
< HTTP/1.1 200 OK
< server: thruster
< access-control-allow-origin: https://bridge.mydomain.com
< access-control-allow-headers: *
< access-control-allow-methods: GET, POST, PUT, DELETE, OPTIONS
< access-control-allow-credentials: true
< content-length: 2218
< date: Fri, 25 Mar 2022 22:30:40 GMT
<
{ [2218 bytes data]
100  2218  100  2218    0     0   9728      0 --:--:-- --:--:-- --:--:--  9728<!doctype html>
<html>
  <head>
    <title>Socket.IO chat</title>
    <style>
      * { margin: 0; padding: 0; box-sizing: border-box; }
      body { font: 13px Helvetica, Arial; }
   ...
trezm commented 2 years ago

That looks correct to me, the initial page load should work, but any calls made by the page at localhost should fail. Are you seeing a fetch request on the page go through successfully as well?

On Fri, Mar 25, 2022, 6:41 PM Gordon @.***> wrote:

I set the allow-origin to "https://bridge.mydomain.com", so if someone access from other domain, the access will be refused, is this correct? But I found that still can access this domain from other domains.

The curl response as follows:

$ curl -v http://localhost:3101/plaintext % Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed 0 0 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0* Trying ::1:3101...

  • Trying 127.0.0.1:3101...
  • Connected to localhost (127.0.0.1) port 3101 (#0) 0 0 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0> GET /plaintext HTTP/1.1

    Host: localhost:3101 User-Agent: curl/7.73.0 Accept: /

  • Mark bundle as not supporting multiuse < HTTP/1.1 200 OK < server: thruster < access-control-allow-origin: https://bridge.mydomain.com < access-control-allow-headers: * < access-control-allow-methods: GET, POST, PUT, DELETE, OPTIONS < access-control-allow-credentials: true < content-length: 2218 < date: Fri, 25 Mar 2022 22:30:40 GMT < { [2218 bytes data] 100 2218 100 2218 0 0 9728 0 --:--:-- --:--:-- --:--:-- 9728<!doctype html> Socket.IO chat