Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Question: Accessing State in OpenApiFromRequest Similar to FromRequest #151

Open
NewtTheWolf opened this issue Aug 31, 2024 · 4 comments
Open

Comments

@NewtTheWolf
Copy link

Hello rocket_okapi team,

I'm currently working on the zitadel-rust project and generating OpenAPI documentation using the OpenApiFromRequest trait. You can find the relevant PR here: smartive/zitadel-rust#559.

In this project, I need to configure the SecurityScheme for OpenID Connect, and the authority URL for this configuration is stored in Rocket's State.

In a typical request guard implementation using FromRequest, I can access the request object and retrieve the configuration from State like this:

#[async_trait]
impl<'request> FromRequest<'request> for &'request IntrospectedUser {
    type Error = &'request IntrospectionGuardError;

    async fn from_request(request: &'request Request<'_>) -> Outcome<Self, Self::Error> {
        // Accessing the authorization header
        let auth: Vec<_> = request.headers().get("authorization").collect();
        if auth.len() > 1 {
            return Outcome::Error((Status::BadRequest, &IntrospectionGuardError::InvalidHeader));
        } else if auth is_empty() {
            return Outcome::Error((Status::Unauthorized, &IntrospectionGuardError::Unauthorized));
        }

        let token = auth[0];
        if !token.starts_with("Bearer ") {
            return Outcome::Error((Status::Unauthorized, &IntrospectionGuardError::WrongScheme));
        }

        // Accessing the configuration from State
        let config = request.rocket().state::<IntrospectionConfig>();
        if config is_none() {
            return Outcome::Error((Status::InternalServerError, &IntrospectionGuardError::MissingConfig));
        }

        // Further processing...
    }
}

However, when working within the OpenApiFromRequest trait, I haven't found a way to similarly access the request object or State to retrieve the configuration data. Currently, I'm using figment to extract the configuration, like this:

let config: IntrospectionRocketConfig = figment
    .extract()
    .expect("authority must be set in Rocket.toml");

But I would prefer to directly access the State via the request, similar to how it's done in FromRequest, to keep consistency and avoid duplicating configuration extraction logic.

My Question:

Is it possible to access the request object within OpenApiFromRequest, or is there another recommended way to retrieve the State while generating OpenAPI documentation with rocket_okapi?

Thank you for your assistance!

@ralpha
Copy link
Collaborator

ralpha commented Nov 7, 2024

Hey, sorry for the late reply. But the request object is never available in rocket_okapi or OpenApiFromRequest
This is because the openapi.json file is generated at the time the macro is called. So it has no knowledge of anything happening at runtime. So it does not relay on/or see any request.
For some info: https://github.com/GREsau/okapi?tab=readme-ov-file#how-it-works

I see your MR got merged. So if this issue is no longer needed, you can close it.

@NewtTheWolf
Copy link
Author

Hey @ralpha thx for your response

yes the PR got merged, but the issue is still here
so everything happens in the Compile Time what also makes sense

So the way to go would be to use the Rocket Config file or something simmilar that can be accesed via the Compile time if i am right?

@ralpha
Copy link
Collaborator

ralpha commented Nov 8, 2024

You can do something during run time too, but although a bunch is done during compile time.
The moment the macro is called openapi_get_routes![] or similar you can some things.

But what exactly do you want to do? You want to change the OpenApi file depending on the Rocket.toml file?
You can always just intercept the spec and then link it yourself.
For example here.

let custom_route_spec = (vec![], custom_openapi_spec());

But you can even replace the mount_endpoints_and_merged_docs! to get even more control.
let openapi_docs = match rocket_okapi::okapi::merge::marge_spec_list(&openapi_list){

Line 164-168 creates all endpoint links.
Line 170-173 merges everything into 1 spec.
Line 175-182 mount so the openapi.json file is added to Rocket.

So if you want change any of that you can just create your own macro.

But if you describe your problem a bit more, I might be able to point you to exactly to what you can do.

@ralpha
Copy link
Collaborator

ralpha commented Nov 8, 2024

Also does the https://github.com/GREsau/okapi/tree/master/examples/secure_request_guard example not describe what you want to do?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants