or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

index.md
tile.json

index.mddocs/

0

# koa-send

1

2

koa-send is a static file serving middleware for Koa.js applications that provides secure, efficient delivery of static assets to web clients. It offers comprehensive file serving capabilities including automatic compression support (gzip and brotli), configurable browser caching, path normalization and security protections against directory traversal attacks, and flexible content type detection.

3

4

## Package Information

5

6

- **Package Name**: koa-send

7

- **Package Type**: npm

8

- **Language**: JavaScript (Node.js)

9

- **Installation**: `npm install koa-send`

10

11

## Core Imports

12

13

```javascript

14

const send = require('koa-send');

15

```

16

17

For ES modules:

18

19

```javascript

20

import send from 'koa-send';

21

```

22

23

## Basic Usage

24

25

```javascript

26

const send = require('koa-send');

27

const Koa = require('koa');

28

const app = new Koa();

29

30

// Basic file serving

31

app.use(async (ctx) => {

32

if (ctx.path === '/') {

33

ctx.body = 'Try GET /package.json';

34

return;

35

}

36

await send(ctx, ctx.path);

37

});

38

39

// Serve from a root directory

40

app.use(async (ctx) => {

41

await send(ctx, ctx.path, { root: __dirname + '/public' });

42

});

43

44

app.listen(3000);

45

```

46

47

## Capabilities

48

49

### Static File Serving

50

51

Serves static files with comprehensive security and performance features.

52

53

```javascript { .api }

54

/**

55

* Send static file with given options to Koa context

56

* @param {Context} ctx - Koa context object (required)

57

* @param {string} path - File path to serve (required)

58

* @param {SendOptions} opts - Options object (optional)

59

* @returns {Promise<string>} - Resolved file path that was served

60

* @throws {Error} 400 if path decode fails

61

* @throws {Error} 404 if file not found

62

* @throws {Error} 500 for other file system errors

63

* @throws {TypeError} if setHeaders is not a function

64

*/

65

async function send(ctx, path, opts = {});

66

```

67

68

**Usage Examples:**

69

70

```javascript

71

// Basic usage

72

await send(ctx, 'path/to/file.txt');

73

74

// With root directory

75

await send(ctx, ctx.path, { root: '/public' });

76

77

// With compression and caching

78

await send(ctx, ctx.path, {

79

root: __dirname + '/static',

80

maxage: 86400000, // 24 hours

81

gzip: true,

82

brotli: true,

83

immutable: true

84

});

85

86

// With custom headers

87

await send(ctx, ctx.path, {

88

root: '/assets',

89

setHeaders: (res, path, stats) => {

90

res.setHeader('X-Served-By', 'koa-send');

91

}

92

});

93

```

94

95

## Options

96

97

### SendOptions Interface

98

99

```javascript { .api }

100

/**

101

* Configuration options for the send function

102

*/

103

interface SendOptions {

104

/** Root directory to restrict file access (defaults to '') */

105

root?: string;

106

/** Browser cache max-age in milliseconds (defaults to 0) */

107

maxage?: number;

108

/** Alias for maxage (defaults to 0) */

109

maxAge?: number;

110

/** Mark resource as immutable for caching (defaults to false) */

111

immutable?: boolean;

112

/** Allow transfer of hidden files (defaults to false) */

113

hidden?: boolean;

114

/** Name of index file for directories (defaults to undefined) */

115

index?: string;

116

/** Format path for directory handling (defaults to true) */

117

format?: boolean;

118

/** File extensions to try when no extension provided (defaults to false) */

119

extensions?: Array<string> | false;

120

/** Enable brotli compression support (defaults to true) */

121

brotli?: boolean;

122

/** Enable gzip compression support (defaults to true) */

123

gzip?: boolean;

124

/** Custom headers function (defaults to undefined) */

125

setHeaders?: (res: ServerResponse, path: string, stats: Stats) => void;

126

}

127

```

128

129

### Option Details

130

131

#### Root Directory (`root`)

132

133

Specifies the root directory from which to serve files. The path is resolved and normalized for security.

134

135

```javascript

136

// Serve files from public directory

137

await send(ctx, ctx.path, { root: __dirname + '/public' });

138

139

// Serve specific file without user input

140

await send(ctx, 'path/to/my.js');

141

```

142

143

#### Caching Options (`maxage`, `immutable`)

