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

Response builder and related changes #580

Merged
merged 9 commits into from
Jun 27, 2020
Merged

Conversation

jbr
Copy link
Member

@jbr jbr commented Jun 10, 2020

This PR does several things that are related, but could be distinct PRs. Please let me know if you'd prefer I break them out for independent review.

  • changes insert_ext from taking mut self to taking &mut self to conform to the rest of the response interface
  • allows Response::set_status to take any TryInto<StatusCode> like Response::new() does
let mut res = Response::new(StatusCode::Ok);
res.set_status(203);
  • provides a From<Body> for Response and uses that conversion in other Body -> Response conversions that already existed. Extracted to provide a From<Body> for Response #584

  • adds a response builder:

app.at("/").get(|_| async {
    Ok(Response::builder(203)
        .body("body")
        .header("custom-header", "value"))
})

@jbr jbr force-pushed the response-builder branch 2 times, most recently from 74dc6f3 to 3f06463 Compare June 10, 2020 21:01
Copy link
Member

@Fishrock123 Fishrock123 left a comment

Choose a reason for hiding this comment

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

I don't have much critique on builders in general, though I do think if we do this we should also do RequestBuilder, for api conformity.

The code certainly seems fine to me, it's nice that ResponseBuilder is essentially a tuple and probably zero-ish-cost.

Re: other changes - I think From<Body> for Response is probably useful enough to already take out and merge. I literally already thought that existed!

src/response_builder.rs Outdated Show resolved Hide resolved

pub struct ResponseBuilder(Response);

impl ResponseBuilder {
Copy link
Member

Choose a reason for hiding this comment

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

Should this include methods for cookie and ext?

Copy link
Member Author

Choose a reason for hiding this comment

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

I initially added those, but I don't think they make a lot of sense on a builder. The purpose of the builder is to make expressing a one-off response easy. I think it's pretty reasonable to say if they need to make cookie or ext changes, that it's not a quick one-liner type response (before rustfmt). It's easy enough to do:

let mut res = Response::build().status(203).body("hello").unwrap();
res.add_cookie();
res.insert_ext();

Copy link
Member

Choose a reason for hiding this comment

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

Not exactly seeing the advantage of that to writing this if it is only partial?
The same example with less characters:

let mut res = Response::new(203);
res.set_body("hello");
res.add_cookie();
res.insert_ext();

Copy link
Member Author

Choose a reason for hiding this comment

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

Agreed, in that circumstance there isn't any advantage to using the builder

@jbr
Copy link
Member Author

jbr commented Jun 10, 2020

@Fishrock123 I agree surf might want a RequestBuilder, but why would tide? App authors aren't ever constructing requests

@Fishrock123
Copy link
Member

Good point, I think for some reason I was thinking this was in http-types.

@yoshuawuyts
Copy link
Member

Thanks so much for kicking this off @jbr! I'm not quite convinced on builders yet, but think this is def worth exploring. With a bit of luck this indeed turns out to be a much more convenient way to create Responses and that would be neat. I do have a few design notes though:

  1. We should rename the main method to Response::builder; build is the conventional name for the finalizer method, builder for the constructor.
  2. Response::builder should take Into<StatusCode> as the argument. It's 3 extra characters, that in many cases will save an extra line. It also creates parity with Response::new which doesn't assume a default status code either. For surf we'd require any form of Request::builder to take a url as an argument, so this creates symmetry there as well.
  3. Many of the examples use .into() as the finalizer. We should add build as an explicit method for this as well.
  4. We can remove the need to invoke the finalizer method in most cases if we change the return type of the enclosing function from -> tide::Result into -> tide::Result<Into<Response>>. This allows ResponseBuilder::Into to be called behind the scenes and saves an extra line in many cases.
    4b. Note that we can't yet express tide::Result as http_types::Result<impl Into<tide::Response>>. This requires lang support.
  5. In the examples for ResponseBuilder we should show the path we want people to take: namely by importing tide::Response and calling Response::builder. That's the canonical way to gain access to the struct, and I think we should use that in our examples as well.

@jbr
Copy link
Member Author

jbr commented Jun 12, 2020

Addressed 1, 2, 3, and 5. Added one example of 4, but not convinced it's particularly convenient to type in most circumstances

@jbr jbr added the enhancement New feature or request label Jun 19, 2020
src/response_builder.rs Outdated Show resolved Hide resolved
tests/chunked-encode-small.rs Show resolved Hide resolved
tests/chunked-encode-large.rs Show resolved Hide resolved
examples/chunked.rs Show resolved Hide resolved
Copy link
Member

@yoshuawuyts yoshuawuyts left a comment

Choose a reason for hiding this comment

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

💯

@jbr jbr merged commit f03ca44 into http-rs:master Jun 27, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants