or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

analysis.mdbackend-api.mdcli.mdindex.mdingestors.mdintegration.mdtesting.mdtypes.md

ingestors.mddocs/

0

# Ingestor SDKs and Integration Libraries

1

2

Metlo provides comprehensive ingestor SDKs for collecting API traffic across multiple programming languages and frameworks. These libraries automatically capture HTTP requests and responses, perform security analysis, and forward data to the Metlo backend for monitoring and vulnerability detection.

3

4

## Capabilities

5

6

### Node.js Ingestor

7

8

#### Core Package (`metlo`)

9

10

The main Node.js ingestor package for automatic traffic collection and analysis.

11

12

```typescript { .api }

13

/**

14

* Initialize Metlo with backend connection

15

* @param key - Metlo API key for authentication

16

* @param host - Metlo backend URL

17

* @param opts - Optional configuration options

18

*/

19

function init(key: string, host: string, opts?: ConfigOptions): void;

20

21

interface ConfigOptions {

22

/** Number of requests per second to send to backend (default: 10) */

23

rps?: number;

24

/** Disable Metlo collection entirely */

25

disable?: boolean;

26

/** Custom configuration for redacting sensitive data */

27

redactionConfig?: RedactionConfig;

28

/** Maximum request body size to capture (bytes) */

29

maxBodySize?: number;

30

/** Headers to exclude from capture */

31

excludeHeaders?: string[];

32

/** Paths to exclude from monitoring */

33

excludePaths?: string[];

34

}

35

36

interface RedactionConfig {

37

/** Automatically redact detected PII data */

38

redactPII?: boolean;

39

/** Custom field patterns to redact */

40

customRedactFields?: string[];

41

/** Replacement text for redacted fields */

42

redactionText?: string;

43

}

44

```

45

46

**Usage Examples:**

47

48

```typescript

49

import { init } from "metlo";

50

51

// Basic initialization

52

init("your-api-key", "https://your-metlo-backend.com");

53

54

// Advanced configuration

55

init("your-api-key", "https://your-metlo-backend.com", {

56

rps: 20,

57

disable: process.env.NODE_ENV === "test",

58

redactionConfig: {

59

redactPII: true,

60

customRedactFields: ["password", "secret", "token"],

61

redactionText: "[REDACTED]"

62

},

63

maxBodySize: 50 * 1024, // 50KB

64

excludeHeaders: ["authorization", "cookie"],

65

excludePaths: ["/health", "/metrics"]

66

});

67

```

68

69

#### Express.js Integration

70

71

Automatic middleware injection for Express applications.

72

73

```typescript { .api }

74

// Automatically detects Express usage and injects middleware

75

// No additional configuration required beyond init()

76

```

77

78

**Usage Examples:**

79

80

```typescript

81

import express from "express";

82

import { init } from "metlo";

83

84

// Initialize Metlo before setting up routes

85

init("your-api-key", "https://your-metlo-backend.com");

86

87

const app = express();

88

89

// Your existing routes - Metlo automatically captures traffic

90

app.get("/api/users", (req, res) => {

91

res.json({ users: [] });

92

});

93

94

app.post("/api/users", (req, res) => {

95

// Metlo captures both request and response automatically

96

res.json({ created: true });

97

});

98

99

app.listen(3000);

100

```

101

102

#### Framework Support

103

104

The Node.js ingestor supports popular web frameworks through automatic detection:

105

106

- **Express.js** - Automatic middleware injection

107

- **Koa.js** - Automatic middleware injection

108

- **Fastify** - Plugin-based integration

109

- **Next.js** - API routes monitoring

110

- **NestJS** - Interceptor-based capture

111

112

### Python Ingestors

113

114

#### Flask Integration

115

116

Flask middleware for automatic API traffic collection.

117

118

```python { .api }

119

from metlo.flask import MetloFlask

120

121

# Initialize Metlo with Flask app

122

metlo = MetloFlask(

123

app, # Flask application instance

124

api_key="your-api-key", # Metlo API key

125

base_url="https://your-metlo-backend.com", # Metlo backend URL

126

rps=10, # Requests per second limit

127

disable=False # Disable flag for testing

128

)

129

```

130

131

**Usage Examples:**

132

133