144

145

Control browser caching behavior:

146

147

```javascript

148

// Cache for 24 hours

149

await send(ctx, ctx.path, {

150

maxage: 86400000,

151

immutable: true // Resource never changes

152

});

153

```

154

155

#### Compression (`gzip`, `brotli`)

156

157

Automatic compression based on client support:

158

159

```javascript

160

// Enable both compression methods (default)

161

await send(ctx, ctx.path, {

162

gzip: true,

163

brotli: true

164

});

165

166

// Disable compression

167

await send(ctx, ctx.path, {

168

gzip: false,

169

brotli: false

170

});

171

```

172

173

#### Extension Matching (`extensions`)

174

175

Try multiple extensions for extensionless requests:

176

177

```javascript

178

// Try .html, .js extensions

179

await send(ctx, ctx.path, {

180

extensions: ['html', 'js']

181

});

182

183

// Also works with dots

184

await send(ctx, ctx.path, {

185

extensions: ['.html', '.js']

186

});

187

```

188

189

#### Index Files (`index`)

190

191

Serve index files for directory requests:

192

193

```javascript

194

// Serve index.html for directory requests

195

await send(ctx, ctx.path, {

196

index: 'index.html',

197

format: true // Handle trailing slashes

198

});

199

```

200

201

#### Custom Headers (`setHeaders`)

202

203

Set custom response headers:

204

205

```javascript

206

await send(ctx, ctx.path, {

207

setHeaders: (res, path, stats) => {

208

// Only modify Cache-Control or Last-Modified here

209

// Other headers should be set before calling send()

210

if (path.endsWith('.js')) {

211

res.setHeader('Cache-Control', 'max-age=31536000, immutable');

212

}

213

}

214

});

215

```

216

217

## Security Features

218

219

### Path Traversal Protection

220

221

koa-send automatically protects against directory traversal attacks:

222

223

- Paths are normalized and resolved safely

224

- Parent directory references (`..`) are handled securely

225

- The `resolve-path` library provides additional security

226

227

### Hidden File Protection

228

229

By default, hidden files (starting with `.`) are not served:

230

231

```javascript

232

// Allow hidden files (use with caution)

233

await send(ctx, ctx.path, { hidden: true });

234

```

235

236

## Error Handling

237

238

The send function throws specific HTTP errors:

239

240

- **400**: Failed to decode the requested path

241

- **404**: File not found, name too long, or not a directory

242

- **500**: Other file system errors

243

- **TypeError**: Invalid `setHeaders` option (not a function)

244

245

```javascript

246

app.use(async (ctx, next) => {

247

try {

248

await send(ctx, ctx.path, { root: '/public' });

249

} catch (err) {

250

if (err.status === 404) {

251

ctx.body = 'File not found';

252

} else {

253

throw err;

254

}

255

}

256

});

257

```

258

259

## Performance Features

260

261

### Automatic Compression

262

263

Files are automatically compressed when:

264

265

- Client supports gzip or brotli encoding

266

- Corresponding compressed file exists (`.gz` or `.br`)

267

- Compression options are enabled (default)

268

269

### Efficient Streaming

270

271

Files are streamed directly to the client using Node.js streams:

272

273

- No memory buffering of large files

274

- Efficient for serving large static assets

275

- Proper Content-Length headers

276

277

### Smart Caching

278

279

Configurable browser caching with:

280

281

- `max-age` directive for cache duration

282

- `immutable` directive for permanent caching

283

- Automatic `Last-Modified` headers

284

- Conditional request support

285

286

## Types

287

288

```javascript { .api }

289

/**

290

* Node.js ServerResponse object

291

*/

292

interface ServerResponse {

293

setHeader(name: string, value: string): void;

294

removeHeader(name: string): void;

295

}

296

297

/**

298

* Node.js fs.Stats object

299

*/

300

interface Stats {

301

size: number;

302

mtime: Date;

303

isDirectory(): boolean;

304

}

305

306

/**

307

* Koa Context object (subset of properties used by send)

308

*/

309

interface Context {

310

path: string;

311

res: ServerResponse;

312

response: {

313

get(field: string): string;

314

};

315

body?: any;

316

type?: string;

317

set(field: string, val: string): void;

318

throw(status: number, message?: string): void;

319

acceptsEncodings(...encodings: string[]): string | false;

320

}

321

```