Webシステム

Actix Web(actix-web)とは?Rustでの使い方とaxumとの違い【4.18.1で実行検証】

Actix Web(actix-web)とは?Rustでの使い方とaxumとの違い【4.18.1で実行検証】

Actix Web(クレート名は actix-web)は、Rustで書かれたWebフレームワークです。2026年10月28日時点の最新版は4.18.1(2026年10月23日公開)で、ビルドにはRust 1.89以降が必要です。本記事では4.18.1を rustc 1.99.1 で実際にビルドし、curlで応答を確かめたコードをもとに、インストールからルーティング、リクエストの受け取り方、状態共有とワーカー数、ミドルウェア、テスト、axumとの違い、2020年の「事件」の経緯までを順に説明します。

まとめ:Actix Webの要点と選びどころ

  • 現行は4.x系です。4.0.0(2022年2月25日)からメジャー版を上げずに機能追加を続けており、2026年10月だけで4.16.0から4.18.1まで4つの版が出ました。4.18.0でMSRV(最低サポートRustバージョン)は1.89になっています。
  • 4.16.0から、rustls-0_23 や openssl などのTLS機能を有効にしてもHTTP/2が自動では入りません。既定の機能を切っている構成では、http2 を明示しないとHTTP/1.1だけになります。
  • 名前はアクターモデル用の actix クレートに由来しますが、Webアプリを書くのに actix は不要です。ハンドラは普通の async fn で書きます。
  • 既定の挙動には落とし穴があります。パスの型変換に失敗すると400ではなく404、JSONボディの上限は2MiB(2,097,152バイト)、ワーカー数は公式ガイドの「物理CPU数」ではなく、Rust標準ライブラリが見積もる利用可能な並列度で決まり、検証環境では論理CPU数と同じ16でした(いずれも4.18.1で実測)。
  • Tokioのエコシステム(tower・tower-http)をそのまま使いたいならaxum、属性マクロで書けて4.xの互換性が4年以上続いている点を重く見るならActix Webが候補です。
  • 2020年1月に作者がunsafeの扱いを巡る批判で離脱しましたが、プロジェクトは引き継がれ、2026年も2月から10月までに8つの版が出ています。

Actix Webの現行版と位置づけ

Actix WebはHTTPサーバー、ルーティング、リクエストの型付き取り出し(エクストラクタ)、ミドルウェアを1つのクレートにまとめたフレームワークです。crates.ioの登録は2017年10月23日、1.0.0は2019年6月5日、現行の4.0.0は2022年2月25日に公開されました。crates.ioのactix-webのページによると、累計ダウンロード数は約8,764万、直近90日で約1,249万です(2026年10月28日時点)。Rust自体の基礎はRust入門の記事にまとめています。

4.13.0以降の版とMSRV

直近の版と、公式のCHANGES.mdに書かれた主な変更です。依存に actix-web = "4" と書くと4.x系の範囲から版が選ばれますが、どの版になるかは既存の Cargo.lock、使っているRustの版、有効にしたフィーチャで変わります。古いRustで cargo build が失敗したら、まずツールチェーンの版を疑ってください。4.18.0以降をビルドするにはRust 1.89以降が必要です。

版 公開日 MSRV 主な変更
4.18.1 2026-10-23 1.89 テスト用にTestRequest::query追加
4.18.0 2026-10-23 1.89 #[query]マクロ・MSRV引き上げ
4.17.0 2026-10-15 1.88 Acceptヘッダーの品質値の解析を修正
4.16.0 2026-10-12 1.88 TLS機能がhttp2を有効にしなくなる
4.15.0 2026-08-21 1.88 Error::add_response_mapper追加・io-uring実験機能を削除
4.14.0 2026-06-21 1.88 wrap後のto呼び出しでpanic・生Cookie取得
4.13.0 2026-02-18 1.88 MSRVを1.75から引き上げ・HTTP/2アップロード高速化

