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

Create RequestExtension trait that allows for ureq-specific methods on http::Request #1011

Open
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

GeeWee
Copy link

@GeeWee GeeWee commented Feb 21, 2025

Creates a RequestExtension trait that will allow attaching ureq-specific methods to an http::Request.

Currently the only trait method is configure, which allows the creation of a ConfigurationBuilder from an http::Request. This method fixes #998.

…f HTTP requests without having to construct an agent.
Copy link
Author

@GeeWee GeeWee left a comment

Choose a reason for hiding this comment

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

I've tried to do my best to make this easy to merge in and match the existing style. I'd be happy to make changes if needed :)

@@ -553,6 +554,8 @@ pub mod tls;

#[cfg(feature = "cookies")]
mod cookies;
mod request_ext;
Copy link
Author

Choose a reason for hiding this comment

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

I wasn't sure whether to create a new file or not - I figured the request file maybe was long enough already? Would be happy to move it into that file if you want.

Copy link
Contributor

Choose a reason for hiding this comment

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

Looks good to me!

use crate::typestate::HttpCrateScope;
use crate::{http, Agent, AsSendBody};

/// Extension trait for [`http::Request<impl AsSendBody>`].
Copy link
Author

Choose a reason for hiding this comment

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

I've tried to match the style of documentation and examples to the existing styles, but lmk if you want any changes made.

///
/// This function will return a `ConfigBuilder` that can be used to set ureq-specific options.
/// The resulting method can be used with `ureq::run` or with an existing agent.
/// Configuration values set on the request takes precedence over configuration values set on the agent.
Copy link
Author

Choose a reason for hiding this comment

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

I think this is correct based on a glance of the source code? I wasn't quite sure, because ureq somewhere also describes it might be an error to run something created with one agent on another agent, and I'm not quite sure how this plays into this - as technically it's not created with any agent.

Copy link
Contributor

Choose a reason for hiding this comment

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

Yeah, I was just going to say. This is where it breaks down. When you do configure_request(), we clone the agent level config to make the request level config. And this config is further manipulated and later used in run.rs.

With this patch, this sequence of events would fail:

  1. Configure a bespoke agent with a global timeout of 10 seconds.
  2. Use RequestExt::configure() to set something else, like https_only(true).
  3. Run the configured Request on agent made in 1.

This would result in a request that does not have the 10 second timeout because we are below using Agent::new_with_defaults() as the starting point for the request level config.

I'm toying with the idea whether we can make an API that borrows the agent until the request is executed.

fn configure<'a>(self, agent: &'a Agent) -> ConfigBuilder<HttpCrateScope<'a, S>> {
...
}

and combine that with that instead of build() followed by Agent::run(), we expose run() straight on the builder. The call would be:

 let request: http::Request<()> = http::Request::builder()
                .method(http::Method::GET)
                .uri("http://foo.bar")
                .body(())
                .unwrap();
  request
        .configure()
        .https_only(false)
        .run()  // <---- run here

Copy link
Author

Choose a reason for hiding this comment

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

Yes I agree with the issue!

I've seen your other suggestion, but I think this is probably the crux of the issue, so will respond here first - I think it makes sense to finish this discussion before any of the other stuff becomes relevant.

Does the same issue not also happen if you use Agent::configure_request and then use ureq::run on the request afterwards?

I'm wondering if the more intuitive way to do this isn't to have each field on the request-based config be an Option and then default to the agent-based configuration if it's not set on the request level?

use crate::config::RequestLevelConfig;

#[test]
fn set_https_only_to_true_on_get_request() {
Copy link
Author

Choose a reason for hiding this comment

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

I've just tested that the request.extensions() get set properly. To be fair, seeing as this mostly calls into existing ureq-machinery, I consider these tests more "does the API work" tests, than actual test of the functionality :)

Copy link
Contributor

Choose a reason for hiding this comment

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

Sounds good!

@GeeWee GeeWee marked this pull request as ready for review February 21, 2025 08:09
Copy link
Contributor

@lolgesten lolgesten 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 looking at this!

Some thoughts.

@@ -553,6 +554,8 @@ pub mod tls;

#[cfg(feature = "cookies")]
mod cookies;
mod request_ext;
Copy link
Contributor

Choose a reason for hiding this comment

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

Looks good to me!

///
/// This function will return a `ConfigBuilder` that can be used to set ureq-specific options.
/// The resulting method can be used with `ureq::run` or with an existing agent.
/// Configuration values set on the request takes precedence over configuration values set on the agent.
Copy link
Contributor

Choose a reason for hiding this comment

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

Yeah, I was just going to say. This is where it breaks down. When you do configure_request(), we clone the agent level config to make the request level config. And this config is further manipulated and later used in run.rs.

With this patch, this sequence of events would fail:

  1. Configure a bespoke agent with a global timeout of 10 seconds.
  2. Use RequestExt::configure() to set something else, like https_only(true).
  3. Run the configured Request on agent made in 1.

This would result in a request that does not have the 10 second timeout because we are below using Agent::new_with_defaults() as the starting point for the request level config.

I'm toying with the idea whether we can make an API that borrows the agent until the request is executed.

fn configure<'a>(self, agent: &'a Agent) -> ConfigBuilder<HttpCrateScope<'a, S>> {
...
}

and combine that with that instead of build() followed by Agent::run(), we expose run() straight on the builder. The call would be:

 let request: http::Request<()> = http::Request::builder()
                .method(http::Method::GET)
                .uri("http://foo.bar")
                .body(())
                .unwrap();
  request
        .configure()
        .https_only(false)
        .run()  // <---- run here

use crate::config::RequestLevelConfig;

#[test]
fn set_https_only_to_true_on_get_request() {
Copy link
Contributor

Choose a reason for hiding this comment

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

Sounds good!

@lolgesten
Copy link
Contributor

Sorry I used my work github user. 🙈

@algesten algesten mentioned this pull request Feb 22, 2025
@GeeWee GeeWee requested a review from lolgesten February 26, 2025 04:50
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.

Missing a request builder that accepts request method as argument in ureq 3
2 participants