← Оглавление

6.4 Что приходит

Адрес несёт больше, чем направление. “Третий этаж, двенадцатая квартира” - это маршрут и одновременно данные о том, кто нужен. Хороший посыльный не спрашивает у двери, к кому он пришёл: прочитал по дороге. Обработчик получал факт прихода. Что написано на конверте - не смотрел.

Что нужно

Два обработчика получают в пути идентификатор задачи: GET /tasks/{id} и PATCH /tasks/{id}/done. Пока они его не видят - оба отвечают одинаково на любой номер.

Нужен способ сказать обработчику: в этом запросе есть {id}, он твой.

Сборка

axum передаёт значения из маршрута в обработчик через аргументы функции: видит тип каждого аргумента, берёт нужное из запроса и передаёт готовым.

Path<u64> - тип аргумента для пути. axum знает, что в маршруте есть {id}, извлекает его и преобразует в u64. Path(id): Path<u64> - деструктуризация: Path оборачивает значение, Path(id) раскрывает обёртку и связывает число с именем id.

Обновите crates/api/src/routes.rs:

// crates/api/src/routes.rs - CHANGED
use axum::{
    Router,
    extract::Path,
    routing::{get, patch, post},
};

async fn add() -> String {
    "TODO: add task".to_string()
}

async fn list() -> String {
    "TODO: list tasks".to_string()
}

async fn get_task(Path(id): Path<u64>) -> String {
    format!("task {id}")
}

async fn done(Path(id): Path<u64>) -> String {
    format!("marking {id} done")
}

pub fn router() -> Router {
    Router::new()
        .route("/tasks", post(add).get(list))
        .route("/tasks/{id}", get(get_task))
        .route("/tasks/{id}/done", patch(done))
}

add и list аргументов не получают: их маршруты не несут переменных частей. crates/api/src/main.rs не меняется.

Результат

$ make serve

В другом терминале:

$ curl localhost:3000/tasks/1
task 1

$ curl localhost:3000/tasks/42
task 42

$ curl -X PATCH localhost:3000/tasks/7/done
marking 7 done

Обработчики видят номер. Данных за ним пока нет. Но письмо теперь читается, не только конверт.

make ci проходит: те же 38 тестов.

Полный код tq для этой главы - 6-the-port/04-what-arrives/.


Lore: Как axum заполняет аргументы

Аргументы, которые axum заполняет из запроса, называются экстракторами (extractor). Path<T> - один из них. Механизм один для всех: axum видит тип аргумента, ищет реализацию трейта FromRequestParts или FromRequest и вызывает её. Если извлечь не удалось (например, {id} - не число), axum сам отвечает ошибкой, не вызывая обработчик.