表の公開日はcrates.ioのUTC表記で、日本時間では1日後になる場合があります。4.15.0で experimental-io-uring フィーチャは削除されました。このフィーチャを有効にしたまま actix-web = "4" と書くと、cargoはエラーを出さずにフィーチャが残る4.14.1を選びます。古い記事の設定を写すときは、この指定が含まれていないか確認してください。

4.16.0でTLSとHTTP/2の機能が分離

4.15.0までは、Cargo.toml で rustls-0_23 や openssl を有効にすると、内部で http2 フィーチャも一緒に有効になっていました。4.16.0以降は両者が切り離され、TLSの機能定義から http2 が外れています(4.15.0と4.18.1の Cargo.toml を比較して確認)。

影響を受けるのは、ビルド時間や依存を減らすために既定の機能を切っている構成です。http2 は既定の機能(default)には今も含まれているので、actix-web = { version = "4", features = ["rustls-0_23"] } のように書いている場合は変わりません。次のように default-features = false にしている場合だけ、http2 を足さないとTLS接続でもHTTP/1.1しか話さなくなります。

[dependencies]
actix-web = { version = "4.18", default-features = false, features = ["macros", "rustls-0_23", "http2"] }

ビルドもテストもエラーにならず、ブラウザからの接続がHTTP/1.1に落ちるだけなので気付きにくい変更です。4.15以前から上げた環境では、curl -sI --http2 https://<ホスト>/ の1行目が HTTP/2 のままかを確かめてください。

actixクレートとアクターモデルの関係

旧来の解説には「Actix Webはアクターモデルで動く」と書かれたものが多いのですが、4.x系の actix-web はアクター用の actix クレートに依存していません。actix の最新版は0.13.5(2024年6月9日)で止まっています。WebSocketをアクターで扱うための actix-web-actors もREADMEで非推奨とされ、アクターを使わない actix-ws(0.4.0、2026年2月24日)への移行が案内されています。非同期処理の土台は actix-rt(2.15.0)で、READMEの説明は「Tokioベースのシングルスレッド非同期ランタイム」です。async/.await とTokioの関係はRustのasync/await入門を参照してください。

インストールとHello World

Rust 1.89以降とパッケージマネージャーのcargoが入っていれば、プロジェクトの作成と依存の追加は3コマンドで済みます。rustc --version が1.88以下なら、先に rustup update を実行してください。cargoの基本はCargoの使い方の記事を参照してください。

cargo new hello-actix
cd hello-actix
cargo add actix-web

cargo add を実行すると、Cargo.toml の [dependencies] に actix-web = "4.18.1" が追記されます。src/main.rs を次のように書き換えます。

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

#[get("/")]
async fn hello() -> impl Responder {
    HttpResponse::Ok().body("Hello, Actix Web!")
}

#[actix_web::main]
async fn main() -> std::io::Result<()> {
    HttpServer::new(|| App::new().service(hello))
        .bind(("127.0.0.1", 8080))?
        .run()
        .await
}

cargo run で起動し、別のターミナルから curl http://127.0.0.1:8080/ を実行すると Hello, Actix Web! が返ります。#[actix_web::main] は main 関数をactix-rtのランタイム上で動かすためのマクロで、HttpServer::new に渡すのはアプリの実体ではなく、アプリを作るクロージャ(ファクトリ)です。この違いは後の状態共有の章で効いてきます。

検証に使った環境(Intel Core i9-9880H、macOS)では、serdeとenv_loggerを含む依存を初めてビルドする cargo build に約2分30秒かかりました。2回目以降は差分ビルドなので数秒です。

ルーティングの書き方と分割

ルートの登録方法は2通りあります。上の例のように #[get] #[post] などの属性マクロを関数に付けて .service() で登録する方法と、.route("/users", web::get().to(handler)) のようにメソッドを組み立てる方法です。以降のコードはすべて1つの main.rs の抜粋で、serde と、ログ出力用の env_logger も使います。先に cargo add serde --features derive と cargo add env_logger を実行してください。Serdeの属性はSerde入門で解説しています。ファイル先頭の use は次のとおりです。

use std::sync::Mutex;

