or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

assertions.mdhttp-client.mdhttp-utilities.mdindex.mdrequest-response-mocking.mdtest-doubles.mdtest-sandbox.mdvalidation-helpers.md

http-utilities.mddocs/

0

# HTTP Utilities

1

2

Async HTTP/HTTPS request utilities and server configuration helpers for test environments.

3

4

## Capabilities

5

6

### HTTP Request Utilities

7

8

Async wrappers for making HTTP and HTTPS requests.

9

10

```typescript { .api }

11

/**

12

* Async wrapper for making HTTP GET requests

13

* @param urlString - URL to request

14

* @param agent - Optional HTTP agent for connection pooling

15

* @returns Promise resolving to IncomingMessage response

16

*/

17

function httpGetAsync(

18

urlString: string,

19

agent?: http.Agent

20

): Promise<IncomingMessage>;

21

22

/**

23

* Async wrapper for making HTTPS GET requests

24

* Uses a default agent that accepts self-signed certificates

25

* @param urlString - HTTPS URL to request

26

* @param agent - Optional HTTPS agent, defaults to permissive agent

27

* @returns Promise resolving to IncomingMessage response

28

*/

29

function httpsGetAsync(

30

urlString: string,

31

agent?: https.Agent

32

): Promise<IncomingMessage>;

33

```

34

35

**Usage Examples:**

36

37

```typescript

38

import { httpGetAsync, httpsGetAsync, expect } from "@loopback/testlab";

39

import http from "http";

40

import https from "https";

41

42

// Basic HTTP request

43

const response = await httpGetAsync("http://localhost:3000/api/status");

44

expect(response.statusCode).to.equal(200);

45

46

// Read response body

47

let body = "";

48

response.on("data", (chunk) => {

49

body += chunk;

50

});

51

response.on("end", () => {

52

const data = JSON.parse(body);

53

expect(data.status).to.equal("ok");

54

});

55

56

// HTTPS request (accepts self-signed certificates by default)

57

const httpsResponse = await httpsGetAsync("https://localhost:3443/secure-endpoint");

58

expect(httpsResponse.statusCode).to.equal(200);

59

60

// Custom HTTP agent for connection pooling

61

const customAgent = new http.Agent({

62

keepAlive: true,

63

maxSockets: 5

64

});

65

66

const pooledResponse = await httpGetAsync("http://api.example.com/data", customAgent);

67

68

// Custom HTTPS agent with specific SSL options

69

const customHttpsAgent = new https.Agent({

70

rejectUnauthorized: true, // Require valid certificates

71

keepAlive: true

72

});

73

74

const secureResponse = await httpsGetAsync("https://api.example.com/secure", customHttpsAgent);

75

```

76

77

### HTTP Server Configuration

78

79

Helper functions for creating HTTP/HTTPS server configurations suitable for testing.

80

81

```typescript { .api }

82

/**

83

* Create an HTTP-server configuration that works well in test environments

84

* - Assigns ephemeral port (port 0)

85

* - Uses IPv4 localhost (127.0.0.1) to avoid IPv6 issues

86

* - Provides default TLS configuration for HTTPS

87

* @param customConfig - Additional configuration options

88

* @returns Complete server configuration with host and port

89

*/

90

function givenHttpServerConfig<T extends HttpOptions | HttpsOptions>(

91

customConfig?: T

92

): HostPort & T;

93

94

/**

95

* HTTP server configuration options

96

*/

97

interface HttpOptions extends ListenOptions {

98

protocol?: 'http';

99

}

100

101

/**

102

* HTTPS server configuration options

103

*/

104

interface HttpsOptions extends ListenOptions, HttpsServerOptions {

105

protocol: 'https';

106

}

107

108

/**

109

* Interface requiring host and port properties

110

*/

111

interface HostPort {

112

host: string;

113

port: number;

114

}

115

```

116

117

**Usage Examples:**

118

119

