# Setting Up an HTTP API

An optional feature serves commands and queries over HTTP.

To serve commands and queries with axum, turn on the feature `axum` of the crate, and add axum, and tower-http for the answer to a handler that panics:

```shell
cargo add architecturekit --features axum
cargo add axum@0.8
cargo add tower-http --features catch-panic
```

**The kit offers building blocks rather than routes**: every route is an ordinary handler of axum, which takes the request apart with extractors, builds a command or a query, and answers with what the kit answers. The building blocks live in the module `architecturekit::httpapi`. What the handlers need, such as the store, the deciders, and the projection that holds the views, goes into the state of the router, a struct that derives `Clone`, so that axum can hand a copy to every handler. Since `Store` can not be cloned, it goes there behind an `Arc`, as does everything else that is shared:

```rust
use std::sync::Arc;

use architecturekit::{Decider, DomainError, httpapi::answer_panic};
use axum::Router;
use tower_http::catch_panic::CatchPanicLayer;

#[derive(Clone)]
pub struct App {
  pub store: Arc<Store>,
  pub acquire_book: Arc<Decider<AcquireBook, Book, DomainError>>,
  pub borrow_book: Arc<Decider<BorrowBook, Book, DomainError>>,
  pub return_book: Arc<Decider<ReturnBook, Book, DomainError>>,
  pub catalog_projection: Arc<CatalogProjection>,
}
```

Then create the state, and the router with the routes of the commands and queries (see **[Handling Commands over HTTP](/docs/architecturekit/rust/handling-commands-over-http)** and **[Handling Queries over HTTP](/docs/architecturekit/rust/handling-queries-over-http)**). The layer `CatchPanicLayer` of tower-http, together with `answer_panic` of the kit, answers a handler that panics with `500 Internal Server Error`:

```rust
let app = App {
  store: Arc::new(store),
  acquire_book: Arc::new(acquire_book()),
  borrow_book: Arc::new(borrow_book()),
  return_book: Arc::new(return_book()),
  catalog_projection: Arc::clone(&catalog_projection),
};

let router: Router = Router::new()
  // ...
  .layer(CatchPanicLayer::custom(answer_panic))
  .with_state(app);
```

A handler answers a failure with an `HttpError`, which nearly every error of the kit turns into with `?`, by its category (see **[Mapping Errors to Status Codes](/docs/architecturekit/rust/mapping-errors-to-status-codes)**). **Every failure that an `HttpError` does not tell the caller in full is logged, once, when it is answered**: a failure of the server, answered with `500` or `503`, at level `error`, and a refusal whose details the caller is not told, such as one with `401`, `409`, or a `404` for a query that found no item, at level `info` (see **[Handling Commands over HTTP](/docs/architecturekit/rust/handling-commands-over-http)**). A panic that `answer_panic` answers is logged at level `error`, with its message. The kit logs with the `log` crate, under targets that start with `architecturekit`, so the records go to the logger the application installs for it, such as `env_logger`. Without a logger, they are dropped.

## Determining the User

The kit does not determine who is making a request, since that is up to the application. Define a type that describes the user, and implement the `FromRequestParts` trait of axum for it, with `HttpError` as its rejection. Every handler that takes the user as an argument then determines it first, and a request whose user can not be determined is refused before the handler runs:

```rust
use architecturekit::{Categorized, Category, httpapi::HttpError};
use axum::{
  extract::FromRequestParts,
  http::{header, request::Parts},
};

pub struct User {
  pub id: String,
  pub is_librarian: bool,
}

impl<S: Send + Sync> FromRequestParts<S> for User {
  type Rejection = HttpError;

  async fn from_request_parts(parts: &mut Parts, _: &S) -> Result<Self, HttpError> {
    let Some(token) = parts.headers.get(header::AUTHORIZATION) else {
      return Err(HttpError::unauthorized("the request carries no token"));
    };

    match verify(token).await {
      Ok(user) => Ok(user),
      Err(error) if error.category() == Some(Category::Transient) => Err(HttpError::of(error)),
      Err(error) => Err(HttpError::unauthorized(error)),
    }
  }
}
```

Here, `verify` stands for whatever your application uses to verify a token, such as a session store, and its error for the one it fails with, which implements `Categorized`. `HttpError::unauthorized` answers with `401 Unauthorized` and the fixed message `unauthorized`, since the cause may name internals, such as the key a token failed to verify with, and logs the cause at level `info`. **Not every failure means that the caller is unknown, though.** If the session store is down, for example, the error belongs to the category `Category::Transient`, and `HttpError::of` answers it with `503 Service Unavailable` and logs it at level `error`, rather than sending the caller off to sign in again.

A handler takes the user like any other extractor, before the body, since an extractor that reads the body comes last (see **[Validating Requests](/docs/architecturekit/rust/handling-commands-over-http#validating-requests)**). So a caller who is not known is refused before the body is read:

```rust
pub async fn handle_me(user: User) -> String {
  user.id
}
```

For an application without authentication, leave the extractor out. Its handlers then take no user.
