Using hyper: how to get URL query string params?

Given a GET url: http://example.com/data?key1=value1&key2=value2, I can get the "query part" via

let params = request.uri().query().unwrap();
// params = "key1=value1&key2=value2"

But, how do I get the values of key1 and key2? Is splitting the string by "&" and then by "=" the only way?
I looked at hyper::Uri - Rust, but it didn't help.

3 Likes

Hyper does not have a built-in method to do that. However, the url crate has the url::Url::query_pairs() method and it's already a dependency of hyper, so you won't need to download anything new.
To convert a Uri from hyper into a Url from url, use url::Url::parse(&request.uri().to_string()) (returns a Result).

In your example, the code would be

let uri_string = request.uri().to_string();
let request_url = Url::parse(&uri_string).unwrap();
let params = request_url.query_pairs();

// or:
let params = Url::parse(&request.uri().to_string()).unwrap().query_pairs();

This method returns an Iterator of (key, value) pairs. So you can collect it into a Vector with params.collect() or you can iterate over it with for param in params { /* ... */ }. Or use any Iterator methods

Note: Hyper did have a Request::query_pairs but in 0.11 they removed it for some reason. I could not find anything related to that change in the changelog of 0.11.

2 Likes

This is one of the first replies in the search results, but it's a bit outdated, and is a good idea to keep it up to date.

On latest hyper I'm not getting full URL with Request::uri() it, just gives me the path without the host. This means that Url::parse(&uri_string).unwrap() always fails, even if it contains the query parameters.

I found out I can just do this:

// use std::collections::HashMap;
// use url::form_urlencoded::parse;
// request : hyper::Request<...>
let params: HashMap<String, String> = request
    .uri()
    .query()
    .map(|v| {
        url::form_urlencoded::parse(v.as_bytes())
            .into_owned()
            .collect()
    })
    .unwrap_or_else(HashMap::new);

And it doesn't require full URI, just the query string given by the request itself.

7 Likes

Thank you, your answer is very useful to me. I found that this may need to be updated.

In Rust version 1.55.0, execution error:

unwrap_or_else(HashMap::new())
                           ^^^^^^^^^^^^^^ expected an `FnOnce<()>` closure, found `HashMap<_, _>`

HashMap::new should be passed in as a function and not be called directly. So remove the () at the end to resolve the error.

:sweat: It's my mistake.

This topic was automatically closed 30 days after the last reply. We invite you to open a new topic if you have further questions or comments.