```typescript

120

import { givenHttpServerConfig, expect } from "@loopback/testlab";

121

import http from "http";

122

import https from "https";

123

124

// Basic HTTP server configuration

125

const httpConfig = givenHttpServerConfig();

126

expect(httpConfig.host).to.equal("127.0.0.1");

127

expect(httpConfig.port).to.equal(0); // Ephemeral port

128

129

// Create HTTP server with test config

130

const httpServer = http.createServer((req, res) => {

131

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

132

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

133

});

134

135

httpServer.listen(httpConfig, () => {

136

const address = httpServer.address() as any;

137

console.log(`HTTP server listening on ${address.address}:${address.port}`);

138

});

139

140

// HTTPS server configuration with defaults

141

const httpsConfig = givenHttpServerConfig({protocol: "https"});

142

expect(httpsConfig.protocol).to.equal("https");

143

expect(httpsConfig.host).to.equal("127.0.0.1");

144

expect(httpsConfig.port).to.equal(0);

145

expect(httpsConfig).to.have.property("key"); // Default TLS key

146

expect(httpsConfig).to.have.property("cert"); // Default TLS cert

147

148

// Create HTTPS server with test config

149

const httpsServer = https.createServer(httpsConfig, (req, res) => {

150

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

151

res.end(JSON.stringify({secure: true}));

152

});

153

154

httpsServer.listen(httpsConfig, () => {

155

const address = httpsServer.address() as any;

156

console.log(`HTTPS server listening on ${address.address}:${address.port}`);

157

});

158

159

// Custom HTTP configuration

160

const customHttpConfig = givenHttpServerConfig({

161

host: "0.0.0.0", // Accept from any interface

162

port: 8080 // Specific port

163

});

164

165

// Custom HTTPS configuration with own certificates

166

const customHttpsConfig = givenHttpServerConfig({

167

protocol: "https",

168

key: fs.readFileSync("/path/to/private-key.pem"),

169

cert: fs.readFileSync("/path/to/certificate.pem"),

170

host: "localhost",

171

port: 8443

172

});

173

```

174

175

### Error Logging

176

177

HTTP error logging utilities for debugging test failures.

178

179

```typescript { .api }

180

/**

181

* Creates a logger that logs HTTP errors when status code is unexpected

182

* @param expectedStatusCode - Status code that should not be logged

183

* @returns Error logging function

184

*/

185

function createUnexpectedHttpErrorLogger(

186

expectedStatusCode?: number

187

): LogError;

188

189

/**

190

* Error logging function type

191

*/

192

type LogError = (err: Error, statusCode: number, request: Request) => void;

193

```

194

195

**Usage Examples:**

196

197

```typescript

198

import { createUnexpectedHttpErrorLogger, expect } from "@loopback/testlab";

199

import { Request } from "express";

200

201

// Create logger that ignores 404 errors

202

const logger = createUnexpectedHttpErrorLogger(404);

203

204

// Simulate different error scenarios

205

const mockRequest = {method: "GET", url: "/api/test"} as Request;

206

207

// This will be logged (unexpected error)

208

logger(new Error("Database connection failed"), 500, mockRequest);

209

// Output: "Unhandled error in GET /api/test: 500 Error: Database connection failed..."

210

211

// This will NOT be logged (expected 404)

212

logger(new Error("Not found"), 404, mockRequest);

213

// No output

214

215

// Logger for successful requests (ignore 200)

216

const successLogger = createUnexpectedHttpErrorLogger(200);

217

218

// This will be logged (unexpected error)

219

successLogger(new Error("Validation failed"), 400, mockRequest);

220

221

// This will NOT be logged (expected success)

222

successLogger(new Error("Should not happen"), 200, mockRequest);

223

224

// Use in Express error handler

225

function errorHandler(err: Error, req: Request, res: Response, next: NextFunction) {

226

const logger = createUnexpectedHttpErrorLogger();

227

logger(err, res.statusCode || 500, req);

228

229

res.status(500).json({error: "Internal server error"});

230

}

231

```

