Quickstart: run your first app

You will build: a one-file Rust server that answers GET /hello. Then you will change the response and rerun it.

Before you start: this repository checkout, current stable Rust, curl, and a terminal opened at the repository root — the directory containing crates/.

You do not need: Docker, a database, Node, or knowledge of the framework's architecture. --manifest-path means every command runs from the root without changing directories.

Your app will live in examples/my-first-app/. Its dependencies point at the framework source in this checkout, so you do not need a registry release or a framework CLI.

Which Rust version?

Use current stable. The main workspace declares Rust 1.85 and edition 2024, but the current dependency set has not been verified on that minimum version.

1. Create the application

Create a new directory so you do not overwrite an existing example:

sh
mkdir -p examples/my-first-app/src

If that directory already contains your work, choose another unused name under examples/ and substitute it in the commands.

Create examples/my-first-app/Cargo.toml:

examples/my-first-app/Cargo.tomltoml
[package]
name = "my-first-app"
version = "0.1.0"
edition = "2024"
publish = false

[workspace]

[dependencies]
axum = "0.8"
iet-http-axum = { path = "../../crates/features/iet-http-axum", features = ["host"] }
tokio = { version = "1", features = ["macros", "rt-multi-thread", "signal"] }
DependencyWhy it is here
axumConnect a URL to your handler.
iet-http-axumBuild the router and serve it using the framework's HTTP host.
tokioRun async code and wait for Ctrl+C.

[workspace] makes this application independent of the repository's main Cargo workspace. The path dependency uses the framework source in your checkout.

2. Write one endpoint

Create examples/my-first-app/src/main.rs with this complete program:

examples/my-first-app/src/main.rsrust
use axum::routing::get;
use iet_http_axum::{HostConfig, HttpHost, RestApi};

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
    let router = RestApi::new()
        .route("/hello", get(hello))
        .finish(());

    let config = HostConfig {
        address: "127.0.0.1:3012".parse()?,
        ..HostConfig::default()
    };

    let host = HttpHost::bind(config, router).await?;
    println!("Open http://127.0.0.1:3012/hello");

    host.run(async {
        let _ = tokio::signal::ctrl_c().await;
    })
    .await?;

    Ok(())
}

async fn hello() -> &'static str {
    "Hello from my application"
}

3. Run it and make a request

In your first terminal:

sh
cargo run --manifest-path examples/my-first-app/Cargo.toml

The first build downloads and compiles dependencies. When it is ready, it prints:

Expected terminal output
Open http://127.0.0.1:3012/hello

Leave it running. In a second terminal:

sh
curl http://127.0.0.1:3012/hello
Expected response body
Hello from my application

Checkpoint

You now have a running application—not a framework command or a generated server. Change the string in hello(), stop the process with Ctrl+C, rerun the Cargo command, and make the request again. You control the response.

4. Understand the four moving parts

sequenceDiagram
    participant C as curl
    participant H as HttpHost
    participant R as Axum route
    participant F as Your hello function
    C->>H: GET /hello
    H->>R: Pass request to router
    R->>F: Call hello()
    F-->>C: Hello from my application
In your programWhat it means
hello()Your code. Decides the response.
get(hello)Axum. Calls hello for a GET request.
RestApi::new()…finish(())Framework. Builds an Axum router with HTTP conventions. () means no shared application state yet.
HttpHost::bind / runFramework. Opens the listener and serves until your shutdown future resolves.

Local lesson, not a deployment

This endpoint has no authentication or concrete rate limiter. It binds only to loopback. Do not change it to a public address and assume security is installed.

Where to go next

  1. Accept and validate JSON — make the app take a POST /notes body and reject blank text.
  2. Run the browser starter — see a complete application: sign-in, server-rendered pages, forms, and a database.
  3. How the framework is built — the four kinds of crate and the full catalog behind the pieces you just ran.
It did not run: two things to check
  • Listener bind failed: stop the notes example or another process using port 3012, or change the port in both the program and curl command.
  • Cargo cannot find a path dependency: the app must be under examples/ in this checkout for the shown ../../crates/ paths to work.
IET Framework documentation — built with the IET Framework.