or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

app-creation.mdcontext-events.mdcore-framework.mdgithub-api.mdindex.mdserver-middleware.md

server-middleware.mddocs/

0

# HTTP Server and Middleware

1

2

The Server class provides a built-in HTTP server for receiving GitHub webhooks, serving web interfaces, and handling custom HTTP requests with extensible middleware support.

3

4

## Capabilities

5

6

### Server Class

7

8

Built-in HTTP server with webhook handling, static file serving, and custom route support.

9

10

```typescript { .api }

11

/**

12

* HTTP server for handling webhooks and web requests

13

*/

14

class Server {

15

/**

16

* Create a new server instance

17

* @param options - Server configuration options

18

*/

19

constructor(options: ServerOptions = {});

20

21

/**

22

* Get the Probot framework version

23

* @returns Version string

24

*/

25

static get version(): string;

26

}

27

```

28

29

**Usage Examples:**

30

31

```typescript

32

import { Server, Probot } from "probot";

33

34

// Basic server setup

35

const server = new Server({

36

port: 3000,

37

host: "localhost",

38

Probot: Probot,

39

});

40

41

// Server with custom options

42

const server = new Server({

43

port: process.env.PORT || 3000,

44

webhookPath: "/api/github/webhooks",

45

enablePing: true,

46

enableStaticFiles: true,

47

loggingOptions: {

48

level: "info",

49

},

50

});

51

```

52

53

### Server Properties

54

55

Access to server configuration and runtime properties.

56

57

```typescript { .api }

58

/**

59

* Port the server is configured to listen on

60

*/

61

get port(): number;

62

63

/**

64

* Host the server is configured to bind to

65

*/

66

get host(): string;

67

68

/**

69

* Server instance version (same as Probot version)

70

*/

71

get version(): string;

72

```

73

74

**Usage Examples:**

75

76

```typescript

77

const server = new Server({ port: 3000, host: "0.0.0.0" });

78

79

console.log(`Server will start on ${server.host}:${server.port}`);

80

console.log(`Server version: ${server.version}`);

81

```

82

83

### Handler Management

84

85

Methods for registering custom HTTP request handlers.

86

87

```typescript { .api }

88

/**

89

* Add a custom HTTP request handler

90

* @param handler - Handler function for processing HTTP requests

91

*/

92

addHandler(handler: Handler): void;

93

94

/**

95

* Load a handler factory function

96

* @param appFn - Factory function that returns a handler

97

*/

98

async loadHandlerFactory(appFn: HandlerFactory): Promise<void>;

99

100

/**

101

* Load an application function that may register handlers

102

* @param appFn - Application function to load

103

*/

104

async load(appFn: ApplicationFunction): Promise<void>;

105

```

106

107

**Usage Examples:**

108

109

```typescript

110

// Add custom handler

111

server.addHandler((req, res) => {

112

if (req.url === "/health") {

113

res.writeHead(200, { "Content-Type": "application/json" });

114

res.end(JSON.stringify({ status: "ok", timestamp: new Date().toISOString() }));

115

return true; // Handler processed the request

116

}

117

return false; // Pass to next handler

118

});

119

120

// Handler factory

121

const createAPIHandler = (app: Probot, options) => {

122

return (req, res) => {

123

if (req.url?.startsWith("/api/v1/")) {

124

// Custom API logic

125

res.writeHead(200, { "Content-Type": "application/json" });

126

res.end(JSON.stringify({ message: "API endpoint" }));

127

return true;

128

}

129

return false;

130

};

131

};

132

133

await server.loadHandlerFactory(createAPIHandler);

134

135

// Application function that adds handlers

136

const appWithRoutes = (app: Probot, { addHandler }) => {

137

// Register webhook handlers

138

app.on("issues.opened", async (context) => {

139

// Handle webhook

140

});

141

142

// Add custom HTTP routes

143

addHandler((req, res) => {

144

if (req.url === "/dashboard") {

145

res.writeHead(200, { "Content-Type": "text/html" });

146

res.end("<h1>Dashboard</h1>");

147

return true;

148

}

149

return false;

150

});

151

};

152

153

await server.load(appWithRoutes);

154

```

155

156

### Server Lifecycle

157

158

Methods for starting and stopping the HTTP server.

159

160

```typescript { .api }

161

/**

162

* Start the HTTP server with all configured handlers

163

* Sets up default handlers for webhooks, ping, static files, and 404s

164

* @returns Promise resolving to Node.js HTTP server instance

165

*/

166

async start(): Promise<HttpServer>;

167

168

/**

169

* Stop the HTTP server and clean up resources

170

* Closes webhook proxy connections if configured

171

*/

172

async stop(): Promise<void>;

173

```

174

175

**Usage Examples:**

176

177

```typescript

178

import { Server, Probot } from "probot";

179

180

const server = new Server({

181

port: 3000,

182

Probot: Probot,

183

});

184

185

// Load application

186

await server.load((app) => {

187

app.on("push", async (context) => {

188

context.log.info("Push received");

189

});

190

});

191

192

// Start server

193

const httpServer = await server.start();

194

console.log(`Server started on port ${server.port}`);

195

196

// Graceful shutdown

197

process.on("SIGTERM", async () => {

198

console.log("Shutting down server...");

199

await server.stop();

200

process.exit(0);

201

});

202

```

203

204

## Built-in Handlers

205

206

### Webhook Handler

207

208

Automatically configured to handle GitHub webhook events at the specified webhook path.

209

210