```python

134

from flask import Flask, request, jsonify

135

from metlo.flask import MetloFlask

136

137

app = Flask(__name__)

138

139

# Initialize Metlo - automatically captures all routes

140

metlo = MetloFlask(

141

app,

142

api_key="your-api-key",

143

base_url="https://your-metlo-backend.com",

144

rps=15

145

)

146

147

@app.route("/api/users", methods=["GET"])

148

def get_users():

149

# Metlo automatically captures this request/response

150

return jsonify({"users": []})

151

152

@app.route("/api/users", methods=["POST"])

153

def create_user():

154

user_data = request.get_json()

155

# Metlo captures request body and response

156

return jsonify({"created": True, "id": 123})

157

158

if __name__ == "__main__":

159

app.run()

160

```

161

162

#### Django Integration

163

164

Django middleware for comprehensive traffic monitoring.

165

166

```python { .api }

167

# settings.py

168

MIDDLEWARE = [

169

'metlo.django.MetloMiddleware', # Add as first middleware

170

# ... other middleware

171

]

172

173

METLO_CONFIG = {

174

'API_KEY': 'your-api-key',

175

'BASE_URL': 'https://your-metlo-backend.com',

176

'RPS': 10,

177

'DISABLE': False,

178

'REDACT_PII': True,

179

'EXCLUDE_PATHS': ['/admin/', '/static/'],

180

}

181

```

182

183

**Usage Examples:**

184

185

```python

186

# settings.py

187

MIDDLEWARE = [

188

'metlo.django.MetloMiddleware',

189

'django.middleware.security.SecurityMiddleware',

190

'django.contrib.sessions.middleware.SessionMiddleware',

191

# ... other middleware

192

]

193

194

METLO_CONFIG = {

195

'API_KEY': os.environ.get('METLO_API_KEY'),

196

'BASE_URL': 'https://your-metlo-backend.com',

197

'RPS': 20,

198

'REDACT_PII': True,

199

'EXCLUDE_PATHS': ['/admin/', '/static/', '/media/'],

200

'MAX_BODY_SIZE': 51200, # 50KB

201

}

202

203

# views.py - No changes needed, Metlo captures automatically

204

from django.http import JsonResponse

205

from django.views.decorators.csrf import csrf_exempt

206

import json

207

208

@csrf_exempt

209

def api_users(request):

210

if request.method == 'GET':

211

# Metlo captures this response

212

return JsonResponse({'users': []})

213

elif request.method == 'POST':

214

data = json.loads(request.body)

215

# Metlo captures request body and response

216

return JsonResponse({'created': True})

217

```

218

219

### Java Ingestors

220

221

#### Spring Boot Integration

222

223

Comprehensive Spring framework integration with automatic configuration.

224

225

```java { .api }

226

// Maven dependency

227

<dependency>

228

<groupId>com.metlo</groupId>

229

<artifactId>metlo-spring-boot-starter</artifactId>

230

<version>1.0.0</version>

231

</dependency>

232

233

// Application properties

234

metlo.api-key=your-api-key

235

metlo.base-url=https://your-metlo-backend.com

236

metlo.rps=10

237

metlo.enabled=true

238

metlo.redact-pii=true

239

metlo.exclude-paths=/actuator/**,/swagger-ui/**

240

241

// Automatic configuration via @EnableMetlo

242

@SpringBootApplication

243

@EnableMetlo

244

public class Application {

245

public static void main(String[] args) {

246

SpringApplication.run(Application.class, args);

247

}

248

}

249

```

250

251

**Usage Examples:**

252

253

```java

254

// Application.java

255

@SpringBootApplication

256

@EnableMetlo // Enables automatic Metlo integration

257

public class ApiApplication {

258

public static void main(String[] args) {

259

SpringApplication.run(ApiApplication.class, args);

260

}

261

}

262

263

// Controller - No changes needed

264

@RestController

265

@RequestMapping("/api")

266

public class UserController {

267

268

@GetMapping("/users")

269

public ResponseEntity<List<User>> getUsers() {

270

// Metlo automatically captures this endpoint

271

List<User> users = userService.findAll();

272

return ResponseEntity.ok(users);

273

}

274

275

@PostMapping("/users")

276

public ResponseEntity<User> createUser(@RequestBody CreateUserRequest request) {

277

// Metlo captures request body and response automatically

278

User user = userService.create(request);

279

return ResponseEntity.status(HttpStatus.CREATED).body(user);

280

}

281

}

282

283

// application.yml configuration

284

metlo:

285

api-key: ${METLO_API_KEY}

286

base-url: https://your-metlo-backend.com

287

rps: 15

288

enabled: true

289

redact-pii: true

290

exclude-paths:

291

- /actuator/**

292

- /swagger-ui/**

293

- /health

294

max-body-size: 51200

295

```