use actix_web::{
    body::MessageBody,
    dev::{ServiceRequest, ServiceResponse},
    error, get, http::StatusCode, middleware::{from_fn, Logger, Next}, post, web, App, Error,
    HttpResponse, HttpServer, Responder, ResponseError,
};
use serde::{Deserialize, Serialize};

#[derive(Deserialize)]
struct ListQuery {
    page: Option<u32>,
}

#[derive(Deserialize, Serialize)]
struct NewUser {
    name: String,
}

#[get("/users/{id}")]
async fn get_user(path: web::Path<u32>) -> Result<String, ApiError> {
    let id = path.into_inner();
    if id == 0 {
        return Err(ApiError::NotFound);
    }
    Ok(format!("user {id}"))
}

#[get("/users")]
async fn list_users(q: web::Query<ListQuery>) -> String {
    format!("page {}", q.page.unwrap_or(1))
}

#[post("/users")]
async fn create_user(body: web::Json<NewUser>) -> HttpResponse {
    HttpResponse::Created().json(body.into_inner())
}

fn config(cfg: &mut web::ServiceConfig) {
    cfg.service(get_user).service(list_users).service(create_user);
}

App 側では .service(web::scope("/api").configure(config)) と書くと、3つのルートがまとめて /api 配下に入ります。ユーザー関連は users.rs、注文関連は orders.rs のように、モジュールごとに config 関数を1つずつ公開する形にすると main が膨らみません。

4.14.0で追加されたRoute::wrapの順序チェック

ルート単位でミドルウェアを掛けるとき、web::get().wrap(mw).to(handler) の順に書くと、4.14.0以降はアプリの初期化時にpanicします。以前の版ではエラーにならず、ミドルウェアだけが黙って外れていました。4.18.1で実行したときのメッセージは次のとおりです。

Route middleware was already registered with `.wrap()`. Calling `.to()` now would replace the wrapped service and silently drop middleware. Call `.to()` before `.wrap()` (for example: `web::get().to(handler).wrap(mw)`).

正しい順序は web::get().to(handler).wrap(mw) です。4.13以前で動いていたコードを4.14以降へ上げたら起動直後に落ちた、という場合はこの順序を確認してください。

4.18.0で追加された#[query]とHTTPのQUERYメソッド

QUERYは、2026年6月にRFC 10008(Proposed Standard)として公開されたHTTPメソッドです。GETと同じく安全で冪等(同じリクエストを繰り返しても、サーバーへの意図した作用が1回送ったときと変わらない)でありながら、POSTのように検索条件をリクエスト本文に入れられます。条件が長くてURLに収まらない検索APIを、POSTで代用せずに書けるようになります。Actix Webは4.18.0で #[query] マクロと guard::Query() を追加しました。

use actix_web::{query, web, App, HttpServer};
use serde::Deserialize;

#[derive(Deserialize)]
struct Search {
    keyword: String,
}

#[query("/search")]
async fn search(body: web::Json<Search>) -> String {
    format!("search {}", body.keyword)
}

#[actix_web::main]
async fn main() -> std::io::Result<()> {
    HttpServer::new(|| App::new().service(search))
        .bind(("127.0.0.1", 8080))?
        .run()
        .await
}

前章のアプリに組み込む場合は、use に query を足し、App に .service(search) を加えます。起動して curl -X QUERY -H 'content-type: application/json' -d '{"keyword":"rust"}' http://127.0.0.1:8080/search で呼ぶと200と search rust が返りました。同じパスにGETやPOSTを送ると、405ではなく404です。手前にプロキシやCDNを置いている場合は、QUERYメソッドを通す設定になっているかも確認してください。

Path・Query・Jsonの受け取りと既定のエラー

ハンドラの引数に web::Path web::Query web::Json などを並べると、Actix Webがリクエストから値を取り出して型に変換します。これをエクストラクタと呼びます。変換に失敗したときはハンドラが呼ばれずに自動でエラー応答が返りますが、そのステータスはエクストラクタごとに違います。上のコードを4.18.1で動かし、curlで確かめた結果が次の表です。

