Express @camada/node
import camada from '@camada/node';
app.use(camada.express());- Works for Connect-style stacks too.
- Register it before your routes so blocked requests never reach them.
Frameworks
Pick your framework. Each snippet is the install for that stack: one package and one middleware on most, a few files for Next.js, and PHP, Java and .NET install from GitHub. The variables are the same everywhere, and the key is printed once when you create a project. Every SDK reads them from the process environment; your framework's quickstart says how to set them there.
CAMADA_KEY=<ingest_token>.<snap_token>
CAMADA_INGEST_URL=http://localhost:8787 # dev only; defaults to production ingestMore JavaScript runtimes, each published on npm with install steps in its README:
import camada from '@camada/node';
app.use(camada.express());import { camadaFastify } from '@camada/node/fastify';
await app.register(camadaFastify);import { CamadaModule } from '@camada/node/nest';
@Module({ imports: [CamadaModule.forRoot()] }) // Nest ≤10: CamadaModule.forRoot({ routes: '*' })
export class AppModule {}import { camadaKoa } from '@camada/node/koa';
app.use(camadaKoa());// middleware.ts (Next ≤15) or proxy.ts (Next 16) at the project root
import { camada } from '@camada/next';
export default camada();
export const config = { matcher: ['/((?!_next/|favicon.ico).*)'] };
// app/api/camada/[...camada]/route.ts
import { camadaRoute } from '@camada/next';
export const { GET, POST } = camadaRoute();
// app/layout.tsx, inside <head>
import { CamadaBeacon } from '@camada/next';
<CamadaBeacon />from camada.fastapi import CamadaMiddleware
app.add_middleware(CamadaMiddleware) # any Starlette app too# settings.py
MIDDLEWARE = ["camada.django.CamadaMiddleware", *MIDDLEWARE]from camada.flask import init_app
init_app(app) # wraps app.wsgi_app, so camada answers before routingimport "github.com/camada-app/camada-go"
mux := http.NewServeMux()
mux.HandleFunc("GET /{$}", home)
http.ListenAndServe(":8080", camada.Handler(mux)) // outermost, so camada answers before routing# config.ru — Sinatra, Hanami, or any Rack app
require "camada"
use Camada::Rack # first, so camada answers before routing
run App
# Rails — nothing to add: the Railtie inserts Camada::Rack at the top of the middleware stackNot on Packagist yet. Run these in your project's folder: Composer installs it straight from GitHub, composer.lock pins the commit, and composer update camada/camada moves it.
composer config repositories.camada vcs https://github.com/camada-app/camada-php
composer require camada/camada:dev-main<?php
// public/index.php — any front controller
require __DIR__ . '/../vendor/autoload.php';
use Camada\Camada;
use Camada\Http\Sapi;
$cam = Camada::default(); // built lazily from the environment, once per request
$ctx = Sapi::run($cam); // null: camada answered (block, challenge, beacon) and the script must stop
if ($ctx === null) {
return;
}
// your app: x-rid and the _sfp cookie are already on the responseNot on Packagist yet. Run these in your project's folder: Composer installs it straight from GitHub, composer.lock pins the commit, and composer update camada/camada moves it.
composer config repositories.camada vcs https://github.com/camada-app/camada-php
composer require camada/camada:dev-main// bootstrap/app.php (Laravel 11+), inside the existing ->withMiddleware(function (Middleware $middleware) { … })
$middleware->prepend(\Camada\Laravel\Middleware::class); // first in the global stack
// or app/Http/Kernel.php (Laravel 10): the first entry of protected $middleware = [ … ]
\Camada\Laravel\Middleware::class,Not on Maven Central yet. From your project's folder: clone it next to the project, build it into your local Maven repository, then add the dependency.
git clone https://github.com/camada-app/camada-java ../camada-java
mvn -q -f ../camada-java install -DskipTests
<!-- then, in pom.xml -->
<dependency>
<groupId>dev.camada</groupId>
<artifactId>camada</artifactId>
<version>0.2.0</version>
</dependency>// CamadaConfig.java, beside your @SpringBootApplication class
package com.example.demo; // your application's package
import dev.camada.servlet.CamadaFilter;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.Ordered;
@Configuration
class CamadaConfig {
@Bean
FilterRegistrationBean<CamadaFilter> camadaFilter() {
var reg = new FilterRegistrationBean<>(new CamadaFilter());
reg.setOrder(Ordered.HIGHEST_PRECEDENCE); // first, so camada answers before routing
return reg;
}
}Not on NuGet yet. From the folder that holds your .csproj: clone it next to the project, then reference it.
git clone https://github.com/camada-app/camada-dotnet ../camada-dotnet
dotnet add reference ../camada-dotnet/src/Camada/Camada.csproj// Program.cs
using Camada.AspNetCore;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddCamada(); // one engine from the environment, drained on shutdown
var app = builder.Build();
app.UseCamada(); // FIRST: camada answers before routing, static files, anything
// your routes go here, the beacon one below included: app.Run() blocks, so nothing after it is mapped
app.Run();Positions
Sees the true wire header order, the final status and latency, and app outcomes from track(). Does not see a TLS fingerprint or ASN; those rules skip here. Enforces IP and path entries, and the user-agent and header conditions of your custom rules, with a socket-peer or trusted-proxy IP. ASN, country and TLS-fingerprint entries fail open here.
Runs inside a Cloudflare Worker. request.cf carries the client's ASN, country and TLS fingerprint, so ASN, country and TLS-fingerprint entries genuinely enforce here, along with IP, path, user-agent and header conditions; events ship through waitUntil, off the response path. Workers normalise header order, so the raw wire order is not available. Docs.
The Node position, in a Python process: final status and latency, app outcomes from track(), and the wire's header order under ASGI (FastAPI, Starlette, async Django) but not under WSGI (Flask, sync Django). No TLS fingerprint or ASN; those rules skip here. Enforces IP, path, user-agent and header conditions with a socket-peer or trusted-proxy IP. Docs.
The Node position, in a Go process: final status and latency, the route pattern, and app outcomes from Track(). net/http parses headers into a map, so the wire's header order is not available; no TLS fingerprint or ASN either, those rules skip here. Enforces IP, path, user-agent and header conditions with a socket-peer or trusted-proxy IP. Docs.
The Node position, one request at a time: final status and latency and app outcomes from track(), with the snapshot and event spool in a file-backed cache every worker shares, refreshed after the response has left. getallheaders() yields a hash, so no header order; no TLS fingerprint or ASN; those rules skip here. Enforces IP, path, user-agent and header conditions with REMOTE_ADDR or a trusted-proxy IP. Docs.
The Node position, in a Ruby process: final status and latency, the matched route, and app outcomes from Camada.track. The Rack env carries no wire header order; no TLS fingerprint or ASN; those rules skip here. Enforces IP, path, user-agent and header conditions with REMOTE_ADDR or a trusted-proxy IP — never request.ip. Docs.
The Node position, in a JVM: final status and latency, the Spring MVC route pattern, app outcomes from Camada.track(), and the header order as the container hands it over. No TLS fingerprint or ASN; those rules skip here. Enforces IP, path, user-agent and header conditions with getRemoteAddr() or a trusted-proxy IP. Docs.
The Node position, in an ASP.NET Core process: final status and latency, the matched route, and app outcomes from CamadaTrack(). Header order is what IHeaderDictionary reports, not the wire's under Kestrel; no TLS fingerprint or ASN; those rules skip here. Enforces IP, path, user-agent and header conditions with the connection peer or a trusted-proxy IP. Docs.
Runs in middleware before the cache. On Vercel it sees a JA4 TLS digest and a trustworthy client IP. Headers arrive sorted, and events ship before the response, so status is unknown except for blocks. Enforces IP and path entries and the user-agent and header conditions of your custom rules; ASN, country and TLS-fingerprint entries fail open. Needs a trusted-proxy setting off Vercel or IP rules do not enforce.