296

297

#### Spring WebFlux (Reactive) Integration

298

299

Support for reactive Spring applications.

300

301

```java { .api }

302

@Configuration

303

@EnableMetloWebFlux

304

public class MetloConfiguration {

305

306

@Bean

307

public MetloWebFilter metloWebFilter() {

308

return MetloWebFilter.builder()

309

.apiKey("your-api-key")

310

.baseUrl("https://your-metlo-backend.com")

311

.rps(10)

312

.redactPII(true)

313

.build();

314

}

315

}

316

```

317

318

### Go Ingestors

319

320

#### Core Go Package

321

322

Main Go library for HTTP traffic collection.

323

324

```go { .api }

325

package metlo

326

327

// Initialize Metlo with default settings

328

func InitMetlo(metloHost, metloKey string) *Metlo

329

330

// Initialize Metlo with custom configuration

331

func InitMetloCustom(metloHost, metloKey string, rps int, disable bool) *Metlo

332

333

type Metlo struct {

334

// Configuration options

335

Host string

336

APIKey string

337

RPS int

338

Disabled bool

339

}

340

341

// Middleware for standard http.Handler

342

func (m *Metlo) Middleware(next http.Handler) http.Handler

343

344

// Configuration options

345

type Config struct {

346

APIKey string

347

Host string

348

RPS int

349

Disable bool

350

RedactPII bool

351

ExcludePaths []string

352

MaxBodySize int64

353

}

354

```

355

356

**Usage Examples:**

357

358

```go

359

package main

360

361

import (

362

"net/http"

363

"github.com/metlo-labs/metlo/golang/metlo"

364

)

365

366

func main() {

367

// Initialize Metlo

368

m := metlo.InitMetlo("https://your-metlo-backend.com", "your-api-key")

369

370

// Create your HTTP handlers

371

mux := http.NewServeMux()

372

mux.HandleFunc("/api/users", func(w http.ResponseWriter, r *http.Request) {

373

w.Header().Set("Content-Type", "application/json")

374

w.Write([]byte(`{"users": []}`))

375

})

376

377

// Wrap with Metlo middleware

378

handler := m.Middleware(mux)

379

380

// Start server

381

http.ListenAndServe(":8080", handler)

382

}

383

384

// Advanced configuration

385

func mainAdvanced() {

386

config := metlo.Config{

387

APIKey: "your-api-key",

388

Host: "https://your-metlo-backend.com",

389

RPS: 20,

390

RedactPII: true,

391

ExcludePaths: []string{"/health", "/metrics"},

392

MaxBodySize: 50 * 1024, // 50KB

393

}

394

395

m := metlo.InitMetloWithConfig(config)

396

397

// Use with your web framework

398

handler := m.Middleware(yourHandler)

399

http.ListenAndServe(":8080", handler)

400

}

401

```

402

403

#### Gin Framework Integration

404

405

Dedicated middleware for the Gin web framework.

406

407

```go { .api }

408

import "github.com/metlo-labs/metlo/golang/gin"

409

410

// Gin middleware

411

func MetloGinMiddleware(apiKey, host string) gin.HandlerFunc

412

func MetloGinMiddlewareWithConfig(config metlo.Config) gin.HandlerFunc

413

```

414

415

**Usage Examples:**

416

417

