Skip to content

Panic when making request, could not parse Url as Uri #668

@timvisee

Description

@timvisee

I just came across a panic in the latest reqwest release (both 0.10 and master). This happens when making a request.

It seems that some input in Client.get(url) parses successfully as URL at first, and then panics when attempting to parse the URL as http::Uri (internally).

Example

Here's a very basic (abstracted) example that causes this panic:

#[tokio::main]
async fn main() -> Result<(), reqwest::Error> {
    reqwest::Client::new()
        .get("http://\"")
        .send()
        .await?;
    Ok(())
}

Which outputs:

thread 'main' panicked at 'a parsed Url should always be a valid Uri: InvalidUri(InvalidUriChar)', src/libcore/result.rs:1165:5
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace.

I believe the Client.get(url) function should return an error in all cases where the URL is invalid. This actually happens when providing something like "http://a b" (InvalidDomainCharacter). However, "http://\"" succeeds and panics when making the request with .send().

The panic is located here.

Assumption

I have the following assumption on what is going on:

I think Url is used first to parse the provided URL (here). Then the assumption is made this URL is valid once parsing succeeds. Internally, when making a request through hyper, this URL is parsed to an Uri. Assuming the URL is valid this should always succeed, but it does not. That probably means that either implementation of Url or Uri is incorrect, or at least not compatible.

Al right. I'm not too familiar with the URL/URI specs, and don't want to go through it right now, to confirm either implementation is correct.

Fixing this

I see the following options:

  • Immediately parse to an Uri when creating the request (and check for validity).
  • Fix Url implementation (if invalid)
  • Fix Uri implementation (if invalid)
  • Use Uri throughout the crate.
  • Propagate this parsing issue up to the calling function, return as error in a Result.

I think the first is easiest to do on a short notice.

What would be the correct way of doing things? What are your thoughts, is the assumption I made right, and is this undesired behaviour?

I might be happy to implement a fix for this in code once I know what path I should take.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions