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

Open APi spec file upload #80

Open
krlohnes opened this issue Jun 4, 2021 · 5 comments
Open

Open APi spec file upload #80

krlohnes opened this issue Jun 4, 2021 · 5 comments

Comments

@krlohnes
Copy link

krlohnes commented Jun 4, 2021

I have a multipart upload working just fine using a #[filter = "function"] on a request. Is there a way to add the open api spec for a file upload? id and version are documented just fine. The code looks roughly like this...

 #[post("/v1/resource/{id}/version/{version}")]
 #[openapi(
    id = "resource.upload",
    description = "Uploads a resource",
    summary = "Uploads a resource"
)]

pub async fn upload(
    id: String,
    version: String,
    #[filter = "multipart"] file_info: FileInfo) {
...
}

fn multipart() -> impl Filter<Extract = (FileInfo,), Error = Infallible> + Clone {
    rweb::header::<Mime>("content-type")
        .and(rweb::body::stream())
        .and_then(get_file_from_form)
        .recover(handle_rejection)
        .unify()
}
@E-gy
Copy link
Contributor

E-gy commented Jun 5, 2021

Considering that the file data comes from a filter, there isn't much that can be done to detect when a file upload is used.

Would an addition of a request attribute akin response work? Smthn like this:

#[post("/v1/resource/{id}/version/{version}")]
#[openapi(request(content = "image/png", schema = "Binary<String>"))]
pub async fn upload(
    id: String,
    version: String,
    #[filter = "multipart"] file_info: FileInfo) {
...
}```

@E-gy
Copy link
Contributor

E-gy commented Jun 5, 2021

On the other side, a more "rweb-y" way to do it would be to impl FromRequest for your own FileInfo, similar to how it is implemented for Json (then you shouldn't even need to use #[filter], transitioning the multipart into FromRequest.new)

Something like this:

impl FromRequest for FileInfo {
    type Filter = BoxedFilter<(FileInfo,)>;

    fn is_body() -> bool {
        true
    }

    fn content_type() -> &'static str {
        "image/png"
    }

    fn new() -> Self::Filter {
        rweb::header::<Mime>("content-type")
            .and(rweb::body::stream())
            .and_then(get_file_from_form)
            .recover(handle_rejection)
            .unify().boxed()
    }
}

#[post("/v1/resource/{id}/version/{version}")]
#[openapi(
    id = "resource.upload",
    description = "Uploads a resource",
    summary = "Uploads a resource"
)]
pub async fn upload(
    id: String,
    version: String,
    file_info: FileInfo) {
...
}

@kdy1
Copy link
Owner

kdy1 commented Jun 9, 2021

Seems like a good idea to me.
Maybe it worth adding a type to rweb.

i'm using rweb in work, and I'll see if it works well.

@E-gy
Copy link
Contributor

E-gy commented Jun 12, 2021

Maybe it worth adding a type to rweb.

Since FromRequest::content_type is there, it'd be nice to have const generics over &'static str.
But oh well, a static getter trait can probably work too... for the time being :D

@sahithyen
Copy link

sahithyen commented Nov 16, 2021

@kdy1 @E-gy I am interested in this feature. Is there already an implementation existing? If there is any help needed for implementation or documentation, I would gladly contribute.

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

4 participants