```go

418

package main

419

420

import (

421

"github.com/gin-gonic/gin"

422

"github.com/metlo-labs/metlo/golang/gin"

423

)

424

425

func main() {

426

r := gin.Default()

427

428

// Add Metlo middleware

429

r.Use(gin_metlo.MetloGinMiddleware("your-api-key", "https://your-metlo-backend.com"))

430

431

// Define routes - Metlo captures automatically

432

r.GET("/api/users", func(c *gin.Context) {

433

c.JSON(200, gin.H{"users": []string{}})

434

})

435

436

r.POST("/api/users", func(c *gin.Context) {

437

var user map[string]interface{}

438

c.ShouldBindJSON(&user)

439

c.JSON(201, gin.H{"created": true, "id": 123})

440

})

441

442

r.Run(":8080")

443

}

444

```

445

446

#### Gorilla Mux Integration

447

448

Integration with Gorilla Mux router.

449

450

```go { .api }

451

import "github.com/metlo-labs/metlo/golang/mux"

452

453

// Mux middleware

454

func MetloMuxMiddleware(apiKey, host string) mux.MiddlewareFunc

455

```

456

457

### Rust Ingestor

458

459

#### Core Rust Crate

460

461

Common utilities and types for Rust integrations.

462

463

```rust { .api }

464

use metlo_rust::{MetloConfig, MetloClient};

465

466

pub struct MetloConfig {

467

pub api_key: String,

468

pub host: String,

469

pub rps: u32,

470

pub disable: bool,

471

pub redact_pii: bool,

472

}

473

474

pub struct MetloClient {

475

config: MetloConfig,

476

}

477

478

impl MetloClient {

479

pub fn new(config: MetloConfig) -> Self;

480

pub async fn capture_request(&self, request: CaptureRequest) -> Result<(), MetloError>;

481

}

482

483

pub struct CaptureRequest {

484

pub method: String,

485

pub path: String,

486

pub headers: Vec<(String, String)>,

487

pub body: Option<String>,

488

pub response_status: u16,

489

pub response_headers: Vec<(String, String)>,

490

pub response_body: Option<String>,

491

}

492

```

493

494

**Usage Examples:**

495

496

```rust

497

use metlo_rust::{MetloConfig, MetloClient};

498

use warp::Filter;

499

500

#[tokio::main]

501

async fn main() {

502

// Initialize Metlo

503

let config = MetloConfig {

504

api_key: "your-api-key".to_string(),

505

host: "https://your-metlo-backend.com".to_string(),

506

rps: 10,

507

disable: false,

508

redact_pii: true,

509

};

510

511

let metlo_client = MetloClient::new(config);

512

513

// Create Warp filter with Metlo middleware

514

let api = warp::path("api")

515

.and(warp::path("users"))

516

.and(warp::get())

517

.and(with_metlo(metlo_client))

518

.and_then(get_users);

519

520

warp::serve(api)

521

.run(([127, 0, 0, 1], 3030))

522

.await;

523

}

524

525

async fn get_users() -> Result<impl warp::Reply, warp::Rejection> {

526

Ok(warp::reply::json(&serde_json::json!({"users": []})))

527

}

528

```

529

530

### Kubernetes Integration

531

532

#### Deployment Configuration

533

534

Deploy Metlo ingestors in Kubernetes environments.

535

536

```yaml { .api }

537

# metlo-configmap.yaml

538

apiVersion: v1

539

kind: ConfigMap

540

metadata:

541

name: metlo-config

542

data:

543

METLO_API_KEY: "your-api-key"

544

METLO_HOST: "https://your-metlo-backend.com"

545

METLO_RPS: "10"

546

547

---

548

# metlo-deployment.yaml

549

apiVersion: apps/v1

550

kind: Deployment

551

metadata:

552

name: your-app

553

spec:

554

template:

555

spec:

556

containers:

557

- name: app

558

image: your-app:latest

559

env:

560

- name: METLO_API_KEY

561

valueFrom:

562

configMapKeyRef:

563

name: metlo-config

564

key: METLO_API_KEY

565

- name: METLO_HOST

566

valueFrom:

567

configMapKeyRef:

568

name: metlo-config

569

key: METLO_HOST

570

```

571

572

#### DaemonSet for Traffic Mirroring

573

574

Deploy traffic mirroring agents across Kubernetes nodes.

575

576