232

233

### Integration with Test Servers

234

235

Complete examples of using HTTP utilities in test scenarios.

236

237

**Usage Examples:**

238

239

```typescript

240

import {

241

givenHttpServerConfig,

242

httpGetAsync,

243

httpsGetAsync,

244

expect

245

} from "@loopback/testlab";

246

import http from "http";

247

import https from "https";

248

249

// Test HTTP server lifecycle

250

describe("HTTP Server Tests", () => {

251

let server: http.Server;

252

let serverUrl: string;

253

254

beforeEach(async () => {

255

const config = givenHttpServerConfig();

256

257

server = http.createServer((req, res) => {

258

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

259

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

260

res.end(JSON.stringify({pong: true}));

261

} else {

262

res.writeHead(404);

263

res.end("Not found");

264

}

265

});

266

267

await new Promise<void>((resolve) => {

268

server.listen(config, () => {

269

const address = server.address() as any;

270

serverUrl = `http://${address.address}:${address.port}`;

271

resolve();

272

});

273

});

274

});

275

276

afterEach(async () => {

277

await new Promise<void>((resolve) => {

278

server.close(() => resolve());

279

});

280

});

281

282

it("should respond to ping", async () => {

283

const response = await httpGetAsync(`${serverUrl}/ping`);

284

expect(response.statusCode).to.equal(200);

285

286

let body = "";

287

response.on("data", chunk => body += chunk);

288

await new Promise(resolve => response.on("end", resolve));

289

290

expect(JSON.parse(body)).to.eql({pong: true});

291

});

292

293

it("should return 404 for unknown routes", async () => {

294

const response = await httpGetAsync(`${serverUrl}/unknown`);

295

expect(response.statusCode).to.equal(404);

296

});

297

});

298

299

// Test HTTPS server with custom certificates

300

describe("HTTPS Server Tests", () => {

301

let server: https.Server;

302

let serverUrl: string;

303

304

beforeEach(async () => {

305

const config = givenHttpServerConfig({protocol: "https"});

306

307

server = https.createServer(config, (req, res) => {

308

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

309

res.end(JSON.stringify({secure: true, url: req.url}));

310

});

311

312

await new Promise<void>((resolve) => {

313

server.listen(config, () => {

314

const address = server.address() as any;

315

serverUrl = `https://${address.address}:${address.port}`;

316

resolve();

317

});

318

});

319

});

320

321

afterEach(async () => {

322

await new Promise<void>((resolve) => {

323

server.close(() => resolve());

324

});

325

});

326

327

it("should handle HTTPS requests", async () => {

328

// Uses default permissive agent for self-signed certificates

329

const response = await httpsGetAsync(`${serverUrl}/secure`);

330

expect(response.statusCode).to.equal(200);

331

332

let body = "";

333

response.on("data", chunk => body += chunk);

334

await new Promise(resolve => response.on("end", resolve));

335

336

const data = JSON.parse(body);

337

expect(data.secure).to.be.true();

338

expect(data.url).to.equal("/secure");

339

});

340

});

341

342

// Test external API integration

343

describe("External API Tests", () => {

344

it("should handle API responses", async () => {

345

// Mock external service (you would replace with actual service in tests)

346

const mockServer = http.createServer((req, res) => {

347

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

348

res.end(JSON.stringify({data: "mock response"}));

349

});

350

351

const config = givenHttpServerConfig();

352

await new Promise<void>(resolve => mockServer.listen(config, resolve));

353

354

const address = mockServer.address() as any;

355

const mockUrl = `http://${address.address}:${address.port}`;

356

357

// Test API call

358

const response = await httpGetAsync(`${mockUrl}/api/data`);

359

expect(response.statusCode).to.equal(200);

360

361

await new Promise<void>(resolve => mockServer.close(() => resolve()));

362

});

363

});

364

```