thruster-rs / Thruster

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

[feature request] Make context.set(header_key, header_value) available to set header #226

Closed Israel-Laguan closed 1 year ago

Israel-Laguan commented 1 year ago

In several places of the documentation and examples, it mentions the use of context.set. i.e.:

https://github.com/thruster-rs/Thruster/blob/d80cf36ca3f8f40324dc5325a3c150aa5c833953/thruster/examples/custom_cors.rs#L39-L50

But when inspecting the types shows that set is not in the public API: https://github.com/thruster-rs/Thruster/blob/d80cf36ca3f8f40324dc5325a3c150aa5c833953/thruster/src/context/basic_context.rs#L191-L193

(the same in all possible contexts)

How can I set the headers without it? Or can this be in the public API?

Use cases

My specific usecase is to implement a middleware like helmet.js or csrf. I need to Remove certain headers, modify others, and create new ones.

What I tried

use hyper::header;
use thruster::context::basic_hyper_context::BasicHyperContext as Ctx;
use thruster::{middleware, MiddlewareNext, MiddlewareResult};

#[middleware]
pub async fn helmet(mut context: Ctx, next: MiddlewareNext<Ctx>) -> MiddlewareResult<Ctx> {
    match &context.hyper_request {
        Some(hyper_request) => {
            let mut headers = hyper_request.request.headers().to_owned();

            headers.remove(header::SERVER); // X-Powered-By or X-AspNet-Version are not used on thruster
            headers.append(
                header::CONTENT_SECURITY_POLICY,
                "default-src 'self';base-uri 'self';font-src 'self' https: data:;form-action 'self';frame-ancestors \
                 'self';img-src 'self' data:;object-src 'none';script-src 'self';script-src-attr 'none';style-src \
                 'self' https: 'unsafe-inline';upgrade-insecure-requests"
                    .parse()
                    .unwrap(),
            );
        }
        None => panic!("Problem when setting helmet headers."),
    }
    // context.set(some_key, some_value) <~ error here
    context = next(context).await?;

    Ok(context)
}

Error output

image

My PC

# Some info of my system
Linux Pop_OS! 22.10 Nvidia, x86_64, linux 5.19.0, bash
# Rust Version running
rustc 1.65.0-nightly
# in my Cargo.toml
thruster = { version = "1.2.4", features = ["hyper_server"]}
trezm commented 1 year ago

Good question(s)!

For what you tried, request is the incoming request, so grabbing any headers (or setting them!) would just affect the incoming side, not the outgoing side.

Israel-Laguan commented 1 year ago

For what you tried, request is the incoming request, so grabbing any headers (or setting them!) would just affect the incoming side, not the outgoing side.

Please explain to me how to change the outgoing headers 🥺 🙏🏻

trezm commented 1 year ago

It's like you were originally asking -- set and remove alter the outgoing headers.

You just need to remember to include the Context trait via use thruster::Context;

Israel-Laguan commented 1 year ago

I followed your suggestion and its working now: image

image

Thanks for the help @trezm!

Israel-Laguan commented 1 year ago

So to answer me, import use thruster::Context allows modifying "outgoing" headers, no need to make "set" public.