リクエスト ステータス 返った本文(抜粋)
GET /api/users/abc 404 can not parse "abc" to a u32
GET /api/users?page=x 400 Query deserialize error
POST(nameが無いJSON) 400 Json deserialize error: missing field
POST(Content-Type無し) 400 Content type error
POST(2,100,012バイト) 413 JSON payload ... is larger than allowed

注意したいのは1行目です。パスの型変換の失敗は、既定では400 Bad Requestではなく404 Not Foundになります。APIの利用者に「IDの形式が違う」と伝えたいなら、web::PathConfig の error_handler で400へ差し替えてください。

JSONボディの上限2MiBとエラー応答の差し替え

web::Json の既定の上限は2,097,152バイト(2MiB)です。ソースの DEFAULT_LIMIT がこの値で、2,000,012バイトのJSONは201、2,100,012バイトは413になりました。web::Bytes や String でボディを受ける場合は別の設定(PayloadConfig)が効き、上限は262,144バイト(256KiB)です。上限を変えつつ、エラーの本文も自前の形式にしたいときは JsonConfig を app_data に登録します。

App::new()
    .app_data(web::JsonConfig::default().limit(4096).error_handler(|err, _req| {
        error::InternalError::from_response(err, HttpResponse::BadRequest().body("invalid json")).into()
    }))

この設定にすると、name が欠けたJSONへの応答は400の invalid json に変わります。既定のメッセージには構造体のフィールド名が含まれるため、外部公開のAPIでは差し替えておくほうが無難です。

ResponseErrorによる独自エラー型の応答変換

ハンドラの戻り値を Result<T, E> にし、E に ResponseError を実装すると、Err を返しただけで対応するステータスの応答になります。上の get_user は、IDが0のとき404と user not found を返します。

#[derive(Debug)]
enum ApiError {
    NotFound,
}

impl std::fmt::Display for ApiError {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        write!(f, "user not found")
    }
}

impl ResponseError for ApiError {
    fn status_code(&self) -> StatusCode {
        StatusCode::NOT_FOUND
    }
}

応答の本文には、fmt で書いた文字列がそのまま入ります。JSONで返したい場合は error_response も実装して HttpResponse を組み立ててください。

web::Dataによる状態共有とワーカー数(本番運用のベストプラクティス)

HttpServer は起動時に複数のワーカースレッドを立て、ワーカーごとに HttpServer::new のクロージャを呼んでアプリを1つずつ作ります。公式ガイドのApplicationの章は、クロージャの内側で作った状態はワーカーごとに別物になり、全体で共有するには外側で作ってクロージャへ移す必要がある、と書いています。DBのコネクションプールやカウンターは外側で作ります。

struct AppState {
    counter: Mutex<u64>,
}

#[get("/count")]
async fn count(data: web::Data<AppState>) -> String {
    let mut n = data.counter.lock().unwrap();
    *n += 1;
    format!("count {n}")
}

#[actix_web::main]
async fn main() -> std::io::Result<()> {
    env_logger::init_from_env(env_logger::Env::new().default_filter_or("info"));
    let state = web::Data::new(AppState { counter: Mutex::new(0) });

    HttpServer::new(move || {
        App::new()
            .app_data(state.clone())
            .wrap(Logger::default())
            .wrap(from_fn(add_header))
            .service(hello)
            .service(count)
            .service(web::scope("/api").configure(config))
    })
    .bind(("127.0.0.1", 8080))?
    .run()
    .await
}

web::Data の中身は Arc なので、clone() は参照カウントを増やすだけです。/count を2回呼ぶと count 1、count 2 と増えました。Mutex は std::sync::Mutex を使っています。SQLxのプールを渡す場合も同じ形で、マイグレーションの手順はSQLx CLIの記事にあります。

ワーカー数の既定値:公式ガイドと実装のずれ

公式ガイドのServerの章には、2026年10月時点でも「ワーカー数の既定値はシステムの物理CPU数」とあります。しかし依存先の actix-server 2.10.0のソースは std::thread::available_parallelism() で決めています。これはプログラムが利用できる並列度の推定値で、CPUの制限が無いマシンでは論理CPU数に一致するのが普通です。物理8コア・16スレッドの環境で4.18.1を起動したところ、ログは starting 16 workers でした。