```typescript { .api }

211

// Default webhook path: "/api/github/webhooks"

212

// Handles POST requests with GitHub webhook payloads

213

// Verifies webhook signatures using the configured secret

214

// Parses payloads and triggers registered event handlers

215

```

216

217

### Ping Handler

218

219

Optional health check endpoint for monitoring server availability.

220

221

```typescript { .api }

222

// Endpoint: GET /ping

223

// Response: "PONG" with 200 status

224

// Enabled with: enablePing: true in ServerOptions

225

```

226

227

**Usage Examples:**

228

229

```typescript

230

const server = new Server({

231

enablePing: true,

232

});

233

234

// GET /ping -> "PONG"

235

```

236

237

### Static Files Handler

238

239

Optional static file serving for web interfaces and assets.

240

241

```typescript { .api }

242

// Serves files from ./static directory

243

// Endpoint: GET /static/*

244

// Enabled with: enableStaticFiles: true in ServerOptions

245

```

246

247

**Usage Examples:**

248

249

```typescript

250

const server = new Server({

251

enableStaticFiles: true,

252

});

253

254

// Files in ./static/logo.png -> GET /static/logo.png

255

// Files in ./static/css/styles.css -> GET /static/css/styles.css

256

```

257

258

### Not Found Handler

259

260

Default 404 handler for unmatched requests.

261

262

```typescript { .api }

263

// Returns 404 status for unhandled requests

264

// Enabled with: enableNotFound: true in ServerOptions (default: true)

265

// Can be disabled to allow custom 404 handling

266

```

267

268

## Configuration Types

269

270

```typescript { .api }

271

interface ServerOptions {

272

/** Current working directory */

273

cwd?: string;

274

/** Logger instance for server logs */

275

log?: Logger;

276

/** Port to listen on */

277

port?: number;

278

/** Host to bind to */

279

host?: string;

280

/** Webhook endpoint path */

281

webhookPath?: string;

282

/** Smee.io proxy URL for development */

283

webhookProxy?: string;

284

/** Enable GET /ping endpoint */

285

enablePing?: boolean;

286

/** Enable 404 not found handler */

287

enableNotFound?: boolean;

288

/** Enable static file serving from ./static */

289

enableStaticFiles?: boolean;

290

/** Probot class to use for app instances */

291

Probot: typeof Probot;

292

/** HTTP request logging configuration */

293

loggingOptions?: LoggingOptions;

294

/** Octokit request configuration */

295

request?: RequestRequestOptions;

296

}

297

298

type Handler = (

299

req: IncomingMessage,

300

res: ServerResponse

301

) => void | boolean | Promise<void | boolean>;

302

303

type HandlerFactory = (

304

app: Probot,

305

options: ApplicationFunctionOptions

306

) => Handler | Promise<Handler>;

307

308

type ApplicationFunction = (

309

app: Probot,

310

options: ApplicationFunctionOptions

311

) => void | Promise<void>;

312

313

interface LoggingOptions {

314

/** Log level for HTTP requests */

315

level?: "trace" | "debug" | "info" | "warn" | "error" | "fatal" | "silent";

316

/** Custom logger instance */

317

logger?: Logger;

318

/** Custom serializers for request/response logging */

319

serializers?: Record<string, (obj: any) => any>;

320

}

321

322

interface ApplicationFunctionOptions {

323

/** Current working directory */

324

cwd: string;

325

/** Function to register custom HTTP handlers */

326

addHandler: (handler: Handler) => void;

327

/** Additional options */

328

[key: string]: unknown;

329

}

330

```

331

332

## Middleware Integration

333

334

### Express Integration

335

336

```typescript

337

import express from "express";

338

import { createNodeMiddleware } from "probot";

339

340

const app = express();

341

342

// Create Probot middleware

343

const probotMiddleware = await createNodeMiddleware((app) => {

344

app.on("issues.opened", async (context) => {

345

// Handle GitHub webhooks

346

});

347

});

348

349

// Mount Probot middleware

350

app.use("/github", probotMiddleware);

351

352

// Add other Express routes

353

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

354

res.send("Hello World");

355

});

356

357

app.listen(3000);

358

```

359

360

### Fastify Integration

361

362

```typescript

363

import Fastify from "fastify";

364

import { createNodeMiddleware } from "probot";

365

366

const fastify = Fastify();

367

368

// Create Probot handler

369

const probotHandler = await createNodeMiddleware((app) => {

370

app.on("push", async (context) => {

371

// Handle webhooks

372

});

373

});

374

375

// Register as Fastify plugin

376

fastify.register(async (fastify) => {

377

fastify.all("/webhooks/*", async (request, reply) => {

378

return probotHandler(request.raw, reply.raw);

379

});

380

});

381

382

await fastify.listen({ port: 3000 });

383

```

384

385

### Custom HTTP Server

386

387

```typescript

388

import { createServer } from "http";

389

import { createNodeMiddleware } from "probot";

390

391

const middleware = await createNodeMiddleware((app) => {

392

app.on("repository.created", async (context) => {

393

context.log.info("New repository created");

394

});

395

});

396

397

const server = createServer(async (req, res) => {

398

// Try Probot middleware first

399

const handled = await middleware(req, res);

400

401

if (!handled) {

402

// Handle other routes

403

res.writeHead(404);

404

res.end("Not Found");

405

}

406

});

407

408

server.listen(3000);

409

```

410

411

## Types

412

413

```typescript { .api }

414

type HandlerFactory = (

415

app: Probot,

416

options: ApplicationFunctionOptions

417

) => Handler | Promise<Handler>;

418

```