ルーティング
パスパラメーター、クエリパラメーターについて
http://example.com/path/param1/param2?query1=param3&query2=param4
この URL の、param1
やparam2
のように、パスに埋め込まれている情報をパスパラメーターと呼びます。
また、パスパラメーターの後にkey=value&key=value&...
の形で埋め込まれる情報をクエリパラメーターと呼びます。この URL のparam3
とparam4
の部分です。
パスパラメーターを取得してみよう
"hello/{ユーザー名}"
というパスのリクエストが来たときに、以下を返すサーバーを書いてみましょう。
Hello, {ユーザー名}.
axum ではパスに/:hoge
のようなコロンから始まる文字列を含めると、ハンドラに渡される Path
という構造体に格納されます。 考えうるユーザー名全てに対して 1 つずつハンドラを設定するのは不可能なので、パスパラメーターを取得して、それをもとにレスポンスを生成します。
use axum::{extract::Path, routing::get, Router};
#[tokio::main]
async fn main() {
// GETリクエストの"/hello/:username"というパターンに対応するルートを設定し、
// URLのパラメータ(:username)を使用してhello_handler関数を呼び出す
let app = Router::new().route("/hello/:username", get(hello_handler));
// ポート8080でリスナーを作成する
let listener = tokio::net::TcpListener::bind("127.0.0.1:8080")
.await
.unwrap();
println!("listening on {}", listener.local_addr().unwrap());
// サーバーを起動する
axum::serve(listener, app).await.unwrap();
}
// ":username"というパスパラメーターを取得する
async fn hello_handler(Path(username): Path<String>) -> String {
format!("Hello, {}.\n", username)
}
サーバーを立て直した後、localhost:8080/hello/kenken にアクセスして実際に機能していることを確かめましょう。 また、URL の kenken
の部分を自分の名前や任意の文字列にしても動く事を確認しましょう。
/hello/:username
とすることでPath(username)
によってkenken
をとれることが分かりました。
参考
クエリパラメータを取得してみよう
/hello/kenken?page=2&lang=ja
パスパラメーターではPath(param)
を使いましたが、クエリパラメーターは受け取るための構造体を定義し、 Query(params)
を使って取得します。 クエリパラメータは順不同で?lang=ja&page=2
でも同じ意味になります。
基本問題
試しに、"hello/{ユーザー名}?lang={言語名}&page={ページ数}"
というパスのリクエストが来たときに、以下を返すサーバーを書いてみましょう。
Hello, {ユーザー名}.
language: {言語名}
page: {ページ数}
書いたらサーバーを立て直した後、localhost:8080/hello/kenken?page=5&lang=ja にアクセスして実際に機能していることを確かめましょう。
解答
use axum::{
extract::{Path, Query},
routing::get,
Router,
};
#[tokio::main]
async fn main() {
// GETリクエストの"/hello/:username"というパターンに対応するルートを設定し、
// URLのパラメータ(:username)を使用してhello_handler関数を呼び出す
let app = Router::new().route("/hello/:username", get(hello_handler));
// ポート8080でリスナーを作成する
let listener = tokio::net::TcpListener::bind("127.0.0.1:8080")
.await
.unwrap();
println!("listening on {}", listener.local_addr().unwrap());
// サーバーを起動する
axum::serve(listener, app).await.unwrap();
}
// クエリパラメータを受け取るための構造体を定義
#[derive(serde::Deserialize)]
pub struct HelloQueryParam {
lang: Option<String>,
page: Option<String>,
}
async fn hello_handler(
Path(username): Path<String>,
// クエリパラメータを受け取る
Query(query): Query<HelloQueryParam>,
) -> String {
format!(
"Hello, {}.\nlang: {}\npage: {}",
username,
query.lang.unwrap_or("".to_string()),
query.page.unwrap_or("".to_string())
)
}
このクエリパラメータは検索のリクエストを受け取るときに使うことが多いです。
例として、Google 検索だとこんな風になってます(Google検索のパラメータ(URLパラメータ)一覧)。