st 2.0.0 → 3.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,23 @@
1
+ name: Test
2
+ on: [push, pull_request]
3
+ jobs:
4
+ test:
5
+ strategy:
6
+ fail-fast: false
7
+ matrix:
8
+ node: [lts/*, current]
9
+ os: [macos-latest, ubuntu-latest, windows-latest]
10
+ runs-on: ${{ matrix.os }}
11
+ steps:
12
+ - name: Checkout Repository
13
+ uses: actions/checkout@v4
14
+ - name: Use Node.js ${{ matrix.node }}
15
+ uses: actions/setup-node@v4
16
+ with:
17
+ node-version: ${{ matrix.node }}
18
+ - name: Install Dependencies
19
+ run: |
20
+ npm install --no-progress
21
+ - name: Run tests
22
+ run: |
23
+ npm test
package/.travis.yml CHANGED
@@ -1,10 +1,10 @@
1
1
  sudo: false
2
2
  language: node_js
3
3
  node_js:
4
- - '10'
5
4
  - '12'
5
+ - '14'
6
6
  - lts/*
7
- - current
7
+ - node
8
8
  branches:
9
9
  only:
10
10
  - master
package/bin/server.js CHANGED
@@ -1,6 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  const st = require('../st.js')
3
3
  const http = require('http')
4
+ const { STATUS_CODES } = http
4
5
  let port = +(process.env.PORT || 1337)
5
6
  let host
6
7
  let dir = ''
@@ -180,7 +181,7 @@ http.createServer(function (q, s) {
180
181
  return
181
182
  }
182
183
  s.statusCode = 404
183
- s.end('not found')
184
+ s.end(STATUS_CODES[s.statusCode])
184
185
  }).listen(port, host, function () {
185
186
  const addr = this.address()
186
187
  const port = addr.port
package/package.json CHANGED
@@ -1,28 +1,28 @@
1
1
  {
2
2
  "name": "st",
3
- "version": "2.0.0",
3
+ "version": "3.0.1",
4
4
  "description": "A module for serving static files. Does etags, caching, etc.",
5
5
  "main": "st.js",
6
6
  "bin": "bin/server.js",
7
7
  "dependencies": {
8
8
  "async-cache": "^1.1.0",
9
- "bl": "^4.0.0",
10
- "fd": "~0.0.2",
11
- "mime": "^2.4.4",
9
+ "bl": "^5.0.0",
10
+ "fd": "~0.0.3",
11
+ "mime": "^2.5.2",
12
12
  "negotiator": "~0.6.2"
13
13
  },
14
14
  "optionalDependencies": {
15
15
  "graceful-fs": "^4.2.3"
16
16
  },
17
17
  "devDependencies": {
18
- "request": "^2.88.0",
19
- "rimraf": "^3.0.0",
20
- "standard": "^14.3.1",
21
- "tap": "^14.9.2"
18
+ "request": "^2.88.2",
19
+ "rimraf": "^3.0.2",
20
+ "standard": "^16.0.3",
21
+ "tap": "^15.0.9"
22
22
  },
23
23
  "scripts": {
24
24
  "lint": "standard",
25
- "test": "npm run lint && tap test/*.js test/cli/*-test.js"
25
+ "test": "npm run lint && tap test/*.js test/cli/*-test.js --no-coverage"
26
26
  },
27
27
  "repository": {
28
28
  "type": "git",
package/st.js CHANGED
@@ -13,6 +13,7 @@ const http = require('http')
13
13
  const AC = require('async-cache')
14
14
  const FD = require('fd')
15
15
  const bl = require('bl')
16
+ const { STATUS_CODES } = http
16
17
 
17
18
  const defaultCacheOptions = {
18
19
  fd: {
@@ -114,8 +115,10 @@ class Mount {
114
115
  this.opt = opt
115
116
  this.url = opt.url
116
117
  this.path = opt.path
117
- this._index = opt.index === false ? false
118
- : typeof opt.index === 'string' ? opt.index
118
+ this._index = opt.index === false
119
+ ? false
120
+ : typeof opt.index === 'string'
121
+ ? opt.index
119
122
  : true
120
123
  this.fdman = FD()
121
124
 
@@ -220,7 +223,10 @@ class Mount {
220
223
 
221
224
  // get a path from a url
222
225
  getPath (u) {
223
- return path.join(this.path, u)
226
+ // trailing slash removal to fix Node.js v23 bug
227
+ // https://github.com/nodejs/node/pull/55527
228
+ // can be removed when this is resolved and released
229
+ return path.join(this.path, u.replace(/\/+$/, ''))
224
230
  }
225
231
 
226
232
  // get a url from a path
@@ -251,7 +257,7 @@ class Mount {
251
257
  // If we got a 403, then it's explicitly forbidden.
252
258
  if (req.sturl === 403 || (!this.opt.dot && (/(^|\/)\./).test(req.sturl))) {
253
259
  res.statusCode = 403
254
- res.end('Forbidden')
260
+ res.end(STATUS_CODES[res.statusCode])
255
261
  return true
256
262
  }
257
263
 
@@ -347,9 +353,12 @@ class Mount {
347
353
  }
348
354
 
349
355
  error (er, res) {
350
- res.statusCode = typeof er === 'number' ? er
351
- : er.code === 'ENOENT' || er.code === 'EISDIR' ? 404
352
- : er.code === 'EPERM' || er.code === 'EACCES' ? 403
356
+ res.statusCode = typeof er === 'number'
357
+ ? er
358
+ : er.code === 'ENOENT' || er.code === 'EISDIR'
359
+ ? 404
360
+ : er.code === 'EPERM' || er.code === 'EACCES'
361
+ ? 403
353
362
  : 500
354
363
 
355
364
  if (typeof res.error === 'function') {
@@ -358,7 +367,7 @@ class Mount {
358
367
  }
359
368
 
360
369
  res.setHeader('content-type', 'text/plain')
361
- res.end(http.STATUS_CODES[res.statusCode] + '\n')
370
+ res.end(STATUS_CODES[res.statusCode] + '\n')
362
371
  }
363
372
 
364
373
  index (p, req, res) {
@@ -559,10 +568,14 @@ class Mount {
559
568
  return ['<a href="' + linkName + '">' + showName + '</a>',
560
569
  d.mtime, d.size, showName]
561
570
  }).sort((a, b) => {
562
- return a[2] === '-' && b[2] !== '-' ? -1 // dirs first
563
- : a[2] !== '-' && b[2] === '-' ? 1
564
- : a[0].toLowerCase() < b[0].toLowerCase() ? -1 // then alpha
565
- : a[0].toLowerCase() > b[0].toLowerCase() ? 1
571
+ return a[2] === '-' && b[2] !== '-' // dirs first
572
+ ? -1
573
+ : a[2] !== '-' && b[2] === '-'
574
+ ? 1
575
+ : a[0].toLowerCase() < b[0].toLowerCase() // then alpha
576
+ ? -1
577
+ : a[0].toLowerCase() > b[0].toLowerCase()
578
+ ? 1
566
579
  : 0
567
580
  }).forEach((line) => {
568
581
  const namePad = new Array(8 + nameLen - line[3].length).join(' ')
package/test/basic.js CHANGED
@@ -97,6 +97,14 @@ test('multiball!', (t) => {
97
97
  }
98
98
  })
99
99
 
100
+ test('trailing slash', (t) => {
101
+ req('/test/test/fixtures/', (er, res, body) => {
102
+ t.equal(res.statusCode, 200)
103
+ t.ok(/<html>.*Index of \/test\/fixtures<[\s\S]+index\.html[\s\S]+space in filename\.txt[\s\S]+<\/html>/.test(body.toString()))
104
+ t.end()
105
+ })
106
+ })
107
+
100
108
  test('space in filename', (t) => {
101
109
  req('/test/test/fixtures/space in filename.txt', (er, res, body) => {
102
110
  t.equal(res.statusCode, 200)
@@ -4,12 +4,12 @@ const { serve, stExpect } = require('./common')
4
4
  test('Basic cli operation', (t) => {
5
5
  serve([], (req) => {
6
6
  req('/st.js', (er, res, body) => {
7
- t.ifError(er) &&
7
+ t.error(er) &&
8
8
  t.equal(res.statusCode, 200) &&
9
9
  t.equal(body.toString(), stExpect)
10
10
  })
11
11
  }, (er, stdout, stderr) => {
12
- t.ifError(er)
12
+ t.error(er)
13
13
  t.match(stdout, /^listening at http:\/\/(\[::\]|0\.0\.0\.0):[0-9]+\n$/)
14
14
  t.equal(stderr, '')
15
15
  t.end()
@@ -19,12 +19,12 @@ test('Basic cli operation', (t) => {
19
19
  test('Listening on localhost only', (t) => {
20
20
  serve(['--localhost'], (req) => {
21
21
  req('/st.js', (er, res, body) => {
22
- t.ifError(er) &&
22
+ t.error(er) &&
23
23
  t.equal(res.statusCode, 200) &&
24
24
  t.equal(body.toString(), stExpect)
25
25
  })
26
26
  }, (er, stdout, stderr) => {
27
- t.ifError(er)
27
+ t.error(er)
28
28
  t.match(stdout, /^listening at http:\/\/localhost:[0-9]+\n$/)
29
29
  t.equal(stderr, '')
30
30
  t.end()
@@ -1,4 +1,5 @@
1
1
  const os = require('os')
2
+ const dns = require('dns')
2
3
  let { test, fail, comment } = require('tap')
3
4
  const { serve } = require('./common')
4
5
  const port = 1338
@@ -44,7 +45,7 @@ function testServer (name, args, addr, canConnect, cannotConnect) {
44
45
  canConnect.forEach(checkConnections(t, req, true))
45
46
  cannotConnect.forEach(checkConnections(t, req, false))
46
47
  }, (err, stdout, stderr) => {
47
- t.ifError(err)
48
+ t.error(err)
48
49
  t.equal(stderr, '')
49
50
  if (addr) {
50
51
  t.equal(stdout, 'listening at ' + addr2url(addr) + '\n')
@@ -59,7 +60,7 @@ function checkConnections (t, req, canConnect) {
59
60
  const url = addr2url(addr, '/st.js')
60
61
  req(url, (er, res, body) => {
61
62
  if (canConnect) {
62
- t.ifError(er, url) && t.equal(res.statusCode, 200, url)
63
+ t.error(er, url) && t.equal(res.statusCode, 200, url)
63
64
  } else {
64
65
  t.ok(er, url)
65
66
  }
@@ -73,12 +74,6 @@ testServer(
73
74
  ['127.0.0.1', 'localhost', otherAddress], []
74
75
  )
75
76
 
76
- testServer(
77
- 'Restricted to localhost',
78
- ['--localhost'], 'localhost',
79
- ['127.0.0.1', 'localhost'], [otherAddress]
80
- )
81
-
82
77
  testServer(
83
78
  'Restricted to non-local host',
84
79
  ['--host', otherAddress], otherAddress,
@@ -90,3 +85,14 @@ testServer(
90
85
  ['--host', '127.0.0.1'], '127.0.0.1',
91
86
  ['127.0.0.1'], ['::1']
92
87
  )
88
+
89
+ dns.lookup('localhost', (err, address) => {
90
+ if (err) {
91
+ throw err
92
+ }
93
+ testServer(
94
+ 'Restricted to localhost',
95
+ ['--localhost'], 'localhost',
96
+ [address, 'localhost'], [otherAddress]
97
+ )
98
+ })
File without changes
package/test/common.js CHANGED
@@ -2,7 +2,7 @@ const path = require('path')
2
2
  const fs = require('fs')
3
3
  const http = require('http')
4
4
  const request = require('request')
5
- const { test, tearDown } = require('tap')
5
+ const { test, teardown } = require('tap')
6
6
 
7
7
  const st = require('../st.js')
8
8
 
@@ -56,7 +56,7 @@ test('setup', (t) => {
56
56
  })
57
57
  })
58
58
 
59
- tearDown(() => {
59
+ teardown(() => {
60
60
  server.close()
61
61
  })
62
62
 
@@ -1,7 +1,7 @@
1
1
  const path = require('path')
2
2
  const http = require('http')
3
3
  const request = require('request')
4
- const { test, tearDown } = require('tap')
4
+ const { test, teardown } = require('tap')
5
5
 
6
6
  const st = require('../st.js')
7
7
 
@@ -37,7 +37,7 @@ test('setup', (t) => {
37
37
  })
38
38
  })
39
39
 
40
- tearDown(() => {
40
+ teardown(() => {
41
41
  server.close()
42
42
  })
43
43
 
@@ -25,7 +25,7 @@ test('gzips second response', (t) => {
25
25
  t.equal(res.headers['x-from-cache'], 'true')
26
26
 
27
27
  t.ok(body, 'returned a body')
28
- t.notEqual(body.toString(), stExpect, 'gzipped string')
28
+ t.not(body.toString(), stExpect, 'gzipped string')
29
29
 
30
30
  zlib.gunzip(body, (er, body) => {
31
31
  if (er) {
@@ -90,7 +90,7 @@ test('setup middleware server', function (t) {
90
90
  })
91
91
  })
92
92
  })
93
- middlewareServer.listen(port, '127.0.0.1', function () {
93
+ middlewareServer.listen(port, 'localhost', function () {
94
94
  t.pass('listening')
95
95
  t.end()
96
96
  })
@@ -103,7 +103,7 @@ test('setup regular server', function (t) {
103
103
  return res.end(`Not a match: ${req.url}`)
104
104
  }
105
105
  })
106
- server.listen(port + 1, '127.0.0.1', function () {
106
+ server.listen(port + 1, 'localhost', function () {
107
107
  t.pass('listening')
108
108
  t.end()
109
109
  })
@@ -114,6 +114,7 @@ const stExpect = fs.readFileSync(require.resolve('../st.js')).toString()
114
114
 
115
115
  test('/test/st.js', function (t) {
116
116
  req('/test/st.js', function (er, res, body) {
117
+ t.error(er)
117
118
  t.equal(res.statusCode, 200)
118
119
  t.ok(res.headers.etag)
119
120
  stEtag = res.headers.etag
@@ -1,5 +1,5 @@
1
1
  const st = require('../st.js')
2
- const { test, tearDown } = require('tap')
2
+ const { test, teardown } = require('tap')
3
3
  const path = require('path')
4
4
  const http = require('http')
5
5
  const request = require('request')
@@ -42,7 +42,7 @@ test('setup', (t) => {
42
42
  })
43
43
  })
44
44
 
45
- tearDown(() => {
45
+ teardown(() => {
46
46
  server.close()
47
47
  })
48
48
 
File without changes