ワーカーごとにDB接続を張る設計だと、この差で接続数が2倍になります。既定値の上限は512です(actix-server 2.9.4で追加)。Linuxではcgroupのクォータも反映されますが、読み取れない環境では多めに数えることがあるため、接続数を固定したい場合は .workers(4) のように明示してください。actix-server 2.9.8からはワーカーを並列に起動するため、ワーカーの多いサーバーほど待ち受け開始が早くなりました。その代わり、ファクトリのクロージャが1つずつ順番に呼ばれる前提で書いた初期化処理は、同期を足す必要があります。キープアライブの既定は5秒で、.keep_alive() で変えられます。

ワーカーを止めるブロッキング処理

1つのワーカーは自分に来たリクエストを1スレッドで処理します。ハンドラの中で std::thread::sleep や同期I/Oを呼ぶと、そのワーカーは終わるまで他のリクエストを処理できません。公式ガイドもこの書き方を「Bad practice」として挙げています。待ち時間は tokio::time::sleep(...).await のような非同期版に置き換え、重い同期処理は web::block で専用のスレッドプールへ逃がします。

リリースビルドとコンテナでの公開

本番では cargo build --release で最適化したバイナリを作ります。上のHello Worldを4.18.1でリリースビルドした実行ファイルは5,205,888バイト(約5.0MiB)で、strip でデバッグ用のシンボルを落とすと3,810,120バイト(約3.6MiB)になりました(macOS・x86_64)。依存クレートは実行ファイルに取り込まれるため、コンテナに入れるのは基本的にこのファイル1つです。ただしmacOSで作った実行ファイルはLinuxのコンテナでは動かないので、実行先のOSとCPUに合わせてビルドし直します。Linuxの既定のターゲットはglibcへ動的リンクするため、実行するイメージにもビルド時と互換のglibcが必要です。x86_64-unknown-linux-musl などのmuslターゲットで静的リンクすれば、この依存を外せます。

コンテナで動かすときに多い失敗が、待ち受けアドレスです。.bind(("127.0.0.1", 8080)) のままだとコンテナ内のループバックでしか待ち受けないため、docker run -p 8080:8080 でポートを公開しても外から届きません。.bind(("0.0.0.0", 8080)) にするか、環境変数からアドレスを読む形にしてください。ワーカー数もコンテナに割り当てたCPU数に合わせて .workers() で固定しておくと、前節のずれに振り回されません。

ミドルウェア:Loggerとfrom_fn

上の main ではミドルウェアを2つ掛けています。Logger はアクセスログを出す組み込みミドルウェアで、env_logger と組み合わせると次の形式で1リクエスト1行が出ます。

[2026-10-27T17:01:55Z INFO  actix_web::middleware::logger] 127.0.0.1 "GET /api/users/42 HTTP/1.1" 200 7 "-" "curl/8.7.1" 0.000347

独自の処理を挟むなら、4.9.0(2024年8月10日)で追加された middleware::from_fn が手軽です。それ以前も App::wrap_fn でクロージャを渡す簡易ミドルウェアは書けましたが、関数として切り出して wrap で使い回すには Transform と Service の2つのトレイトを実装する必要があり、数十行の定型コードになっていました。次の関数は、後続の処理が正常に返した応答に x-app: demo ヘッダーを付けます。

async fn add_header(
    req: ServiceRequest,
    next: Next<impl MessageBody>,
) -> Result<ServiceResponse<impl MessageBody>, Error> {
    let mut res = next.call(req).await?;
    res.headers_mut().insert(
        actix_web::http::header::HeaderName::from_static("x-app"),
        actix_web::http::header::HeaderValue::from_static("demo"),
    );
    Ok(res)
}

next.call(req).await より前に書いた処理はハンドラの前に、後に書いた処理はハンドラの後に走ります。後続が Err を返した場合は ? でそのまま返るため、ヘッダーは付きません。認証ヘッダーの検査なら next.call の前でヘッダーを読み、足りなければ Err を返します。