```yaml { .api }

577

apiVersion: apps/v1

578

kind: DaemonSet

579

metadata:

580

name: metlo-traffic-mirror

581

spec:

582

selector:

583

matchLabels:

584

name: metlo-traffic-mirror

585

template:

586

metadata:

587

labels:

588

name: metlo-traffic-mirror

589

spec:

590

hostNetwork: true

591

containers:

592

- name: metlo-mirror

593

image: metlo/traffic-mirror:latest

594

env:

595

- name: METLO_API_KEY

596

value: "your-api-key"

597

- name: METLO_HOST

598

value: "https://your-metlo-backend.com"

599

securityContext:

600

privileged: true

601

volumeMounts:

602

- name: proc

603

mountPath: /host/proc

604

readOnly: true

605

- name: sys

606

mountPath: /host/sys

607

readOnly: true

608

volumes:

609

- name: proc

610

hostPath:

611

path: /proc

612

- name: sys

613

hostPath:

614

path: /sys

615

```

616

617

### Burp Suite Integration

618

619

#### Security Testing Extension

620

621

Burp Suite extension for API security testing integration.

622

623

```java { .api }

624

// Extension configuration

625

public class MetloBurpExtension implements IBurpExtender {

626

627

public void registerExtenderCallbacks(IBurpExtenderCallbacks callbacks) {

628

// Initialize Metlo integration

629

MetloConfig config = new MetloConfig(

630

"your-api-key",

631

"https://your-metlo-backend.com"

632

);

633

634

// Register HTTP listener

635

callbacks.registerHttpListener(new MetloHttpListener(config));

636

}

637

}

638

```

639

640

**Features:**

641

- Automatic request/response capture during security testing

642

- Integration with Metlo test generation

643

- Export scan results to Metlo backend

644

- Custom vulnerability detection rules

645

646

### Docker Compose Integration

647

648

#### Complete Environment Setup

649

650

Docker Compose configuration for development environments.

651

652

```yaml { .api }

653

version: '3.8'

654

services:

655

app:

656

build: .

657

environment:

658

- METLO_API_KEY=your-api-key

659

- METLO_HOST=http://metlo-backend:3000

660

- METLO_RPS=15

661

depends_on:

662

- metlo-backend

663

664

metlo-backend:

665

image: metlo/backend:latest

666

ports:

667

- "3000:3000"

668

environment:

669

- DATABASE_URL=postgresql://postgres:password@db:5432/metlo

670

- REDIS_URL=redis://redis:6379

671

depends_on:

672

- db

673

- redis

674

675

db:

676

image: postgres:13

677

environment:

678

- POSTGRES_DB=metlo

679

- POSTGRES_PASSWORD=password

680

681

redis:

682

image: redis:6-alpine

683

```

684

685

## Configuration Best Practices

686

687

### Production Configuration

688

689

```typescript

690

// Recommended production settings

691

const productionConfig = {

692

rps: 50, // Higher throughput for production

693

redactPII: true, // Always redact sensitive data

694

maxBodySize: 100 * 1024, // 100KB limit

695

excludePaths: [

696

"/health",

697

"/metrics",

698

"/favicon.ico",

699

"/robots.txt"

700

],

701

excludeHeaders: [

702

"authorization",

703

"cookie",

704

"x-api-key"

705

]

706

};

707

```

708

709

### Development Configuration

710

711

```typescript

712

// Development/testing settings

713

const developmentConfig = {

714

rps: 10, // Lower rate for dev

715

disable: process.env.NODE_ENV === "test",

716

redactPII: false, // Keep data for debugging

717

maxBodySize: 50 * 1024, // 50KB limit

718

verbose: true // Enable detailed logging

719

};

720

```

721

722

### Performance Optimization

723

724

- **Rate Limiting**: Configure appropriate RPS based on your traffic volume

725

- **Body Size Limits**: Set reasonable limits to avoid memory issues

726

- **Path Exclusion**: Exclude health checks, static assets, and admin paths

727

- **Header Filtering**: Exclude sensitive headers like authentication tokens

728

- **Async Processing**: Use background queues for high-traffic applications

729

730

### Security Considerations

731

732

- **API Key Management**: Use environment variables, never hardcode keys

733

- **Data Redaction**: Enable PII redaction in production environments

734

- **Network Security**: Use HTTPS for all Metlo backend communication

735

- **Access Control**: Restrict Metlo backend access to authorized networks

736

- **Data Retention**: Configure appropriate data retention policies