Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I decode a URL and get the query string as a HashMap?

I have a URL like this:

http%3A%2F%2Fexample.com%3Fa%3D1%26b%3D2%26c%3D3

I parsed it with hyper::Url::parse and fetch the query string:

let parsed_url = hyper::Url::parse(&u).unwrap();
let query_string = parsed_url.query();

But it gives me the query as a string. I want to get the query string as HashMap. something like this:

// some code to convert query string to HashMap
hash_query.get(&"a"); // eq to 1
hash_query.get(&"b"); // eq to 2
like image 919
Saeed M. Avatar asked Apr 07 '17 08:04

Saeed M.


People also ask

Can I pass URL as query parameter?

Yes, that's what you should be doing. encodeURIComponent is the correct way to encode a text value for putting in part of a query string. but when it is decoded at the server, the parameters of url are interpreted as seperate parameters and not as part of the single url parameter.

How do I find the query string of a website?

The PHP Server object provides access to the query string for a page URL. Add the following code to retrieve it: $query_string = $_SERVER['QUERY_STRING']; This code stores the query string in a variable, having retrieved it from the Server object.

Does URL include query string?

A query string is a part of a uniform resource locator (URL) that assigns values to specified parameters.


2 Answers

There are a few steps involved:

  • The .query_pairs() method will give you an iterator over pairs of Cow<str>.

  • Calling .into_owned() on that will give you an iterator over String pairs instead.

  • This is an iterator of (String, String), which is exactly the right shape to .collect() into a HashMap<String, String>.

Putting it together:

use std::collections::HashMap;
let parsed_url = Url::parse("http://example.com/?a=1&b=2&c=3").unwrap();
let hash_query: HashMap<_, _> = parsed_url.query_pairs().into_owned().collect();
assert_eq!(hash_query.get("a"), "1");

Note that you need a type annotation on the hash_query—since .collect() is overloaded, you have to tell the compiler which collection type you want.

If you need to handle repeated or duplicate keys, try the multimap crate:

use multimap::MultiMap;
let parsed_url = Url::parse("http://example.com/?a=1&a=2&a=3").unwrap();
let hash_query: MultiMap<_, _> = parsed_url.query_pairs().into_owned().collect();
assert_eq!(hash_query.get_vec("a"), Some(&vec!["1", "2", "3"]));
like image 184
Lambda Fairy Avatar answered Oct 23 '22 13:10

Lambda Fairy


The other answer is good, but I feel that this is something that should be more straightforward, so I wrapped it in a function:

use {
   std::collections::HashMap,
   url::Url
};

fn query(u: Url) -> HashMap<String, String> {
   u.query_pairs().into_owned().collect()
}

fn main() -> Result<(), url::ParseError> {
   let u = Url::parse("http://stackoverflow.com?month=May&day=Friday")?;
   let q = query(u);
   println!("{:?}", q);
   Ok(())
}

Alternatively, I found another crate that does this for you:

use auris::URI;

fn main() -> Result<(), auris::ParseError> {
   let s = "http://stackoverflow.com?month=May&day=Friday";
   let u: URI<String> = s.parse()?;
   println!("{:?}", u.qs); // Some({"month": "May", "day": "Friday"})
   Ok(())
}

https://docs.rs/auris

like image 39
Zombo Avatar answered Oct 23 '22 13:10

Zombo