### Basic Fluent Setup with Vapor Source: https://github.com/hummingbird-project/hummingbird-docs/blob/main/Hummingbird.docc/HummingbirdFluent/HummingbirdFluent.md Demonstrates the initial setup of Fluent within a Vapor application, including adding a SQLite database and defining a basic route to fetch a Todo item. ```swift let fluent = Fluent() // add sqlite database fluent.databases.use(.sqlite(.file("db.sqlite")), as: .sqlite) // add router with one route to return a Todo type let router = Router() router.get("todo/{id}") { request, context in let id = try await context.parameters.require("id", as: UUID.self) return Todo.find(id, on: fluent.db()) } var app = Application(router: router) // add fluent as a service to manage its lifecycle app.addServices(fluent) try await app.runService() ``` -------------------------------- ### Perform Actions Before Server Starts Source: https://github.com/hummingbird-project/hummingbird-docs/blob/main/Hummingbird.docc/Articles/ServiceLifecycle.md Execute custom processes, like database migrations, before the HTTP server starts by using the `beforeServerStarts(perform:)` method. ```swift var app = Application(router: router) app.addServices(dbClient) app.beforeServerStarts { try await dbClient.migrate() } try await app.runService() ``` -------------------------------- ### Create an HTTP1 Server Source: https://github.com/hummingbird-project/hummingbird-docs/blob/main/Hummingbird.docc/HummingbirdCore/HummingbirdCore.md This example demonstrates how to create an HTTP1 server that always returns a response containing 'Hello' in the body. It configures the server with a specific channel setup, address, event loop group, and logger. ```swift let server = Server( childChannelSetup: HTTP1Channel { (_, responseWriter: consuming ResponseWriter, _) in let responseBody = ByteBuffer(string: "Hello") var bodyWriter = try await responseWriter.writeHead(.init(status: .ok)) try await bodyWriter.write(responseBody) try await bodyWriter.finish(nil) }, configuration: .init(address: .hostname(port: 8080)), eventLoopGroup: eventLoopGroup, logger: Logger(label: "HelloServer") ) ``` -------------------------------- ### Setup JobsPostgres with PostgresClient and Migrations Source: https://github.com/hummingbird-project/hummingbird-docs/blob/main/Hummingbird.docc/JobsPostgres/JobsPostgres.md Configure and initialize the JobsPostgres driver with a Postgres client, migrations, and custom configuration. Ensure logger is provided. ```swift import JobsPostgres import PostgresNIO import ServiceLifecycle let postgresClient = PostgresClient(...) let postgresMigrations = DatabaseMigrations() let jobService = JobService( .postgres( client: postgresClient, migrations: postgresMigrations, configuration: .init( pollTime: .milliseconds(50), queueName: "MyJobQueue" ), logger: logger ), logger: logger ) ``` -------------------------------- ### Create and Run a Basic Hummingbird Application Source: https://github.com/hummingbird-project/hummingbird-docs/blob/main/Hummingbird.docc/Hummingbird/Application.md Demonstrates how to create a router, define a simple GET route, and initialize an Application with the router and an HTTP/1 server. The application is then run. ```swift let router = Router() router.get("hello") { _,_ in return "hello" } // create application let app = Application( router: router, server: .http1() // This is the default value ) // run application try await app.runService() ``` -------------------------------- ### Run Hummingbird Application Source: https://github.com/hummingbird-project/hummingbird-docs/blob/main/Hummingbird.docc/Articles/GettingStarted.md Execute this command to build and run your Hummingbird application after setup. ```bash swift run ``` -------------------------------- ### Setup Valkey Job Service Source: https://github.com/hummingbird-project/hummingbird-docs/blob/main/Hummingbird.docc/JobsValkey/JobsValkey.md Initializes a JobService with the Valkey driver. Requires a ValkeyClient and configuration for queue name and poll time. ```swift import JobsValkey import ServiceLifecycle import Valkey let valkeyClient = ValkeyClient(...) let jobService = JobService( .valkey( valkeyClient, configuration: .init( queueName: "MyJobQueue", pollTime: .milliseconds(50) ) ), logger: logger ) ``` -------------------------------- ### Configure WebSocket Upgrade Server Source: https://github.com/hummingbird-project/hummingbird-docs/blob/main/Hummingbird.docc/Articles/ServerProtocol.md Set up a server that can handle WebSocket upgrades. This example upgrades connections for requests to the "/ws" URI. ```swift import HummingbirdWebSocket let app = Application( router: router, server: .http1WebSocketUpgrade { request, channel, logger in // upgrade if request URI is "/ws" guard request.uri == "/ws" else { return .dontUpgrade } // The upgrade response includes the headers to include in the response and // the WebSocket handler return .upgrade([:]) { inbound, outbound, context in for try await frame in inbound { // send "Received" for every frame we receive try await outbound.write(.text("Received")) } } } ) ``` -------------------------------- ### Fluent Storage with Persist Driver Source: https://github.com/hummingbird-project/hummingbird-docs/blob/main/Hummingbird.docc/HummingbirdFluent/HummingbirdFluent.md Shows how to use the FluentPersistDriver to store and retrieve key-value pairs from a SQLite database. Includes setup, migration, and route definitions for GET and PUT operations. ```swift let fluent = Fluent() // add sqlite database fluent.databases.use(.sqlite(.file("db.sqlite")), as: .sqlite) let persist = FluentPersistDriver(fluent: fluent) if doingMigration { // fluent persist driver requires a migrate the first time you run try await fluent.migrate() } let router = Router() // return value from sqlite database router.get("{id}") { request, context -> String? in let id = try context.parameters.require("id") try await persist.get(key: id, as: String.self) } // set value in sqlite database router.put("{id}") { request, context -> String? in let id = try context.parameters.require("id") let value = try request.uri.queryParameters.require("value") try await persist.set(key: id, value: value) } var app = Application(router: router) // add fluent and persist driver as services to manage their lifecycle app.addServices(fluent, persist) try await app.runService() ``` -------------------------------- ### Hummingbird v2 Router Setup Source: https://github.com/hummingbird-project/hummingbird-docs/blob/main/Hummingbird.docc/Articles/MigratingToV2.md In v2, you create a Router first, then initialize the Application with it. Routes added after Application initialization are ignored. ```swift let router = Router() router.get { request, context in "hello" } let app = Application(router: router) ``` -------------------------------- ### Apply Database Migrations Source: https://github.com/hummingbird-project/hummingbird-docs/blob/main/Hummingbird.docc/Examples/OTPAuthenticationExample.md Applies database migrations before the server starts. Ensure the PostgresClient connection manager has started. ```swift app.beforeServerStarts { client in try await client.application.postgresMigrations.apply(client: client, groups: [.initial], options: .default, logger: client.logger, dryRun: false) } ``` -------------------------------- ### Dictionary Context Example Source: https://github.com/hummingbird-project/hummingbird-docs/blob/main/Hummingbird.docc/Mustache/MustacheSyntax.md Demonstrates how a dictionary can be used as a context for Mustache rendering. ```swift let object = ["name": "John Smith", "age": 68] ``` -------------------------------- ### Clone Hummingbird Project Template Source: https://github.com/hummingbird-project/hummingbird-docs/blob/main/Hummingbird.docc/Articles/GettingStarted.md Use this command to clone the official Hummingbird starting template to your local machine. ```bash git clone https://github.com/hummingbird-project/template ``` -------------------------------- ### Test Application Response with Router Framework Source: https://github.com/hummingbird-project/hummingbird-docs/blob/main/Hummingbird.docc/Articles/Testing.md Use the `.router` test framework to send a GET request to a specific URI and assert the response status and body. This method is fast as it bypasses server setup. ```swift func testApplicationReturnsCorrectText() async throw { try await app.test(.router) { client in try await client.execute( uri: "/hello/john", method: .get, headers: [:], // default value body: nil // default value ) { response in #expect(response.status == .ok) #expect(String(buffer: response.body) == "Hello john!") } } } ``` -------------------------------- ### Bootstrap and Run a Hummingbird Server Source: https://context7.com/hummingbird-project/hummingbird-docs/llms.txt Use the Application type to bind a router to an HTTP server configuration, manage services, and expose lifecycle hooks. This example shows how to create a router, configure the application, and run the server. ```swift import Hummingbird // 1. Build the router let router = Router() router.get("hello") { request, _ -> String in return "Hello, World!" } // 2. Build the application let app = Application( router: router, configuration: .init(address: .hostname("127.0.0.1", port: 8080)) ) // 3. Run (blocks until SIGINT/SIGTERM) try await app.runService() ``` -------------------------------- ### Apply Migrations Before Server Starts Source: https://github.com/hummingbird-project/hummingbird-docs/blob/main/Hummingbird.docc/PostgresMigrations/MigrationsGuide.md Apply database migrations before the Hummingbird server starts accepting connections. Use `dryRun: true` for a supervised check of pending migrations. ```swift var app = Application(router: router) // add postgres client as a service to ensure it is active app.addServices(postgresClient) app.beforeServerStarts { try await migrations.apply(client: postgresClient, logger: logger, dryRun: true) } ``` -------------------------------- ### Create and Run a Basic Hummingbird Application Source: https://github.com/hummingbird-project/hummingbird-docs/blob/main/Hummingbird.docc/index.md This snippet demonstrates how to create a simple Hummingbird application with a single GET /hello route. It includes the necessary import and shows how to initialize the router, add a route handler, create the application, and run it. ```swift import Hummingbird // create router and add a single GET /hello route let router = Router() .get("hello") { request, _ -> String in return "Hello" } // create application using router let app = Application(router: router) // run hummingbird application try await app.runService() ``` -------------------------------- ### Test Server Request Source: https://github.com/hummingbird-project/hummingbird-docs/blob/main/Hummingbird.docc/HummingbirdTesting/HummingbirdTesting.md Setup a router, application, and then test requests to your server's routes. Ensure the response status and body match expectations. ```swift let router = Router() router.get("test") { _ in return "testing" } let app = Application(router: router) try await app.test(.router) { client in try await client.execute(uri: "test", method: .GET) { response in #expect(response.status == .ok) #expect(String(buffer: response.body) == "testing") } } ``` -------------------------------- ### Hummingbird v1 Router Setup Source: https://github.com/hummingbird-project/hummingbird-docs/blob/main/Hummingbird.docc/Articles/MigratingToV2.md In v1, routes were added directly to the Application instance. ```swift let app = Application() app.router.get { request in "hello" } ``` -------------------------------- ### Shortcut for GET Route Source: https://github.com/hummingbird-project/hummingbird-docs/blob/main/Hummingbird.docc/HummingbirdRouter/RouterBuilderGuide.md Use the `Get` shortcut function for defining GET routes, which is equivalent to `Route(.get, ...)`. ```swift Get("health") { _,_ in HTTPResponse.Status.ok } ``` -------------------------------- ### Struct Context Example Source: https://github.com/hummingbird-project/hummingbird-docs/blob/main/Hummingbird.docc/Mustache/MustacheSyntax.md Illustrates using a Swift struct as a context for Mustache rendering, showing equivalent rendering to a dictionary. ```swift struct Person { let name: String let age: Int } let object = Person(name: "John Smith", age: 68) ``` -------------------------------- ### Service Lifecycle Management Source: https://context7.com/hummingbird-project/hummingbird-docs/llms.txt `Application` integrates with Swift Service Lifecycle. Use `addServices(_:)` to attach dependent services and `beforeServerStarts(perform:)` to run setup before accepting HTTP traffic. ```APIDOC ## Application Setup and Run ### Description Initializes the Hummingbird application with a router and logger, adds managed services, performs pre-server start tasks like migrations, and then runs the application. ### Method (Not applicable, this describes application setup and execution) ### Endpoint (Not applicable) ### Actions 1. Initialize `Application` with a router and logger. 2. Add managed services using `app.addServices(_:)`. 3. Schedule pre-server start tasks (e.g., database migrations) using `app.beforeServerStarts { ... }`. 4. Run the application, which handles graceful shutdown signals, using `app.runService()`. ``` -------------------------------- ### Create and Run a Basic Hummingbird Application Source: https://github.com/hummingbird-project/hummingbird-docs/blob/main/Hummingbird.docc/Hummingbird/Hummingbird.md This snippet demonstrates how to create a simple Hummingbird application with a single GET /hello route. It initializes a router, adds a handler for the route, configures the application's address, and then runs the service. Ensure the necessary imports are included. ```swift import Hummingbird // create router and add a single GET /hello route let router = Router() router.get("hello") { request, _ -> String in return "Hello" } // create application using router let app = Application( router: router, configuration: .init(address: .hostname("127.0.0.1", port: 8080)) ) // run hummingbird application try await app.runService() ``` -------------------------------- ### Create and Run Hummingbird Lambda Source: https://github.com/hummingbird-project/hummingbird-docs/blob/main/Hummingbird.docc/HummingbirdLambda/HummingbirdLambda.md Define a router, create a LambdaFunction with the router, and then run the service. This example sets up a basic route that returns a greeting with a name from the URL parameters. ```swift typealias AppRequestContext = BasicLambdaRequestContext // Create router and add a single route returning "Hello" and name in its body let router = Router(context: AppRequestContext.self) router.get("hello/{name}") { request, context in let name = try context.parameters.require("name") return "Hello \(name)" } // create APIGatewayV2 lambda using router and run. let lambda = LambdaFunction( router: router, event: APIGatewayV2Request.self, output: APIGatewayV2Response.self ) try await lambda.runService() ``` -------------------------------- ### Manage Server Lifecycle Source: https://github.com/hummingbird-project/hummingbird-docs/blob/main/Hummingbird.docc/HummingbirdCore/HummingbirdCore.md This code snippet shows how to use Swift Service Lifecycle to manage the server's startup and shutdown. It starts the server and ensures graceful shutdown on receiving termination signals. ```swift let serviceGroup = ServiceGroup( services: [server], configuration: .init(gracefulShutdownSignals: [.sigterm, .sigint]), logger: logger ) try await serviceGroup.run() ``` -------------------------------- ### Define a GET Route using Shortcut Source: https://github.com/hummingbird-project/hummingbird-docs/blob/main/Hummingbird.docc/Articles/RouterGuide.md Utilize shortcut methods like `router.get` for common HTTP methods to simplify route definition. This is equivalent to using `router.on` with `.get`. ```swift let router = Router() router.get("/hello") { request, context in return "Hello" } ``` -------------------------------- ### Service Lifecycle Management Source: https://context7.com/hummingbird-project/hummingbird-docs/llms.txt Integrate with Swift Service Lifecycle for managing application services, startup, and shutdown. Use `addServices` to attach dependent services and `beforeServerStarts` for pre-startup setup like database migrations. ```swift import Logging var logger = Logger(label: "MyApp") logger.logLevel = .info let router = Router(context: AppRequestContext.self) // … register routes … var app = Application(router: router, logger: logger) // Add managed services (started and stopped with the application) app.addServices(postgresClient, sessionStorage, jobService) // Run migrations before the HTTP server starts app.beforeServerStarts { try await migrations.apply(client: postgresClient, logger: logger, dryRun: false) } // Handles SIGTERM / SIGINT for graceful shutdown try await app.runService() ``` -------------------------------- ### Implement WebSocket Echo Server with Hummingbird Source: https://context7.com/hummingbird-project/hummingbird-docs/llms.txt Set up a WebSocket endpoint using `.http1WebSocketUpgrade` and `wsRouter.ws(_:shouldUpgrade:onUpgrade:)`. This example demonstrates a simple echo server that processes incoming text frames and sends replies. It includes basic authentication by checking a query parameter. ```swift import HummingbirdWebSocket let wsRouter = Router(context: BasicWebSocketRequestContext.self) wsRouter.middlewares.add(BasicAuthenticator()) // Echo server: one-to-one frame response wsRouter.ws("/ws") { request, context in // Guard on query param; only authenticated users proceed guard request.uri.queryParameters["token"] != nil else { return .dontUpgrade } return .upgrade([:]) } onUpgrade: { inbound, outbound, context in // Process message stream (multi-frame messages collapsed to max 1 MB) for try await message in inbound.messages(maxSize: 1024 * 1024) { let reply = await processMessage(message) try await outbound.write(.text(reply)) } } ``` -------------------------------- ### Integrate Observability Middleware in Hummingbird Source: https://context7.com/hummingbird-project/hummingbird-docs/llms.txt This example demonstrates setting up Prometheus metrics, OpenTelemetry tracing, and a logger for a Hummingbird application. It adds middleware for logging requests, collecting metrics, and enabling distributed tracing. ```swift import Metrics import Prometheus import OpenTelemetry import Tracing // Prometheus metrics let prometheus = PrometheusClient() MetricsSystem.bootstrap(PrometheusMetricsFactory(client: prometheus)) // OpenTelemetry tracing var otelConfig = OTel.Configuration.default otelConfig.serviceName = "my-hummingbird-app" let otel = try OTel.bootstrap(configuration: otelConfig) // Configure logger var logger = Logger(label: "MyApp") logger.logLevel = .info let router = Router() router.add { LogRequestsMiddleware(.info, includeHeaders: false) // one line per request MetricsMiddleware() // request count, latency, error rate TracingMiddleware(recordingHeaders: ["content-type", "x-request-id"]) } router.get("health") { _, _ in HTTPResponse.Status.ok } let app = Application(router: router, logger: logger, services: [otel]) try await app.runService() ``` -------------------------------- ### Template Inheritance Example Source: https://github.com/hummingbird-project/hummingbird-docs/blob/main/Hummingbird.docc/Mustache/MustacheFeatures.md Demonstrates how to override sections of a parent template using the `<` tag and section tags prefixed with `$`. Use this to create base layouts and customize specific parts. ```mustache {{! mypage.mustache }} {{My page title{{/head}} {{$body}}Hello world{{/body}} {{/base}} ``` ```mustache {{! base.mustache }} {{$head}}{{/head}} {{$body}}Default text{{/body}} ``` ```mustache My page title Hello world ``` -------------------------------- ### Configure WebSocket with perMessageDeflate Extension Source: https://github.com/hummingbird-project/hummingbird-docs/blob/main/Hummingbird.docc/WSCompression/WSCompression.md Add the `perMessageDeflate` extension to your HTTP server configuration for WebSocket upgrades. This example sets a minimum frame size for compression. ```swift let app = Application( router: Router(), server: .http1WebSocketUpgrade( configuration: .init(extensions: [.perMessageDeflate(minFrameSizeToCompress: 16)]) ) { _, _, _ in return .upgrade([:]) { inbound, _, _ in var iterator = inbound.messages(maxSize: .max).makeAsyncIterator() let firstMessage = try await iterator.next() XCTAssertEqual(firstMessage, .text("Hello, testing compressed data")) } } ) ``` -------------------------------- ### Implement Basic Authenticator Source: https://github.com/hummingbird-project/hummingbird-docs/blob/main/Hummingbird.docc/HummingbirdAuth/AuthenticatorMiddlewareGuide.md Implement a basic username and password authenticator. This example checks the Authorization header and verifies credentials against a database. It uses Bcrypt for password hashing verification, which should be run on a thread pool. ```swift import HummingbirdAuth struct BasicAuthenticator: AuthenticatorMiddleware { func authenticate(request: Request, context: Context) async throws -> Identity? { // Basic authentication info in the "Authorization" header, is accessible // via request.headers.basic guard let basic = request.headers.basic else { return nil } // check if user exists in the database and then verify the entered password // against the one stored in the database. If it is correct then login in user let user = try await database.getUserWithUsername(basic.username) // did we find a user guard let user = user else { return nil } // verify password against password hash stored in database. If valid // return the user. HummingbirdAuth provides an implementation of Bcrypt // This should be run on the thread pool as it is a long process. return try await NIOThreadPool.singleton.runIfActive { if Bcrypt.verify(basic.password, hash: user.passwordHash) { return user } return nil } } } ``` -------------------------------- ### Postgres Database Migrations with Hummingbird Source: https://context7.com/hummingbird-project/hummingbird-docs/llms.txt Define and apply incremental database schema changes using PostgresMigrations. Ensure migrations are run before the server starts. ```swift import HummingbirdPostgres import PostgresMigrations struct CreateUsersTable: DatabaseMigration { func apply(connection: PostgresConnection, logger: Logger) async throws { try await connection.query( """ CREATE TABLE users ( "id" UUID PRIMARY KEY, "email" TEXT NOT NULL UNIQUE, "name" TEXT NOT NULL ) """, logger: logger ) } func revert(connection: PostgresConnection, logger: Logger) async throws { try await connection.query("DROP TABLE users", logger: logger) } } let migrations = DatabaseMigrations() await migrations.add(CreateUsersTable()) var app = Application(router: router) app.addServices(postgresClient) app.beforeServerStarts { // dryRun: true → throws + logs what would change, no DB writes try await migrations.apply( client: postgresClient, logger: logger, dryRun: false ) } try await app.runService() ``` -------------------------------- ### Define a Basic GET Route Source: https://github.com/hummingbird-project/hummingbird-docs/blob/main/Hummingbird.docc/Articles/RouterGuide.md Use `router.on` to define a route for a specific path and HTTP method. The handler function receives the request and context, and should return a `ResponseGenerator`. ```swift let router = Router() router.on("/hello", method: .get) { request, context in return "Hello" } ``` -------------------------------- ### Test Authentication Flow with Cookies Source: https://github.com/hummingbird-project/hummingbird-docs/blob/main/Hummingbird.docc/Articles/Testing.md Simulate a login POST request to obtain a session cookie, then use that cookie in a subsequent GET request to verify authentication. This demonstrates testing multi-step interactions. ```swift @Test func testApplicationReturnsCorrectText() async throw { try await app.test(.router) { client in // test login, returns a set-cookie header and extract let cookie = try await client.execute( uri: "/user/login", method: .post, headers: [.authorization: "Basic blahblah"] ) { response in #expect(response.status == .ok) return try #require(response.headers[.setCookie]) } // check session cookie works try await client.execute( uri: "/user/is-authenticated", method: .get, headers: [.cookie: cookie] ) { response in #expect(response.status == .ok) } } } ``` -------------------------------- ### Integrate Valkey/Redis with Hummingbird Source: https://github.com/hummingbird-project/hummingbird-docs/blob/main/Hummingbird.docc/HummingbirdValkey/HummingbirdValkey.md Set up a Valkey client and persist driver, then integrate them into a Hummingbird router for GET and PUT operations. Ensure the Valkey client is added as a service to manage its lifecycle. ```swift let valkeyClient = ValkeyClient( .hostname(Self.valkeyHostname, port: 6379), logger: Logger(label: "Valkey") ) let persist = ValkeyPersistDriver(client: valkeyClient) let router = Router() // return value from valkey database router.get("{id}") { request, context -> String? in let id = try context.parameters.require("id") try await persist.get(key: id, as: String.self) } // set value in valkey database router.put("{id}") { request, context -> String? in let id = try context.parameters.require("id") let value = try request.uri.queryParameters.require("value") try await persist.set(key: id, value: value) } var app = Application(router: router) // add Valkey client as service to manage its lifecycle app.addServices(valkeyClient) try await app.runService() ``` -------------------------------- ### Integrate DatabaseMigrationService with ServiceGroup Source: https://github.com/hummingbird-project/hummingbird-docs/blob/main/Hummingbird.docc/JobsPostgres/JobsPostgres.md Add the DatabaseMigrationService to your ServiceGroup to automatically run necessary database migrations before the job service starts. Set `dryRun` to `false` for actual migrations. ```swift let migrationService = DatabaseMigrationService( client: postgresClient, migrations: postgresMigrations, logger: logger, dryRun: false ) let serviceGroup = ServiceGroup( configuration: .init( services: [postgresClient, migrationService, jobService], gracefulShutdownSignals: [.sigterm, .sigint], logger: jobService.logger ) ) try await serviceGroup.run() ``` -------------------------------- ### Configure HTTP Server for WebSocket Upgrade Source: https://github.com/hummingbird-project/hummingbird-docs/blob/main/Hummingbird.docc/HummingbirdWebSocket/HummingbirdWebSocket.md Integrate HummingbirdWebSocket by specifying WebSocket support in your Application's configuration. This example upgrades connections to WebSocket if the request URI is '/ws'. ```swift import Hummingbird import HummingbirdWebSocket let app = Application( router: router, server: .http1WebSocketUpgrade { request, channel, logger in // upgrade if request URI is "/ws" guard request.uri == "/ws" else { return .dontUpgrade } // The upgrade response includes the headers to include in the response and // the WebSocket handler return .upgrade([:]) { inbound, outbound, context in // Send "Hello" to the client try await outbound.write(.text("Hello")) // Ending this function automatically closes the connection } } ) ``` -------------------------------- ### Setup WebSocket Upgrade with Closure Source: https://github.com/hummingbird-project/hummingbird-docs/blob/main/Hummingbird.docc/HummingbirdWebSocket/WebSocketServerUpgrade.md Configure the Hummingbird server to handle WebSocket upgrades using a closure. This method allows direct control over whether to upgrade and how to handle the WebSocket connection. ```swift import HummingbirdWebsocket let app = Application( router: router, server: .http1WebSocketUpgrade { request, channel, logger in // upgrade if request URI is "/ws" guard request.uri == "/ws" else { return .dontUpgrade } // The upgrade response includes the headers to include in the response and // the WebSocket handler return .upgrade([:]) { inbound, outbound, context in for try await frame in inbound { // send "Received" for every frame we receive try await outbound.write(.text("Received")) } } } ) ``` -------------------------------- ### Setup WebSocket Upgrade with Router Source: https://github.com/hummingbird-project/hummingbird-docs/blob/main/Hummingbird.docc/HummingbirdWebSocket/WebSocketServerUpgrade.md Configure the Hummingbird server to handle WebSocket upgrades using a dedicated router. This approach allows for middleware processing of upgrade requests before they are handled. ```swift // Setup WebSocket router let wsRouter = Router(context: BasicWebSocketRequestContext.self) // add middleware wsRouter.middlewares.add(LogRequestsMiddleware()) wsRouter.middlewares.add(BasicAuthenticator()) // An upgrade only occurs if a WebSocket path is matched wsRouter.ws("/ws") { request, context in // allow upgrade .upgrade([:]) } onUpgrade: { inbound, outbound, context in for try await frame in inbound { // send "Received" for every frame we receive try await outbound.write(.text("Received")) } } let app = Application( router: router, server: .http1WebSocketUpgrade(webSocketRouter: wsRouter) ) ``` -------------------------------- ### Set up JobService with Valkey Driver Source: https://github.com/hummingbird-project/hummingbird-docs/blob/main/Hummingbird.docc/Jobs/JobsGuide.md Initializes a JobService using the Valkey driver. Ensure you have a configured `valkeyClient` and a `logger` instance. ```swift let jobService = JobService( .valkey( valkeyClient, configuration: .init(queueName: "MyQueue"), logger: logger ), logger: logger ) ``` -------------------------------- ### Build Documentation with Version Source: https://github.com/hummingbird-project/hummingbird-docs/blob/main/CONTRIBUTING.md Run the documentation build script with the HUMMINGBIRD_VERSION environment variable set to ensure documentation is placed in the correct folder for the current version. ```bash HUMMINGBIRD_VERSION=2.0 ./scripts/build-docc.sh ``` -------------------------------- ### Configure New Hummingbird Project Source: https://github.com/hummingbird-project/hummingbird-docs/blob/main/Hummingbird.docc/Articles/GettingStarted.md After cloning the template, run this script to create a new project folder and initialize your project. ```bash ./template/configure.sh MyNewProject ``` -------------------------------- ### Navigate to New Project Directory Source: https://github.com/hummingbird-project/hummingbird-docs/blob/main/Hummingbird.docc/Articles/GettingStarted.md Change your current directory to the newly created project folder. ```bash cd MyNewProject ``` -------------------------------- ### Initialize Valkey Persist Driver Source: https://github.com/hummingbird-project/hummingbird-docs/blob/main/Hummingbird.docc/Articles/PersistentData.md Set up the Valkey/Redis storage driver. This requires a configured `ValkeyClient` and the `HummingbirdValkey` library. ```swift let valkeyClient = ValkeyClient( .hostname(valkeyHostname, port: 6379), logger: Logger(label: "Valkey") ) let persist = ValkeyPersistDriver(client: valkeyClient) ``` -------------------------------- ### Initialize Fluent Persist Driver Source: https://github.com/hummingbird-project/hummingbird-docs/blob/main/Hummingbird.docc/Articles/PersistentData.md Set up the Fluent ORM storage driver. This requires a pre-configured Fluent instance and ensures database migrations are run. ```swift let fluent = Fluent(logger: Logger(label: "Fluent")) fluent.databases.use(...) // Configure your database connection let persist = await FluentPersistDriver(fluent: fluent) // run migrations if shouldMigrate { try await fluent.migrate() } ``` -------------------------------- ### Create a Simple Hummingbird Application Source: https://github.com/hummingbird-project/hummingbird-docs/blob/main/Hummingbird.docc/Articles/Testing.md Define a basic router and application instance for testing purposes. This sets up the core components of your web service. ```swift let router = Router() router.get("hello/{name}") { _,context in return try "Hello \(context.parameters.require("name"))!" } let app = Application(router: router) ``` -------------------------------- ### Define a Partial Mustache Template Source: https://github.com/hummingbird-project/hummingbird-docs/blob/main/Hummingbird.docc/Mustache/MustacheFeatures.md Define a simple Mustache template that can be included in other templates. This example shows the content of an 'included.mustache' file. ```mustache {{! included.mustache }} Hello world ``` -------------------------------- ### Conform Service to Service Protocol Source: https://github.com/hummingbird-project/hummingbird-docs/blob/main/Hummingbird.docc/Articles/ServiceLifecycle.md Conform your custom service to the `Service` protocol and implement `run()` to handle startup and shutdown logic using `withGracefulShutdownHandler`. ```swift struct MyService: Service { func run() async throws { withGracefulShutdownHandler { // run service } onGracefulShutdown { // shutdown service } } } ``` -------------------------------- ### Creating Custom HTTPResponseError Source: https://github.com/hummingbird-project/hummingbird-docs/blob/main/Hummingbird.docc/Articles/ErrorHandling.md Define your own error types that conform to HTTPResponseError to customize the server's error response. This example adds a custom 'error-code' header. ```swift struct MyError: HTTPResponseError { init(_ status: HTTPResponseStatus, errorCode: String) { self.status = status self.errorCode = errorCode } let errorCode: String // required by HTTPResponseError protocol let status: HTTPResponseStatus // required by HTTPResponseError protocol func response(from request: Request, context: some RequestContext) throws -> Response { .init( status: self.status, headers: ["error-code": self.errorCode]) } } ``` -------------------------------- ### Initialize and Run WebSocket Client Source: https://github.com/hummingbird-project/hummingbird-docs/blob/main/Hummingbird.docc/WSClient/WebSocketClientGuide.md Create and run a WebSocket client with a custom handler for incoming and outgoing frames. The client will automatically manage the connection lifecycle. ```swift import WSClient let ws = WebSocketClient(url: "ws://mywebsocket/ws") { inbound, outbound, context in try await outbound.write(.text("Hello")) for try await frame in inbound { context.logger.info(frame) } } try await ws.run() ``` -------------------------------- ### Sign Up Page Source: https://github.com/hummingbird-project/hummingbird-docs/blob/main/Hummingbird.docc/Examples/TodosAuthExample.md Renders the sign-up webpage. ```APIDOC ## GET /signup ### Description Displays the sign-up form for new users. ### Method GET ### Endpoint /signup ``` -------------------------------- ### Match Specific Prefix with Wildcard Source: https://github.com/hummingbird-project/hummingbird-docs/blob/main/Hummingbird.docc/Articles/RouterGuide.md Place a wildcard `*` after a specific prefix in a path component to match all paths starting with that prefix. This is useful for matching variations of a base path. ```swift router.get("/files/image.*") { request, context in return request.uri.description } ``` -------------------------------- ### Convert EventLoopFuture to Swift Concurrency Source: https://github.com/hummingbird-project/hummingbird-docs/blob/main/Hummingbird.docc/Articles/MigratingToV2.md Use the `get()` method from `EventLoopFuture` to convert EventLoop-based APIs to Swift concurrency. This is useful when integrating with libraries that still rely on EventLoop futures. ```swift let value = try await eventLoopBasedFunction().get() ``` -------------------------------- ### Initialize UserController with Dependencies Source: https://github.com/hummingbird-project/hummingbird-docs/blob/main/Hummingbird.docc/Articles/MigratingToV2.md In v2, controllers require explicit dependency injection. Initialize controllers with the specific dependencies they need, such as `Fluent` and `SessionStorage`, for better clarity on their requirements. ```swift struct UserController { // The user authentication routes use fluent and session storage init(fluent: Fluent, sessions: SessionStorage) { ... } } ``` -------------------------------- ### Create and Run a Service Group Source: https://github.com/hummingbird-project/hummingbird-docs/blob/main/Hummingbird.docc/Articles/ServiceLifecycle.md Instantiate a `ServiceGroup` with your services and desired shutdown signals, then run the group to manage their lifecycles. ```swift let serviceGroup = ServiceGroup( configuration: .init( services: [MyService(), MyOtherService()], gracefulShutdownSignals: [.sigterm, .sigint] logger: logger ) ) try await serviceGroup.run() ``` -------------------------------- ### Queue Job using Job Parameters Source: https://github.com/hummingbird-project/hummingbird-docs/blob/main/Hummingbird.docc/Jobs/JobsGuide.md Creates an instance of your job parameters struct and pushes it onto the job queue using `JobService.push(_:options:)`. ```swift let job = SendEmailJobParameters( to: "joe@email.com", subject: "Testing Jobs", message: "..." ) jobService.push(job) ``` -------------------------------- ### Implement ApplicationProtocol Source: https://github.com/hummingbird-project/hummingbird-docs/blob/main/Hummingbird.docc/Hummingbird/ApplicationProtocol.md Implement the `ApplicationProtocol` by defining a `responder` and `server`. The `responder` handles requests and returns responses, while the `server` defines the server type. ```swift struct MyApp: ApplicationProtocol { /// The responder will return an `Response` given an `Request` and a context var responder: some Responder { let router = Router(context: Context.self) router.get("hello") { _,_ in "Hello" } return router.buildResponder() } /// Defines your server type. This is the default value so in /// effect is unnecessary var server: HTTPChannelBuilder { .http1() } } let app = MyApp() try await app.runService() ``` -------------------------------- ### Build Application with Opaque Type Source: https://github.com/hummingbird-project/hummingbird-docs/blob/main/Hummingbird.docc/Hummingbird/Application.md Shows how to build an application using the opaque type 'some ApplicationProtocol' for easier type erasure when passing the application around. ```swift func buildApplication() -> some ApplicationProtocol { let router = Router() router.get("hello") { _,_ in return "hello" } // create application let app = Application(router: router) } ``` -------------------------------- ### Schedule Regular Job Cleanup Source: https://github.com/hummingbird-project/hummingbird-docs/blob/main/Hummingbird.docc/JobsPostgres/JobsPostgres.md Configure automatic job cleanup during JobService initialization using the `JobScheduler`. This example sets up weekly cleanup for completed jobs older than 7 days. ```swift let jobService = JobService( .postgres(...), logger: logger, options: .init( cleanup: .init( jobs: .init( parameters: .init(completedJobs: .remove(maxAge: .seconds(60*60*24*7))), schedule: .weekly(day: .sunday) ) ) ) ) ``` -------------------------------- ### Schedule Regular Job Queue Cleanup Source: https://github.com/hummingbird-project/hummingbird-docs/blob/main/Hummingbird.docc/JobsValkey/JobsValkey.md Configures the JobService to automatically clean up the job queue on a schedule. This example sets up weekly cleanup for completed jobs older than 7 days. ```swift let jobService = JobService( .valkey(...), logger: logger, options: .init( cleanup: .init( jobs: .init( parameters: .init(completedJobs: .remove(maxAge: .seconds(60*60*24*7))), schedule: .weekly(day: .sunday) ) ) ) ) ``` -------------------------------- ### Metrics Middleware with Prometheus Source: https://github.com/hummingbird-project/hummingbird-docs/blob/main/Hummingbird.docc/Articles/LoggingMetricsAndTracing.md Bootstrap Prometheus and add the MetricsMiddleware to your router to record request metrics. Requires importing Metrics and Prometheus. ```swift import Metrics import Prometheus // Bootstrap Prometheus let prometheus = PrometheusClient() MetricsSystem.bootstrap(PrometheusMetricsFactory(client: prometheus)) // Add metrics middleware to router router.middlewares.add(MetricsMiddleware()) ``` -------------------------------- ### Sequence Context Transform: Last Element Check Source: https://github.com/hummingbird-project/hummingbird-docs/blob/main/Hummingbird.docc/Mustache/MustacheFeatures.md Uses the `last()` sequence context transform within an array section to conditionally render content. This example prevents a trailing comma after the last element. ```mustache {{#array}}{{.}}{{^last()}}, {{/last()}}{{/array}} ``` -------------------------------- ### Configure and Initialize HTTP2 Server Source: https://github.com/hummingbird-project/hummingbird-docs/blob/main/Hummingbird.docc/HummingbirdHTTP2/HummingbirdHTTP2.md Load certificates and private key to construct server TLS configuration. This code initializes a Hummingbird application with HTTP2 upgrade support using the provided TLS configuration. ```swift // Load certificates and private key to construct server TLS configuration let certificateChain = try NIOSSLCertificate.fromPEMFile(arguments.certificateChain) let privateKey = try NIOSSLPrivateKey(file: arguments.privateKey, format: .pem) let tlsConfiguration = TLSConfiguration.makeServerConfiguration( certificateChain: certificateChain.map { .certificate($0) }, privateKey: .privateKey(privateKey) ) let router = Router() let app = Application( router: router, server: .http2Upgrade(tlsConfiguration: tlsConfiguration) ) ``` -------------------------------- ### Get a Persist Value Source: https://github.com/hummingbird-project/hummingbird-docs/blob/main/Hummingbird.docc/Articles/PersistentData.md Retrieve a value from the persist store using its key. Specify the expected type for decoding. Returns `nil` if the key doesn't exist or throws `PersistError.invalidConversion` if the value cannot be converted to the expected type. ```swift let value = try await persist.get(key: "mykey", as: MyValueType.self) ``` -------------------------------- ### Tracing Middleware with OpenTelemetry Source: https://github.com/hummingbird-project/hummingbird-docs/blob/main/Hummingbird.docc/Articles/LoggingMetricsAndTracing.md Bootstrap OpenTelemetry and add the TracingMiddleware to your router for request and response tracing. Specify recording headers. ```swift import OpenTelemetry import Tracing // Bootstrap Open Telemetry and create OTel service var otelConfig = OTel.Configuration.default otelConfig.serviceName = "Hummingbird" let otel = try OTel.bootstrap(configuration: otelConfig) // Add tracing middleware router.middlewares.add(TracingMiddleware(recordingHeaders: ["content-type", "content-length"])) // Include otel in Hummingbird services let application = Application( router: router, services: [otel] ) ``` -------------------------------- ### HTTPError for Structured Error Responses Source: https://context7.com/hummingbird-project/hummingbird-docs/llms.txt Throw `HTTPError` to return structured HTTP error responses with specified status codes and optional messages. This example demonstrates handling invalid input and resource not found scenarios. ```swift router.get("user") { request, context -> User in guard let id = request.uri.queryParameters.get("id", as: Int.self) else { throw HTTPError(.badRequest, message: "Invalid user id") // → 400 Bad Request, body: "Invalid user id" } guard let user = try await database.getUser(id: id) else { throw HTTPError(.notFound, message: "User not found") // → 404 Not Found } return user } ``` -------------------------------- ### Implement a Simple Logging Middleware Source: https://github.com/hummingbird-project/hummingbird-docs/blob/main/Hummingbird.docc/Articles/MiddlewareGuide.md Create custom middleware by conforming to `RouterMiddleware`. Log the request URI before passing it to the next handler in the stack. ```swift public struct LogRequestsMiddleware: RouterMiddleware { public func handle(_ request: Request, context: Context, next: (Request, Context) async throws -> Response) async throws -> Response { // log request URI context.logger.log(level: .debug, String(describing:request.uri.path)) // pass request onto next middleware or the router and return response return try await next(request, context) } } ``` -------------------------------- ### Define Router with Result Builder Source: https://github.com/hummingbird-project/hummingbird-docs/blob/main/Hummingbird.docc/HummingbirdRouter/HummingbirdRouter.md Use RouterBuilder with a result builder to construct your router. This example shows how to add CORS middleware, a simple health check route, and a nested route group for user authentication. ```swift let router = RouterBuilder(context: BasicRouterRequestContext.self) { CORSMiddleware() Route(.get, "health") { _,_ in HTTPResponse.Status.ok } RouteGroup("user") { BasicAuthenticationMiddleware() Route(.post, "login") { request, context in ... } } } ``` -------------------------------- ### Use Custom Transform in Mustache Template Source: https://github.com/hummingbird-project/hummingbird-docs/blob/main/Hummingbird.docc/Mustache/MustacheFeatures.md Render custom transformable objects in Mustache templates by calling the defined transform function. This example shows how to use the `eitherOr` transform to achieve a logical OR operation within the template. ```mustache {{#eitherOr(object)}}Success{{/eitherOr(object)}} ``` -------------------------------- ### Return Codable Types as HTTP Responses Source: https://context7.com/hummingbird-project/hummingbird-docs/llms.txt Conform types to `ResponseEncodable` to have them automatically encoded and returned as HTTP responses. The default `JSONEncoder` is used, and the `Content-Type` header is set appropriately. This example shows a `UserResponse` struct and a route handler returning it. ```swift struct UserResponse: ResponseEncodable { let id: Int let email: String let name: String } router.get("user/{id}") { request, context -> UserResponse in guard let id = context.parameters.get("id", as: Int.self) else { throw HTTPError(.badRequest) } let user = try await database.getUser(id: id) return UserResponse(id: user.id, email: user.email, name: user.name) // Response: 200 OK, Content-Type: application/json // Body: {"id":1,"email":"js@email.com","name":"John Smith"} } ``` ```swift // Return edited response with custom status and headers router.post("resource") { request, _ -> EditedResponse in return .init( status: .accepted, headers: [.contentType: "application/json"], response: #"{"queued": true}"# ) } ``` -------------------------------- ### Home Page Source: https://github.com/hummingbird-project/hummingbird-docs/blob/main/Hummingbird.docc/Examples/TodosAuthExample.md Displays the user's todo list. Requires authentication and redirects if not logged in. ```APIDOC ## GET / ### Description Renders the main page displaying the user's todo list. Requires authentication. ### Method GET ### Endpoint / ### Middleware - SessionAuthenticator - RedirectMiddleware ``` -------------------------------- ### WebSocket Message Processing with Max Size Source: https://github.com/hummingbird-project/hummingbird-docs/blob/main/Hummingbird.docc/HummingbirdWebSocket/WebSocketServerUpgrade.md Processes incoming WebSocket messages, ensuring that individual messages do not exceed a specified maximum size (1MB in this example) to prevent memory exhaustion. This converts the stream of frames into a stream of complete messages. ```swift wsRouter.ws("/ws") { inbound, outbound, context in // We have set the maximum size of a message to be 1MB. If we don't set // a maximum size a client could keep sending us frames until we ran // out of memory. for try await message in inbound.messages(maxSize: 1024*1024) { let response = await process(message) try await outbound.write(response) } } ``` -------------------------------- ### Add Services to Application Source: https://github.com/hummingbird-project/hummingbird-docs/blob/main/Hummingbird.docc/Hummingbird/Application.md Illustrates how to add custom services, such as database clients or job queue handlers, to the Application's ServiceGroup for managed lifecycle. ```swift var app = Application(router: router) app.addServices(postgresClient, jobQueueHandler) ``` -------------------------------- ### Load Templates from Filesystem Source: https://github.com/hummingbird-project/hummingbird-docs/blob/main/Hummingbird.docc/Mustache/Mustache.md Initialize a MustacheLibrary to load templates from a specified directory and its subfolders. Templates are registered by their filename without the .mustache extension. ```swift let library = MustacheLibrary("folder/my/templates/are/in") ``` -------------------------------- ### Configure Hummingbird Server with TLS Source: https://github.com/hummingbird-project/hummingbird-docs/blob/main/Hummingbird.docc/HummingbirdTLS/HummingbirdTLS.md Load certificates and private key to construct server TLS configuration. This enables TLS support for the Hummingbird server. ```swift // Load certificates and private key to construct server TLS configuration let certificateChain = try NIOSSLCertificate.fromPEMFile(arguments.certificateChain) let privateKey = try NIOSSLPrivateKey(file: arguments.privateKey, format: .pem) let tlsConfiguration = TLSConfiguration.makeServerConfiguration( certificateChain: certificateChain.map { .certificate($0) }, privateKey: .privateKey(privateKey) ) let router = Router() let app = Application( router: router, server: .tls(.http1(), tlsConfiguration: tlsConfiguration) ) ``` -------------------------------- ### Add Target Dependency Source: https://github.com/hummingbird-project/hummingbird-docs/blob/main/Hummingbird.docc/HummingbirdOTP/OneTimePasswords.md Link the HummingbirdOTP library to your application target. ```bash swift package add-target-dependency HummingbirdOTP --package hummingbird-auth ``` -------------------------------- ### Define Routes with Path Parameters and Wildcards Source: https://context7.com/hummingbird-project/hummingbird-docs/llms.txt The Router uses a Trie-based lookup for efficient routing. Handlers receive Request and Context, and can return any ResponseGenerator. This snippet demonstrates static routes, path parameters, OpenAPI-style parameters, catch-all wildcards, and query parameters. ```swift let router = Router() // Static route router.get("/hello") { _, _ in "Hello" } // Path parameter — /user/42 router.get("/user/:id") { request, context -> User in guard let id = context.parameters.get("id", as: Int.self) else { throw HTTPError(.badRequest, message: "Invalid user id") } return try await database.getUser(id: id) } // OpenAPI-style parameter with partial match — /files/photo.jpg router.get("/files/{image}.jpg") { request, context in let name = try context.parameters.require("image") return try await storage.loadImage(named: name) } // Catch-all wildcard — /files/nested/folder/file.png router.get("/files/**") { request, context in return context.parameters.getCatchAll().joined(separator: "/") } // Query parameters — GET /search?q=swift&page=2 router.get("/search") { request, context in guard let q = request.uri.queryParameters.get("q") else { throw HTTPError(.badRequest) } let page = request.uri.queryParameters.get("page", as: Int.self) ?? 1 return try await search(query: q, page: page) } // Grouped routes share a path prefix and optional middleware router.group("/todos") .put(use: createTodo) .get(use: listTodos) .get("{id}", getTodo) .patch("{id}", editTodo) .delete("{id}", deleteTodo) ``` -------------------------------- ### Initialize In-Memory Persist Driver Source: https://github.com/hummingbird-project/hummingbird-docs/blob/main/Hummingbird.docc/Articles/PersistentData.md Set up the in-memory storage driver for the persist framework. This driver stores data in the server's memory and is lost on server restart. ```swift let persist = MemoryPersistDriver() ``` -------------------------------- ### Connect WebSocket Client Shortcut Source: https://github.com/hummingbird-project/hummingbird-docs/blob/main/Hummingbird.docc/WSClient/WebSocketClientGuide.md A convenience function to initialize and run a WebSocket client in a single call, simplifying the connection process. ```swift try await WebSocketClient.connect(url: "ws://mywebsocket/ws") { inbound, outbound, context in try await outbound.write(.text("Hello")) for try await frame in inbound { context.logger.info(frame) } } ``` -------------------------------- ### Configure HTTP/2 Server with TLS Source: https://github.com/hummingbird-project/hummingbird-docs/blob/main/Hummingbird.docc/Articles/ServerProtocol.md Enable HTTP/2 support, which requires TLS. This configuration includes various timeouts for connections and streams. ```swift import HummingbirdHTTP2 let app = Application( router: router, server: .http2Upgrade( tlsConfiguration: tlsConfiguration, configuration: .init( idleTimeout: .seconds(60), gracefulCloseTimeout: .seconds(15), maxAgeTimeout: .seconds(900), streamConfiguration: .init(idleTimeout: .seconds(60)) ) ) ) ``` -------------------------------- ### Configure Job Service Scheduler Options Source: https://github.com/hummingbird-project/hummingbird-docs/blob/main/Hummingbird.docc/Jobs/JobsGuide.md Initialize `JobService` with custom scheduler options to control lock acquisition intervals for distributed scheduling. This ensures only one scheduler gains control at a time. ```swift let jobService = JobService( .valkey( valkeyClient, configuration: .init(queueName: "MyQueue"), logger: logger ), logger: logger, options: .init( scheduler: .init(schedulerLock: .init(.acquire(every: .seconds(60), for: .seconds(70)))) ) ) ``` -------------------------------- ### Configure HTTP/1.1 Server with Idle Timeout Source: https://github.com/hummingbird-project/hummingbird-docs/blob/main/Hummingbird.docc/Articles/ServerProtocol.md Set up an HTTP/1.1 server with a custom idle timeout for requests. This is the default server protocol. ```swift let app = Application( router: router, server: .http1(idleTimeout: .seconds(60)) ) ```