セッションとCORSは本体ではなく actix-extras の別クレートです。actix-session(0.11.0)は SessionMiddleware を wrap し、保存先をCookie(cookie-session フィーチャ)かRedis(redis-session フィーチャ)から選びます。CORSは actix-cors(0.7.2)、静的ファイル配信は actix-files(0.7.2)を使います。

actix_web::testによるハンドラのテスト

サーバーを起動せずにハンドラを呼び出すテストは、本体に含まれる actix_web::test で書けます。追加のクレートは要りません。

#[cfg(test)]
mod tests {
    use super::*;
    use actix_web::test;

    #[actix_web::test]
    async fn hello_returns_200() {
        let app = test::init_service(App::new().service(hello)).await;
        let req = test::TestRequest::get().uri("/").to_request();
        let resp = test::call_service(&app, req).await;
        assert_eq!(resp.status(), StatusCode::OK);
        let body = test::read_body(resp).await;
        assert_eq!(body, "Hello, Actix Web!");
    }
}

4.18.1での cargo test の結果は、このテストが ok でした。ステータスが200であることと本文の両方を確かめているので、ハンドラが201や空の本文を返すように変わればテストが落ちます。init_service には本番と同じ App の組み立てを渡せるので、configure(config) で分割しておくとテストでも同じルート定義を使い回せます。QUERYメソッドのハンドラを試すときは、4.18.1で追加された TestRequest::query() を使います。

axumとの違いと選び方

RustのWebフレームワークでActix Webと並んで比較されるのが、Tokioの開発チームが作るaxum(2026年10月時点で0.8.9)です。どちらもTokioの上で動くため、選定の分かれ目は性能より設計の土台です。

観点 Actix Web 4.18.1 axum 0.8.9
ランタイム actix-rt(ワーカーごとに単一スレッド) Tokio(通常はマルチスレッド)
ミドルウェア 独自のTransform・from_fn towerのServiceを共有
ルート定義 属性マクロも使える マクロなしでRouterへ登録
版の安定性 2022年から4.x 0.x(マイナー版で破壊的変更)

tower-httpのタイムアウトや圧縮、gRPCのtonicと同じミドルウェアを使い回したいならaxumを選びます。属性マクロでルートを宣言したい、あるいは版上げのたびにコードを直す手間を減らしたいならActix Webです。ただしワーカーごとに状態が分かれる設計なので、共有したいものは必ずクロージャの外で作る、という前章の規則は守る必要があります。axum側の書き方と両者の詳しい比較表はAxumの解説記事にあります。どちらで組むか決めきれない段階のAPI設計から相談したい場合は、弊社のAPI開発・システム連携でも受けています。

axum以外の選択肢:Rocket・Salvo・ntex・Loco

比較記事で名前が挙がるほかのフレームワークは、2026年10月28日時点で次の版です。直近90日のダウンロード数は、axumが約1億4,325万、Actix Webが約1,249万で、Rocketは約226万でした。axumの数字は他のクレートの依存として入る分を含むので、そのまま利用者数の差とは読めません。

クレート 最新版 公開日 特徴
rocket 0.5.2 2026-10-23 属性マクロ中心・0.5.1から約2年半ぶり
salvo 1.0.1 2026-10-04 1.0.0は2026-09-24
ntex 4.4.1 2026-10-27 Actix Webの原作者が開発
loco-rs 1.2.0 2026-09-24 axumの上に載るRails風の全部入り

業務のAPIサーバーで迷ったら、採用例と周辺クレートの多さでaxumかActix Webの2択から始めるのが現実的です。Rocketは2024年5月の0.5.1から2026年10月まで版が出ていなかった時期があるため、長期保守の案件では更新の頻度を確かめてから選んでください。

2020年のunsafe騒動とその後の体制

「actix-web 事件」と呼ばれるのは、2020年1月の作者離脱の件です。当時のActix Webはunsafeコードを多用しており、メモリ安全性を破る箇所が指摘された際、作者のNikolay Kim氏(GitHubではfafhrd91)が修正パッチを採らず、報告のissueを削除したことで批判が集まりました。同氏は2020年1月17日ごろに公開した「Actix project postmortem」で「I am done with open source.」と書き、リポジトリを個人アカウントへ移しました。

