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

Request decompression #282

Merged
merged 20 commits into from Feb 24, 2023
Merged

Conversation

wanderinglethe
Copy link
Contributor

@wanderinglethe wanderinglethe commented Jul 9, 2022

Motivation

Currently compression and decompression of response bodies are supported with the Compression and Decompression services. Issue #276 proposes to also implement decompression for request bodies, this PR addresses that. To complete the compression and decompression modules, request compression could be added in another PR.

Solution

RequestDecompression decompresses the request body with the algorithm defined in the Content-Encoding header, it does not support multiple/stacked algorithms. When an algorithm is not supported it will return a 415 Unsupported Media Type by default, but it can also be configured to pass-through the request to the inner service.

Questions

This is my first PR and I am not sure if I am going in the right direction, I would already like some feedback while working on the issue.

Refactor decompression module

Will be done in a different PR.

Service and Future implementation

The service and future are based on the Decompression service and ResponseFuture, but I have the feeling the constraints are too complex. Can these be simplified?

And the same for the boxing of the bodies and errors, has this been done correctly?

API

I have copied the layer implementation from the request decompression layer to make the API uniform. The extra functionality is the pass-through of unsupported encodings, maybe later this can be changed into a single final decompression, that return the 415, and a stacked decompression that pops an encoding and pass-through to the next service.

Would this be a good first way to go?

General code style / conventions

Since I have the basic functionalities tested I can now refactor code. Are there any structures that can be written clearer or more concise? Or are there things that do not follow Rust or Tower conventions?

Todos

  • Documentation
  • Non-breaking decompression::Decompression, including docs
  • Refactor code structure / style

Thank you

Thank you for looking into this.

Still needs some refactor to remove duplicate code and needs documentation
Which either polls its inner future or returns 415 Unsupported Media Type
Copy link
Member

@davidpdrsn davidpdrsn left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I haven't read through the code yet and while I appreciate that you wanna refactor I would prefer if it was done in a separate PR. Makes it easier to review and bisect in case of bugs.

Is it possible for you to split things up?

@wanderinglethe
Copy link
Contributor Author

wanderinglethe commented Jul 9, 2022

Is it possible for you to split things up?

Of course, where should I locate the request decompression module and what should I name it?
Also how do you think we should name the layer and service? RequestDecompression or just Decompression distiquished by its module name?

@davidpdrsn
Copy link
Member

I'd call it RequestDecompression and put it in the decompression module if possible

@davidpdrsn
Copy link
Member

I think we should also consider making separate middleware for (de)compressing requests and responses rather than making one middleware do both. It's easy to apply both if that's what users want.

@wanderinglethe
Copy link
Contributor Author

I think we should also consider making separate middleware for (de)compressing requests and responses rather than making one middleware do both.

That is what I have done, right?

@davidpdrsn
Copy link
Member

Yes sorry. It was mostly a note to myself. Haven't actually read your code yet 😅

@wanderinglethe wanderinglethe marked this pull request as ready for review July 13, 2022 22:11
@wanderinglethe
Copy link
Contributor Author

I think most of the PR is completed and can be reviewed. Although my questions, in the first message, still stand.
@davidpdrsn could you run the workflow?

Thank you

@davidpdrsn
Copy link
Member

Thanks!

I'm not sure when I'll get time to review this. Going on vacation in a few days. So might not get time before I'm back in a few weeks.

@wanderinglethe
Copy link
Contributor Author

I'm not sure when I'll get time to review this. Going on vacation in a few days. So might not get time before I'm back in a few weeks.

Have a good vacation. I will see if I can work on some other PR or maybe I will take some vacation as well. :)

@reneklacan
Copy link

@davidpdrsn any chance you are back from vacation? 🙏 I'd also hugely appreciate getting this merged ❤️

@davidpdrsn
Copy link
Member

I am 😊 I'll try and have a look soon.

@wanderinglethe
Copy link
Contributor Author

Thank you

@reneklacan
Copy link

@davidpdrsn Thanks! Hope you had a lovely vacation

Copy link
Collaborator

@Nehliin Nehliin left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM!

@wanderinglethe
Copy link
Contributor Author

Do you have any critique on conventions, design or anything else?

LGTM!

@davidpdrsn
Copy link
Member

I still wanna look through. Please remain patient.

@wanderinglethe
Copy link
Contributor Author

wanderinglethe commented Aug 23, 2022

I still wanna look through. Please remain patient.

Thank you. That's what I expected, but maybe @Nehliin has some critique as well

@frxstrem
Copy link

frxstrem commented Oct 7, 2022

Any progress on getting this merged? At my workplace we have a need to support request decompression in our Axum/Hyper based services, and it would be much better if we get support from that in tower-http rather than doing it in our own codebase.

@mmd-osm
Copy link

mmd-osm commented Oct 25, 2022

Apologies if this question is asking the obvious. Would it be possible to specify the maximum permitted request body size after decompression in a lazy way somehow, ie. without uncompressing the whole payload, as to avoid excessive memory consumption?

@frxstrem
Copy link

Apologies if this question is asking the obvious. Would it be possible to specify the maximum permitted request body size after decompression in a lazy way somehow, ie. without uncompressing the whole payload, as to avoid excessive memory consumption?

@mmd-osm As far as I can tell, this is doing streaming decompression, so you should be able to apply a tower_http::limit::RequestBodyLimitLayer layer to limit the number of bytes in the request body. Applying that layer after the request decompression layer should apply the limit to the decompressed bytes.

Copy link
Member

@davidpdrsn davidpdrsn left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry for taking forever to review. First round of feedback is in! Generally I think this looks good. Mostly minor nitpicks here and there.

tower-http/src/decompression/mod.rs Show resolved Hide resolved
tower-http/src/decompression/request/future.rs Outdated Show resolved Hide resolved
tower-http/src/decompression/request/future.rs Outdated Show resolved Hide resolved
tower-http/src/decompression/request/future.rs Outdated Show resolved Hide resolved
tower-http/src/decompression/request/future.rs Outdated Show resolved Hide resolved
tower-http/src/decompression/request/layer.rs Outdated Show resolved Hide resolved
}

/// Passes through the request even when the encoding is not supported.
pub fn pass_through_unaccepted(mut self) -> Self {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this method should take a bool to similar to the set_* methods.

Then users can easily configure things based on things like env vars:

layer.passthrough_unaccepted(std::env::var("FOO").is_ok())

I believe it is also spelled passthrough and not pass through

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In my native language it would also be passthrough, but in English that is a noun and the verb is to pass through.

@davidpdrsn
Copy link
Member

Oh and CI should be fixed if you merge the latest master.

@wanderinglethe
Copy link
Contributor Author

Thank you for reviewing David. I have made the changes you requested.

@bruwozniak
Copy link

bruwozniak commented Jan 12, 2023

Would be amazing to see this merged :) thanks for the effort @wanderinglethe

Copy link
Member

@davidpdrsn davidpdrsn left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for working on this! Sorry for taking so long to review it.

@davidpdrsn davidpdrsn merged commit 67130ab into tower-rs:master Feb 24, 2023
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

Successfully merging this pull request may close these issues.

None yet

7 participants