H. Desane
H. Desane

Reputation: 653

How can I parse query strings in actix-web?

How can I parse the name and color arguments from the following URL using actix-web?

http://example.com/path/to/page?name=ferret&color=purple

I suppose my path should be /path/to/page and then when I try to query for name I receive an empty string (req.match_info().query("name") where req: &HttpRequest).

The only documentation I found is about matching names (e.g., if the path is /people/{page}/ it'll match /people/123/ such that page = 123 but that's not what I want.

Upvotes: 31

Views: 20213

Answers (4)

gil.fernandes
gil.fernandes

Reputation: 14621

If you need default query parameters you can define them with the following code:


use actix_web::{App, get, HttpResponse, HttpServer, Responder, web, HttpRequest};

...

#[derive(Debug, Deserialize)]
pub struct Params {
    orgIds: String
}

...

async fn totd(db_pool: web::Data<Pool>, req: HttpRequest) -> impl Responder {
    let params = web::Query::<Params>::from_query(req.query_string())
        .unwrap_or(web::Query(Params { orgIds: String::from("2") }));
    let org_ids = &params.orgIds;
...

This applies to actix-web = "4"

Alternatively you can also use Query::<HashMap<String, String>>::from_query to parse the query.

Here is an example using from_query:

let params = Query::<HashMap<String, String>>::from_query(req.query_string())
        .unwrap();
let default_org_id = &String::from("2");
let default_lang = &String::from("en");
let org_ids = params.get("orgIds").unwrap_or(default_org_id);
let lang = params.get("lang").unwrap_or(default_lang);

With this second technique it is easier to deal with default values.

Upvotes: 2

pinsl
pinsl

Reputation: 121

actix_web::web::query parses query strings:

use actix_web::{web, App};
use serde_derive::Deserialize;

#[derive(Debug, Deserialize)]
pub struct Params {
    name: String,
    color: String,
}

#[get("/path/to/page")]
async fn handler(req: HttpRequest) -> HttpResponse {
    let params = web::Query::<Params>::from_query(req.query_string()).unwrap();
    HttpResponse::Ok().body(format!("{:?}", params))
}

The official documentation has another example.

Upvotes: 11

Rokit
Rokit

Reputation: 1141

It looks like they removed the query function and just have a query_string function. You could use a crate for this called qstring:

use qstring::QString;
...
let query_str = req.query_string(); // "name=ferret"
let qs = QString::from(query_str);
let name = qs.get("name").unwrap(); // "ferret"

You could also use an extractor to deserialize the query params into a struct with Serde

use serde::Deserialize;

#[derive(Deserialize)]
struct Info {
    username: String,
}

fn index(info: web::Query<Info>) -> Result<String, actix_web::Error> {
    Ok(format!("Welcome {}!", info.username))
}

Note that the handler will only be called if the query username is actually present in the request. This would call the handler:

curl "http://localhost:5000?username=joe"

but these would not:

curl "http://localhost:5000"
curl "http://localhost:5000?password=blah"

If you need optional parameters, just make the properties in your struct Options.

username: Option<String>

You can also use multiple web::Query<SomeType> parameters in a handler.

Upvotes: 36

H. Desane
H. Desane

Reputation: 653

This is for actix-web v0.7

I managed to get it work by using:

let name = req.query().get("name").unwrap(); // name = "ferret"

Upvotes: 5

Related Questions