その後リポジトリはactix組織に戻され、開発はコミュニティの保守者に引き継がれました。2026年10月28日時点のGitHubの集計では、コミット数はfafhrd91氏が2,475件で最多、次いでrobjtede氏が1,017件で、作者離脱後も4.x系のリリースは継続しています。現在の版で本番採用を避ける理由にはなりませんが、依存クレートにunsafeが含まれるかを気にする組織なら、cargo-geiger(0.13.0)などで自分の依存ツリーを数えてから判断してください。

「速い」の根拠とベンチマークの現状

Actix Webの速さの根拠としてよく挙がるのが、TechEmpower Framework Benchmarksです。ただしこのベンチマークは2025年3月17日に公式ブログで発表されたRound 23(結果の確定は同年2月)が最後の回で、GitHubのリポジトリは2026年3月24日にアーカイブ(読み取り専用)になりました。公開済みの結果はRound 23当時の版で測ったもので、4.18.1や現行のaxumの性能を示すものではありません。

アーカイブ時点のリポジトリには、Rustの実装だけでactix・axum・ntex・xitca-webなど32件が置かれています。ベンチマーク用の実装はDB接続やシリアライズを極限まで詰めたコードで、一般的なAPIサーバーの書き方とは違います。自社のAPIで性能を見積もるなら、実際のハンドラとDBを使って負荷をかけるほうが確実で、Rust製の負荷試験ツールの使い方はGooseの記事で紹介しています。

よくある質問

Actix Webの読み方は?

公式の読み方は示されていませんが、日本語では「アクティクス・ウェブ」「アクティックス・ウェブ」と表記されます。公式サイト(actix.rs)の表記は「Actix Web」、crates.ioのクレート名は actix-web で、コード中では actix_web と書きます。

Actix Webの最新バージョンはいくつですか?

2026年10月28日時点の最新安定版は4.18.1(2026年10月23日公開)で、ビルドにはRust 1.89以降が必要です。10月だけで4つの版が出ているように更新の間隔が短いため、導入前にcrates.ioのactix-webのページで最新版を確認してください。

Actix Webを使うのにactixクレートやアクターの知識は必要ですか?

必要ありません。4.x系の actix-web はアクター用の actix クレートに依存しておらず、ハンドラは async fn で書きます。WebSocketもアクター不要の actix-ws で書けます(アクター連携用の actix-web-actors は非推奨)。

Actix Webでセッション管理をするには?

actix-session クレートを追加し、SessionMiddleware を App に wrap します。保存先はCookieに入れる CookieSessionStore(cookie-session フィーチャ)か、Redisに置く RedisSessionStore(redis-session フィーチャ)から選びます。

パスパラメータの型が合わないと404になるのはなぜですか?

web::Path の変換エラーは、既定で404 Not Foundを返す仕様だからです。4.18.1で Path<u32> に abc を渡すと、404と can not parse "abc" to a u32 が返りました。400にしたい場合は web::PathConfig の error_handler で差し替えます。

関連記事

お気に入りに入れた記事の一覧

この記事は以下の記事からリンクされています

資料請求

今日のトレンド記事 直近 24 時間で、いつもより多く読まれている記事

  1. 2026.10.27 テックブログ Brotli 脆弱性:CVE-2026-111497の影響確認とNode.js・Python・.NETの更新手順
  2. 2026.10.28 テックブログ リンツ不正アクセス:314万件の対象確認とパスワード強制リセット後の対処
  3. 2026.10.27 テックブログ Joshin(ジョーシン)不正アクセス:最大600万件の対象とサブスク初期パスワードの対処
  4. 2026.10.29 テックブログ So-net情報漏洩:258万件の対象確認とメールのパスワード再設定、窓口の番号
  5. 2026.10.23 テックブログ Renta!はいつ再開?不正アクセスでメールアドレス等が流出したおそれ・再開時のパスワード再設定と運営側の対応

RELATED POSTS 関連記事

目次