Compare commits

...

176 Commits

Author SHA1 Message Date
dependabot[bot]
0b03952404 build(deps): bump github/codeql-action from 3.29.7 to 4.31.2
Bumps [github/codeql-action](https://github.com/github/codeql-action) from 3.29.7 to 4.31.2.
- [Release notes](https://github.com/github/codeql-action/releases)
- [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md)
- [Commits](51f77329af...0499de31b9)

---
updated-dependencies:
- dependency-name: github/codeql-action
  dependency-version: 4.31.2
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-11-01 06:16:37 +00:00
dependabot[bot]
364e273836 build(deps): bump github/codeql-action from 3.28.19 to 3.29.5 (#133)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-08-01 11:22:39 +02:00
dependabot[bot]
c4cde95e31 build(deps): bump step-security/harden-runner from 2.12.0 to 2.13.0 (#132)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-08-01 11:21:02 +02:00
Sebastian Beltran
b3cf4a76ce chore: add funding to package.json (#131) 2025-07-23 14:46:10 +02:00
dependabot[bot]
988bc1109c build(deps): bump ossf/scorecard-action from 2.4.0 to 2.4.2 (#123)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-06-07 12:13:38 +02:00
dependabot[bot]
411920523e build(deps): bump actions/upload-artifact from 4.5.0 to 4.6.2 (#122)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-06-07 12:13:06 +02:00
dependabot[bot]
068b999804 build(deps): bump coverallsapp/github-action from 1.2.5 to 2.3.6 (#121)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-06-07 12:12:25 +02:00
dependabot[bot]
af5eb8e7c3 build(deps): bump github/codeql-action from 3.27.9 to 3.28.19 (#124)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-06-07 12:11:38 +02:00
Ulises Gascón
1696289791 ci: upgrade Node versions (#128) 2025-06-07 12:06:49 +02:00
Ulises Gascón
d8efc0e652 ci: apply OSSF Scorecard security best practices (#119)
Co-authored-by: Ulises Gascón <ulisesgascongonzalez@gmail.com>
Co-authored-by: StepSecurity Bot <bot@stepsecurity.io>
2025-06-05 14:40:58 +02:00
Carlos Serrano
6729afa6d2 chore: upgrade scorecard workflow pinned action versions (#112) 2025-04-17 16:17:01 +02:00
Íñigo Marquínez Prado
544279a064 ci: migrate to GitHub actions and add missing Node.js versions (#109)
- PR-URL: https://github.com/expressjs/serve-index/pull/109
- This commit drops support for Travis
2024-05-14 18:28:45 +02:00
Íñigo Marquínez Prado
7b27f08fac chore: add support for OSSF scorecard reporting (#110)
PR-URL: https://github.com/expressjs/serve-index/pull/110
2024-05-14 18:18:01 +02:00
Douglas Christopher Wilson
d2922cd872 deps: mime-types@~2.1.30 2021-04-02 22:20:37 -04:00
Douglas Christopher Wilson
51b376a02d build: use nyc for test coverage 2021-04-01 21:41:49 -04:00
Douglas Christopher Wilson
4e7785c620 Fix icons for MIME types with "+"
fixes #99
2021-04-01 16:40:42 -04:00
Douglas Christopher Wilson
7bc2da919b build: eslint@7.23.0 2021-04-01 16:35:32 -04:00
Douglas Christopher Wilson
1e07314bb3 build: Node.js@15.13 2021-03-31 20:54:39 -04:00
Douglas Christopher Wilson
b14fff17ff build: Node.js@12.22 2021-03-31 20:48:19 -04:00
Douglas Christopher Wilson
b74579da7b build: eslint-plugin-markdown@2.0.0 2021-03-17 19:57:35 -04:00
Douglas Christopher Wilson
b827e29cc0 build: mocha@8.3.2 2021-03-17 19:44:33 -04:00
Douglas Christopher Wilson
783928d36d build: Node.js@15.11 2021-03-15 16:33:41 -04:00
Douglas Christopher Wilson
c26a84ccdb build: eslint@7.21.0 2021-02-28 00:06:53 -05:00
Douglas Christopher Wilson
6410f231d2 build: mocha@8.3.0 2021-02-27 23:48:31 -05:00
Douglas Christopher Wilson
1230f3a2a4 build: Node.js@15.10 2021-02-27 23:38:30 -05:00
Douglas Christopher Wilson
5a6402bc62 deps: mime-types@~2.1.29 2021-02-27 23:31:53 -05:00
Douglas Christopher Wilson
55c94d53d7 build: eslint@7.20.0 2021-02-25 01:24:29 -05:00
Douglas Christopher Wilson
85a41c6169 build: Node.js@10.24 2021-02-25 01:22:03 -05:00
Douglas Christopher Wilson
c22ac7619b build: Node.js@12.21 2021-02-24 20:10:12 -05:00
Douglas Christopher Wilson
410d2e0336 build: Node.js@14.16 2021-02-24 20:08:10 -05:00
Douglas Christopher Wilson
395c961e7d build: Node.js@15.8 2021-02-03 00:11:40 -05:00
Douglas Christopher Wilson
91a3cd9ac1 build: eslint@7.19.0 2021-02-02 23:51:13 -05:00
Douglas Christopher Wilson
0812a30474 build: Node.js@15.7 2021-01-27 19:36:40 -05:00
Douglas Christopher Wilson
6a3fdb0dae build: supertest@6.1.3 2021-01-27 19:33:08 -05:00
Douglas Christopher Wilson
8af3044675 build: eslint@7.17.0 2021-01-04 00:12:51 -05:00
Douglas Christopher Wilson
be96563b6b build: Node.js@15.5 2021-01-04 00:09:54 -05:00
Douglas Christopher Wilson
22828c2005 deps: mime-types@~2.1.28 2021-01-03 23:55:38 -05:00
Douglas Christopher Wilson
9c8d7e70c3 build: eslint@7.15.0 2020-12-13 23:51:58 -05:00
Douglas Christopher Wilson
ac3c870ad2 build: Node.js@15.3 2020-11-27 19:09:34 -05:00
Douglas Christopher Wilson
546b996dad build: supertest@6.0.1 2020-11-18 00:48:39 -05:00
Douglas Christopher Wilson
de3bcd39c9 build: mocha@8.2.1 2020-11-18 00:42:18 -05:00
Douglas Christopher Wilson
4bd3a75480 build: Node.js@12.20 2020-11-17 20:04:08 -05:00
Douglas Christopher Wilson
0f4a3bd370 build: eslint@7.13.0 2020-11-16 17:59:52 -05:00
Douglas Christopher Wilson
438feabf50 build: support Node.js 15.x 2020-11-07 18:44:40 -05:00
Douglas Christopher Wilson
07e47df692 build: supertest@6.0.0 2020-11-01 21:22:22 -05:00
Douglas Christopher Wilson
81afa23b29 build: Node.js@14.15 2020-10-30 22:07:21 -04:00
Douglas Christopher Wilson
cad6e104ef build: eslint@7.12.1 2020-10-29 22:09:34 -04:00
Douglas Christopher Wilson
947fc1bbc8 build: mocha@8.2.0 2020-10-27 20:41:15 -04:00
Douglas Christopher Wilson
30ae682927 build: Node.js@14.14 2020-10-24 00:32:57 -04:00
Douglas Christopher Wilson
b9469ab500 build: Node.js@10.23 2020-10-24 00:29:06 -04:00
Douglas Christopher Wilson
2fb9ab3260 build: Node.js@12.19 2020-10-23 20:21:44 -04:00
Douglas Christopher Wilson
9f931d53f9 build: eslint@7.10.0 2020-10-05 00:51:51 -04:00
Douglas Christopher Wilson
3884c54c00 build: Node.js@14.13 2020-10-04 20:01:27 -04:00
Douglas Christopher Wilson
e161893d4a build: eslint@7.8.1 2020-09-10 00:13:18 -04:00
Douglas Christopher Wilson
006327c26a build: mocha@8.1.3 2020-09-10 00:10:02 -04:00
Douglas Christopher Wilson
ed99750527 build: Node.js@14.10 2020-09-09 23:08:59 -04:00
Douglas Christopher Wilson
5f5124a79a build: eslint@7.6.0 2020-08-05 22:40:12 -04:00
Douglas Christopher Wilson
b7186ae2db build: Node.js@14.7 2020-08-03 20:16:43 -04:00
Douglas Christopher Wilson
6ed2cab63e build: mocha@8.1.0 2020-08-03 20:11:18 -04:00
Douglas Christopher Wilson
7b37172d09 build: Node.js@10.22 2020-07-18 19:44:10 -04:00
Douglas Christopher Wilson
bfef3ecf2a deps: http-errors@~1.8.0 2020-07-17 00:07:45 -04:00
Douglas Christopher Wilson
4fbef9d380 build: eslint@7.4.0 2020-07-16 20:29:49 -04:00
Douglas Christopher Wilson
c32caf8a37 build: Node.js@14.5 2020-07-16 20:25:24 -04:00
Douglas Christopher Wilson
8e68e57125 build: mocha@8.0.1 2020-06-13 22:01:34 -04:00
Douglas Christopher Wilson
f3d18ab5ce build: Node.js@12.18 2020-06-11 23:07:26 -04:00
Douglas Christopher Wilson
b7b10be97d build: Node.js@10.21 2020-06-10 19:08:41 -04:00
Douglas Christopher Wilson
d416ee987e build: eslint@7.2.0 2020-06-06 17:48:33 -04:00
Douglas Christopher Wilson
f15cbc8386 build: Node.js@14.4 2020-06-06 17:44:03 -04:00
Douglas Christopher Wilson
5c959be72f build: Node.js@12.17 2020-05-30 21:34:02 -04:00
Douglas Christopher Wilson
a92a2a10d7 build: eslint@7.1.0 2020-05-25 22:19:22 -04:00
Douglas Christopher Wilson
a4fe4bcf96 build: mocha@7.2.0 2020-05-23 19:09:35 -04:00
Douglas Christopher Wilson
fe7aa00af8 build: Node.js@14.3 2020-05-23 19:04:19 -04:00
Douglas Christopher Wilson
7e737fb9f4 build: eslint@7.0.0 2020-05-17 23:08:37 -04:00
Douglas Christopher Wilson
ba0c70c6b5 build: Node.js@14.1 2020-05-01 21:52:54 -04:00
Douglas Christopher Wilson
ee51d44121 build: mocha@7.1.2 2020-04-30 20:28:53 -04:00
Douglas Christopher Wilson
313678fdc4 build: Node.js@13.14 2020-04-29 00:08:09 -04:00
Douglas Christopher Wilson
4921806568 build: support Node.js 14.x 2020-04-28 23:11:13 -04:00
Douglas Christopher Wilson
bc57152e09 deps: mime-types@~2.1.27 2020-04-28 23:08:00 -04:00
Douglas Christopher Wilson
27facca566 build: Node.js@10.20 2020-04-20 21:58:49 -04:00
Douglas Christopher Wilson
13f7bc57a2 build: Node.js@13.13 2020-04-15 16:09:24 -04:00
Douglas Christopher Wilson
c1db68ba39 build: mocha@7.1.1 2020-04-06 17:50:45 -04:00
Douglas Christopher Wilson
cb8b5c60f4 build: eslint-plugin-markdown@1.0.2 2020-03-14 17:44:20 -04:00
Douglas Christopher Wilson
51372447e0 build: Node.js@13.10 2020-03-11 20:41:28 -04:00
Douglas Christopher Wilson
39e8b5782b build: mocha@7.1.0 2020-03-09 23:04:24 -04:00
Douglas Christopher Wilson
fc7be1bfb5 build: Node.js@12.16 2020-02-14 22:59:12 -05:00
Douglas Christopher Wilson
38768868ea build: remove deprecated Travis CI directive 2020-02-14 22:58:50 -05:00
Douglas Christopher Wilson
cd937079b3 build: Node.js@13.8 2020-02-08 20:06:33 -05:00
Douglas Christopher Wilson
4f0326af87 build: Node.js@12.15 2020-02-07 22:42:08 -05:00
Douglas Christopher Wilson
d0e883a3df build: Node.js@10.19 2020-02-07 22:41:01 -05:00
Douglas Christopher Wilson
105ca237f6 build: Node.js@13.7 2020-02-05 19:52:35 -05:00
Douglas Christopher Wilson
4d34c9b736 build: mocha@7.0.1 2020-02-05 19:51:54 -05:00
Douglas Christopher Wilson
34fffcb92c build: Node.js@13.6 2020-01-12 01:28:42 -05:00
Douglas Christopher Wilson
86e87f8c5e deps: mime-types@~2.1.26 2020-01-12 01:21:44 -05:00
Douglas Christopher Wilson
b08cbbabd4 build: mocha@7.0.0 2020-01-11 21:42:39 -05:00
Douglas Christopher Wilson
34aa14a456 build: Node.js@13.5 2019-12-24 15:27:14 -05:00
Douglas Christopher Wilson
9b69727ad2 build: eslint@6.8.0 2019-12-24 15:20:44 -05:00
Douglas Christopher Wilson
82b74e75bf build: Node.js@12.14 2019-12-19 00:28:26 -05:00
Douglas Christopher Wilson
544b6e49a2 build: Node.js@10.18 2019-12-19 00:21:13 -05:00
Douglas Christopher Wilson
84660635a2 build: Node.js@8.17 2019-12-18 21:54:37 -05:00
Douglas Christopher Wilson
8336655fcb build: Node.js@13.3 2019-12-05 18:44:26 -05:00
Douglas Christopher Wilson
6044ccbd7d build: eslint@6.7.2 2019-12-03 19:38:41 -05:00
Douglas Christopher Wilson
2f549f0bab build: Node.js@13.2 2019-11-22 00:10:20 -05:00
Douglas Christopher Wilson
87aa9ef47c deps: mime-types@~2.1.25 2019-11-21 23:39:17 -05:00
Douglas Christopher Wilson
327056b44b build: eslint-plugin-markdown@1.0.1 2019-11-19 22:54:51 -05:00
Douglas Christopher Wilson
6e1bcada54 build: Node.js@13.1 2019-11-09 20:44:00 -05:00
Douglas Christopher Wilson
4c64e7b791 build: mocha@6.2.2 2019-11-06 17:05:11 -05:00
Douglas Christopher Wilson
823d804e58 build: support Node.js 13.x 2019-11-04 19:52:20 -05:00
Douglas Christopher Wilson
8e1d258ad1 build: Node.js@12.13 2019-11-02 00:50:02 -04:00
Douglas Christopher Wilson
c24512e404 build: Node.js@10.17 2019-11-02 00:43:03 -04:00
Douglas Christopher Wilson
a15e3fbb0c build: eslint@6.6.0 2019-11-01 23:51:01 -04:00
Douglas Christopher Wilson
58bfa078c7 build: fix eslint uninstall failures 2019-09-23 00:41:20 -04:00
Douglas Christopher Wilson
9f0a8519f5 build: supertest@4.0.2 2019-09-22 23:07:53 -04:00
Douglas Christopher Wilson
214eea3175 build: Node.js@12.10 2019-09-12 21:50:06 -04:00
Douglas Christopher Wilson
018fa454e0 build: eslint@6.3.0 2019-09-10 19:45:54 -04:00
Douglas Christopher Wilson
4d8b4917e7 build: mocha@6.2.0 2019-09-10 19:40:18 -04:00
Douglas Christopher Wilson
2b82ea68fc build: Node.js@12.8 2019-08-10 16:50:24 -04:00
Douglas Christopher Wilson
3ab32ac667 build: eslint@6.1.0 2019-08-10 16:47:59 -04:00
Douglas Christopher Wilson
71b655e777 build: mocha@5.2.0 2019-08-08 23:19:32 -04:00
Douglas Christopher Wilson
2802ec6f2f build: supertest@3.4.2 2019-08-06 01:22:44 -04:00
Douglas Christopher Wilson
54e0eb7115 build: Node.js@12.7 2019-08-05 19:38:35 -04:00
Douglas Christopher Wilson
fc6d3eadac build: mocha@4.1.0 2019-07-17 19:44:53 -04:00
Douglas Christopher Wilson
e3ff991be9 build: supertest@2.0.0 2019-07-15 22:09:35 -04:00
Douglas Christopher Wilson
8fbb732bde build: mocha@3.5.3 2019-07-14 23:07:26 -04:00
Douglas Christopher Wilson
00f3ef67a6 build: restructure CI build steps 2019-07-13 21:55:53 -04:00
Douglas Christopher Wilson
5271288d1a build: eslint@5.16.0 2019-07-10 17:49:45 -04:00
Douglas Christopher Wilson
bda73e36c2 build: eslint-plugin-markdown@1.0.0 2019-07-06 18:52:56 -04:00
Douglas Christopher Wilson
9c0287c406 deps: http-errors@~1.7.3 2019-07-05 00:44:00 -04:00
Douglas Christopher Wilson
136fe69c11 build: Node.js@10.16 2019-07-05 00:27:24 -04:00
Douglas Christopher Wilson
0dde93dc69 build: Node.js@12.6 2019-07-04 23:51:06 -04:00
Douglas Christopher Wilson
12a56a6f2e build: eslint@4.19.1 2019-07-04 19:43:32 -04:00
Douglas Christopher Wilson
9569cb6852 tests: move asserts so supertest can catch 2019-06-17 20:43:06 -04:00
Douglas Christopher Wilson
20e83c893b build: support Node.js 12.x 2019-05-02 23:37:45 -04:00
Douglas Christopher Wilson
4c8c716ded build: Node.js@11.15 2019-05-02 23:37:20 -04:00
Douglas Christopher Wilson
002a251122 Fix text and json responses to match html sorting 2019-05-02 23:35:13 -04:00
Douglas Christopher Wilson
5583f9ec06 build: Node.js@11.14 2019-04-29 23:55:03 -04:00
Douglas Christopher Wilson
4482ec9639 build: Node.js@8.16 2019-04-29 23:54:49 -04:00
Douglas Christopher Wilson
e7ae813459 build: eslint-plugin-markdown@1.0.0-beta.8 2019-04-29 23:54:04 -04:00
Douglas Christopher Wilson
fa3fe02a2f deps: accepts@~1.3.7 2019-04-29 23:52:19 -04:00
Douglas Christopher Wilson
a30f269f99 deps: parseurl@~1.3.3 2019-04-28 00:56:30 -04:00
Douglas Christopher Wilson
d8ff9b9e41 deps: mime-types@~2.1.24 2019-04-28 00:55:52 -04:00
Joonas Rouhiainen
d3ee7d8f55 Use 400 error on URI decode failure instead of 500
closes #85
closes #88
2019-04-27 23:18:36 -04:00
Douglas Christopher Wilson
32b7a1adec deps: http-errors@~1.7.2 2019-04-01 00:45:20 -04:00
Douglas Christopher Wilson
173f71a6a1 deps: mime-types@~2.1.22 2019-04-01 00:38:48 -04:00
Douglas Christopher Wilson
4382b8f625 build: Node.js@11.13 2019-03-31 23:02:00 -04:00
Douglas Christopher Wilson
6636afe7fd build: Node.js@6.17 2019-03-31 22:54:48 -04:00
Douglas Christopher Wilson
156303efe0 deps: http-errors@~1.7.1 2019-01-04 21:40:16 -05:00
Douglas Christopher Wilson
9c56901718 build: support Node.js 11.x 2019-01-03 17:02:48 -05:00
Douglas Christopher Wilson
935ee09c82 build: Node.js@10.15 2018-12-30 00:14:12 -05:00
Douglas Christopher Wilson
05b0e21848 build: Node.js@8.15 2018-12-30 00:09:51 -05:00
Douglas Christopher Wilson
fadb156765 build: Node.js@6.16 2018-12-30 00:02:39 -05:00
Douglas Christopher Wilson
abedc7fcfe deps: mime-types@~2.1.21 2018-12-25 23:50:40 -05:00
Douglas Christopher Wilson
92d67676ff build: support Node.js 10.x 2018-06-09 19:26:38 -04:00
Douglas Christopher Wilson
fcad6767c0 build: Node.js@9.11 2018-06-04 00:34:22 -04:00
Douglas Christopher Wilson
9bf00b76ad deps: http-errors@~1.6.3 2018-06-04 00:21:18 -04:00
Douglas Christopher Wilson
98107736e0 deps: accepts@~1.3.5 2018-06-03 23:39:21 -04:00
Douglas Christopher Wilson
77919cf57b build: Node.js@8.11 2018-05-29 12:07:12 -04:00
Douglas Christopher Wilson
010b8c9124 build: Node.js@6.14 2018-05-26 00:08:11 -04:00
Douglas Christopher Wilson
b215084582 build: Node.js@4.9 2018-05-26 00:03:32 -04:00
Douglas Christopher Wilson
451dc90796 build: fix Node.js 0.8 appveyor build 2018-05-25 23:49:02 -04:00
Douglas Christopher Wilson
9d29665ce3 Show font icon for more font types 2018-02-21 23:24:56 -05:00
Douglas Christopher Wilson
f31db046f6 deps: mime-types@~2.1.18 2018-02-21 23:01:11 -05:00
Douglas Christopher Wilson
c67b828cbc lint: remove usages of "==" 2017-11-23 00:08:40 -05:00
Douglas Christopher Wilson
7fc9fe1f7b build: support Node.js 9.x 2017-11-23 00:02:38 -05:00
Douglas Christopher Wilson
cec35eed49 build: Node.js@8.9 2017-11-22 23:59:29 -05:00
Douglas Christopher Wilson
561f159d00 build: Node.js@6.12 2017-11-22 23:58:48 -05:00
Douglas Christopher Wilson
d66e8036f7 lint: add editorconfig and eslint to enforce 2017-11-22 23:54:40 -05:00
Douglas Christopher Wilson
b0f8f33d4a docs: remove gratipay badge 2017-11-22 23:30:04 -05:00
Douglas Christopher Wilson
a399faa180 1.9.1 2017-09-29 00:23:59 -04:00
Douglas Christopher Wilson
fc6953383f deps: parseurl@~1.3.2 2017-09-29 00:22:44 -04:00
Douglas Christopher Wilson
45dbe4f219 docs: add express.static to the express example
closes #64
2017-09-29 00:20:54 -04:00
Daniel Tschinder
76e3c3af41 deps: debug@2.6.9
closes #65
2017-09-28 23:27:29 -04:00
Douglas Christopher Wilson
da37631e2c build: Node.js@8.3 2017-09-02 20:01:11 -04:00
Douglas Christopher Wilson
3e09fb26f9 build: Node.js@6.11 2017-09-02 19:58:07 -04:00
Douglas Christopher Wilson
0894f8c9ff deps: mime-types@~2.1.17 2017-09-02 19:54:30 -04:00
Douglas Christopher Wilson
a4f1ef3d5e deps: http-errors@~1.6.2 2017-09-02 19:48:04 -04:00
Douglas Christopher Wilson
ccbeaebe69 deps: accepts@~1.3.4 2017-09-02 19:45:33 -04:00
16 changed files with 973 additions and 353 deletions

11
.editorconfig Normal file
View File

@@ -0,0 +1,11 @@
# http://editorconfig.org
root = true
[*]
charset = utf-8
insert_final_newline = true
trim_trailing_whitespace = true
[{*.js,*.json,*.yml}]
indent_size = 2
indent_style = space

3
.eslintignore Normal file
View File

@@ -0,0 +1,3 @@
.nyc_output
coverage
node_modules

13
.eslintrc.yml Normal file
View File

@@ -0,0 +1,13 @@
root: true
extends:
- plugin:markdown/recommended
plugins:
- markdown
overrides:
- files: '**/*.md'
processor: 'markdown/markdown'
rules:
eol-last: error
eqeqeq: [error, allow-null]
indent: [error, 2, { SwitchCase: 1 }]
no-trailing-spaces: error

15
.github/dependabot.yml vendored Normal file
View File

@@ -0,0 +1,15 @@
version: 2
updates:
- package-ecosystem: github-actions
directory: /
schedule:
interval: monthly
- package-ecosystem: npm
directory: /
schedule:
interval: monthly
open-pull-requests-limit: 10
ignore:
- dependency-name: "*"
update-types: ["version-update:semver-major"]

241
.github/workflows/ci.yml vendored Normal file
View File

@@ -0,0 +1,241 @@
name: ci
on:
- pull_request
- push
permissions:
contents: read
jobs:
test:
permissions:
checks: write # for coverallsapp/github-action to create new checks
contents: read # for actions/checkout to fetch code
runs-on: ubuntu-latest
strategy:
matrix:
name:
- Node.js 0.8
- Node.js 0.10
- Node.js 0.12
- io.js 1.x
- io.js 2.x
- io.js 3.x
- Node.js 4.x
- Node.js 5.x
- Node.js 6.x
- Node.js 7.x
- Node.js 8.x
- Node.js 9.x
- Node.js 10.x
- Node.js 11.x
- Node.js 12.x
- Node.js 13.x
- Node.js 14.x
- Node.js 15.x
- Node.js 16.x
- Node.js 17.x
- Node.js 18.x
- Node.js 19.x
- Node.js 20.x
- Node.js 21.x
- Node.js 22.x
- Node.js 23.x
- Node.js 24.x
include:
- name: Node.js 0.8
node-version: "0.8"
npm-i: mocha@2.5.3 supertest@1.1.0
npm-rm: nyc
- name: Node.js 0.10
node-version: "0.10"
npm-i: mocha@3.5.3 nyc@10.3.2 supertest@2.0.1
- name: Node.js 0.12
node-version: "0.12"
npm-i: mocha@3.5.3 nyc@10.3.2 supertest@2.0.1
- name: io.js 1.x
node-version: "1"
npm-i: mocha@3.5.3 nyc@10.3.2 supertest@2.0.1
- name: io.js 2.x
node-version: "2"
npm-i: mocha@3.5.3 nyc@10.3.2 supertest@2.0.1
- name: io.js 3.x
node-version: "3"
npm-i: mocha@3.5.3 nyc@10.3.2 supertest@2.0.1
- name: Node.js 4.x
node-version: "4"
npm-i: mocha@5.2.0 nyc@11.9.0 supertest@3.4.2
- name: Node.js 5.x
node-version: "5"
npm-i: mocha@5.2.0 nyc@11.9.0 supertest@3.4.2
- name: Node.js 6.x
node-version: "6"
npm-i: mocha@6.2.2 nyc@14.1.1 supertest@6.1.3
- name: Node.js 7.x
node-version: "7"
npm-i: mocha@6.2.2 nyc@14.1.1 supertest@6.1.3
- name: Node.js 8.x
node-version: "8"
npm-i: mocha@7.1.2 nyc@14.1.1 supertest@6.1.3
- name: Node.js 9.x
node-version: "9"
npm-i: mocha@7.1.2 nyc@14.1.1 supertest@6.1.3
- name: Node.js 10.x
node-version: "10"
npm-i: mocha@8.4.0 supertest@6.1.3
- name: Node.js 11.x
node-version: "11"
npm-i: mocha@8.4.0 supertest@6.1.3
- name: Node.js 12.x
node-version: "12"
npm-i: mocha@9.2.2 supertest@6.1.3
- name: Node.js 13.x
node-version: "13"
npm-i: mocha@9.2.2 supertest@6.1.3
- name: Node.js 14.x
node-version: "14"
npm-i: supertest@6.1.3
- name: Node.js 15.x
node-version: "15"
npm-i: supertest@6.1.3
- name: Node.js 16.x
node-version: "16"
npm-i: supertest@6.1.3
- name: Node.js 17.x
node-version: "17"
npm-i: supertest@6.1.3
- name: Node.js 18.x
node-version: "18"
- name: Node.js 19.x
node-version: "19"
- name: Node.js 20.x
node-version: "20"
- name: Node.js 21.x
node-version: "21"
- name: Node.js 22.x
node-version: "22"
- name: Node.js 23.x
node-version: "23"
- name: Node.js 24.x
node-version: "24"
steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- name: Install Node.js ${{ matrix.node-version }}
shell: bash -eo pipefail -l {0}
run: |
nvm install --default ${{ matrix.node-version }}
if [[ "${{ matrix.node-version }}" == 0.* && "$(cut -d. -f2 <<< "${{ matrix.node-version }}")" -lt 10 ]]; then
nvm install --alias=npm 0.10
nvm use ${{ matrix.node-version }}
if [[ "$(npm -v)" == 1.1.* ]]; then
nvm exec npm npm install -g npm@1.1
ln -fs "$(which npm)" "$(dirname "$(nvm which npm)")/npm"
else
sed -i '1s;^.*$;'"$(printf '#!%q' "$(nvm which npm)")"';' "$(readlink -f "$(which npm)")"
fi
npm config set strict-ssl false
fi
dirname "$(nvm which ${{ matrix.node-version }})" >> "$GITHUB_PATH"
- name: Configure npm
run: |
if [[ "$(npm config get package-lock)" == "true" ]]; then
npm config set package-lock false
else
npm config set shrinkwrap false
fi
- name: Remove npm module(s) ${{ matrix.npm-rm }}
if: matrix.npm-rm != ''
run: npm rm --silent --save-dev ${{ matrix.npm-rm }}
- name: Install npm module(s) ${{ matrix.npm-i }}
if: matrix.npm-i != ''
run: npm install --save-dev ${{ matrix.npm-i }}
- name: Setup Node.js version-specific dependencies
shell: bash
run: |
# eslint for linting
# - remove on Node.js < 12
if [[ "$(cut -d. -f1 <<< "${{ matrix.node-version }}")" -lt 12 ]]; then
node -pe 'Object.keys(require("./package").devDependencies).join("\n")' | \
grep -E '^eslint(-|$)' | \
sort -r | \
xargs -n1 npm rm --silent --save-dev
fi
- name: Install Node.js dependencies
run: npm install
- name: List environment
id: list_env
shell: bash
run: |
echo "node@$(node -v)"
echo "npm@$(npm -v)"
npm -s ls ||:
(npm -s ls --depth=0 ||:) | awk -F'[ @]' 'NR>1 && $2 { print $2 "=" $3 }' >> "$GITHUB_OUTPUT"
- name: Run tests
shell: bash
run: |
if npm -ps ls nyc | grep -q nyc; then
npm run test-ci
else
npm test
fi
- name: Lint code
if: steps.list_env.outputs.eslint != ''
run: npm run lint
- name: Collect code coverage
uses: coverallsapp/github-action@648a8eb78e6d50909eff900e4ec85cab4524a45b # master
if: steps.list_env.outputs.nyc != ''
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
flag-name: run-${{ matrix.test_number }}
parallel: true
coverage:
permissions:
checks: write # for coverallsapp/github-action to create new checks
needs: test
runs-on: ubuntu-latest
steps:
- name: Upload code coverage
uses: coverallsapp/github-action@648a8eb78e6d50909eff900e4ec85cab4524a45b # master
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
parallel-finished: true

78
.github/workflows/codeql.yml vendored Normal file
View File

@@ -0,0 +1,78 @@
# For most projects, this workflow file will not need changing; you simply need
# to commit it to your repository.
#
# You may wish to alter this file to override the set of languages analyzed,
# or to provide custom queries or build logic.
#
# ******** NOTE ********
# We have attempted to detect the languages in your repository. Please check
# the `language` matrix defined below to confirm you have the correct set of
# supported CodeQL languages.
#
name: "CodeQL"
on:
push:
branches: ["master"]
pull_request:
# The branches below must be a subset of the branches above
branches: ["master"]
schedule:
- cron: "0 0 * * 1"
permissions:
contents: read
jobs:
analyze:
name: Analyze
runs-on: ubuntu-latest
permissions:
actions: read
contents: read
security-events: write
strategy:
fail-fast: false
matrix:
language: ["javascript"]
# CodeQL supports [ $supported-codeql-languages ]
# Learn more about CodeQL language support at https://aka.ms/codeql-docs/language-support
steps:
- name: Harden the runner (Audit all outbound calls)
uses: step-security/harden-runner@ec9f2d5744a09debf3a187a3f4f675c53b671911 # v2.13.0
with:
egress-policy: audit
- name: Checkout repository
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@0499de31b99561a6d14a36a5f662c2a54f91beee # v3.29.5
with:
languages: ${{ matrix.language }}
# If you wish to specify custom queries, you can do so here or in a config file.
# By default, queries listed here will override any specified in a config file.
# Prefix the list here with "+" to use these queries and those in the config file.
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
# If this step fails, then you should remove it and run the build manually (see below)
- name: Autobuild
uses: github/codeql-action/autobuild@0499de31b99561a6d14a36a5f662c2a54f91beee # v3.29.5
# Command-line programs to run using the OS shell.
# 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun
# If the Autobuild fails above, remove it and uncomment the following three lines.
# modify them (or add more) to build your code if your project, please refer to the EXAMPLE below for guidance.
# - run: |
# echo "Run, Build Application using script"
# ./location_of_script_within_repo/buildscript.sh
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@0499de31b99561a6d14a36a5f662c2a54f91beee # v3.29.5
with:
category: "/language:${{matrix.language}}"

73
.github/workflows/scorecard.yml vendored Normal file
View File

@@ -0,0 +1,73 @@
# This workflow uses actions that are not certified by GitHub. They are provided
# by a third-party and are governed by separate terms of service, privacy
# policy, and support documentation.
name: Scorecard supply-chain security
on:
# For Branch-Protection check. Only the default branch is supported. See
# https://github.com/ossf/scorecard/blob/main/docs/checks.md#branch-protection
branch_protection_rule:
# To guarantee Maintained check is occasionally updated. See
# https://github.com/ossf/scorecard/blob/main/docs/checks.md#maintained
schedule:
- cron: '16 21 * * 1'
push:
branches: [ "master" ]
# Declare default permissions as read only.
permissions: read-all
jobs:
analysis:
name: Scorecard analysis
runs-on: ubuntu-latest
permissions:
# Needed to upload the results to code-scanning dashboard.
security-events: write
# Needed to publish results and get a badge (see publish_results below).
id-token: write
# Uncomment the permissions below if installing in a private repository.
# contents: read
# actions: read
steps:
- name: "Checkout code"
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
persist-credentials: false
- name: "Run analysis"
uses: ossf/scorecard-action@05b42c624433fc40578a4040d5cf5e36ddca8cde # v2.4.2
with:
results_file: results.sarif
results_format: sarif
# (Optional) "write" PAT token. Uncomment the `repo_token` line below if:
# - you want to enable the Branch-Protection check on a *public* repository, or
# - you are installing Scorecard on a *private* repository
# To create the PAT, follow the steps in https://github.com/ossf/scorecard-action#authentication-with-pat.
# repo_token: ${{ secrets.SCORECARD_TOKEN }}
# Public repositories:
# - Publish results to OpenSSF REST API for easy access by consumers
# - Allows the repository to include the Scorecard badge.
# - See https://github.com/ossf/scorecard-action#publishing-results.
# For private repositories:
# - `publish_results` will always be set to `false`, regardless
# of the value entered here.
publish_results: true
# Upload the results as artifacts (optional). Commenting out will disable uploads of run results in SARIF
# format to the repository Actions tab.
- name: "Upload artifact"
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
with:
name: SARIF file
path: results.sarif
retention-days: 5
# Upload the results to GitHub's code scanning dashboard.
- name: "Upload to code-scanning"
uses: github/codeql-action/upload-sarif@0499de31b99561a6d14a36a5f662c2a54f91beee # v3.29.5
with:
sarif_file: results.sarif

2
.gitignore vendored
View File

@@ -1,3 +1,5 @@
.nyc_output/
coverage
node_modules
npm-debug.log
package-lock.json

View File

@@ -1,29 +0,0 @@
language: node_js
node_js:
- "0.8"
- "0.10"
- "0.12"
- "1.8"
- "2.5"
- "3.3"
- "4.8"
- "5.12"
- "6.10"
- "7.10"
sudo: false
cache:
directories:
- node_modules
before_install:
# Setup Node.js version-specific dependencies
- "test $TRAVIS_NODE_VERSION != '0.8' || npm rm --save-dev istanbul"
# Update Node.js modules
- "test ! -d node_modules || npm prune"
- "test ! -d node_modules || npm rebuild"
script:
# Run test script, depending on istanbul install
- "test ! -z $(npm -ps ls istanbul) || npm test"
- "test -z $(npm -ps ls istanbul) || npm run-script test-ci"
after_script:
- "test -e ./coverage/lcov.info && npm install coveralls@2 && cat ./coverage/lcov.info | coveralls"

View File

@@ -1,3 +1,39 @@
unreleased
==========
* Fix icons for MIME types with `+`
* Fix text and json responses to match html sorting
* Show font icon for more font types
* Use 400 error on URI decode failure instead of 500
* deps: accepts@~1.3.7
- deps: mime-types@~2.1.24
- deps: negotiator@0.6.2
* deps: http-errors@~1.8.0
- Set constructor name when possible
- deps: depd@~1.1.2
- deps: inherits@2.0.4
- deps: setprototypeof@1.2.0
- deps: statuses@'>= 1.5.0 < 2'
* deps: mime-types@~2.1.30
- Add new mime types
- deps: mime-db@~1.47.0
* deps: parseurl@~1.3.3
1.9.1 / 2017-09-28
==================
* deps: accepts@~1.3.4
- deps: mime-types@~2.1.16
* deps: debug@2.6.9
* deps: http-errors@~1.6.2
- deps: depd@1.1.1
* deps: mime-types@~2.1.17
- Add new mime types
- deps: mime-db@~1.30.0
* deps: parseurl@~1.3.2
- perf: reduce overhead for full URLs
- perf: unroll the "fast-path" `RegExp`
1.9.0 / 2017-05-25
==================

View File

@@ -2,10 +2,9 @@
[![NPM Version][npm-image]][npm-url]
[![NPM Downloads][downloads-image]][downloads-url]
[![Linux Build][travis-image]][travis-url]
[![Linux Build Status][ci-image]][ci-url]
[![Windows Build][appveyor-image]][appveyor-url]
[![Test Coverage][coveralls-image]][coveralls-url]
[![Gratipay][gratipay-image]][gratipay-url]
[![Coverage Status][coveralls-image]][coveralls-url]
Serves pages that contain directory listings for a given path.
@@ -127,8 +126,12 @@ var serveIndex = require('serve-index')
var app = express()
// Serve URLs like /ftp/thing as public/ftp/thing
app.use('/ftp', serveIndex('public/ftp', {'icons': true}))
app.listen()
// The express.static serves the file contents
// The serveIndex is this module serving the directory
app.use('/ftp', express.static('public/ftp'), serveIndex('public/ftp', {'icons': true}))
// Listen
app.listen(3000)
```
## License
@@ -136,15 +139,13 @@ app.listen()
[MIT](LICENSE). The [Silk](http://www.famfamfam.com/lab/icons/silk/) icons
are created by/copyright of [FAMFAMFAM](http://www.famfamfam.com/).
[npm-image]: https://img.shields.io/npm/v/serve-index.svg
[npm-url]: https://npmjs.org/package/serve-index
[travis-image]: https://img.shields.io/travis/expressjs/serve-index/master.svg?label=linux
[travis-url]: https://travis-ci.org/expressjs/serve-index
[appveyor-image]: https://img.shields.io/appveyor/ci/dougwilson/serve-index/master.svg?label=windows
[appveyor-url]: https://ci.appveyor.com/project/dougwilson/serve-index
[ci-image]: https://badgen.net/github/checks/expressjs/serve-index/master?label=ci
[ci-url]: https://github.com/expressjs/serve-index/actions/workflows/ci.yml
[coveralls-image]: https://img.shields.io/coveralls/expressjs/serve-index/master.svg
[coveralls-url]: https://coveralls.io/r/expressjs/serve-index?branch=master
[downloads-image]: https://img.shields.io/npm/dm/serve-index.svg
[downloads-url]: https://npmjs.org/package/serve-index
[gratipay-image]: https://img.shields.io/gratipay/dougwilson.svg
[gratipay-url]: https://www.gratipay.com/dougwilson/
[npm-image]: https://img.shields.io/npm/v/serve-index.svg
[npm-url]: https://npmjs.org/package/serve-index

View File

@@ -6,23 +6,87 @@ environment:
- nodejs_version: "1.8"
- nodejs_version: "2.5"
- nodejs_version: "3.3"
- nodejs_version: "4.8"
- nodejs_version: "4.9"
- nodejs_version: "5.12"
- nodejs_version: "6.10"
- nodejs_version: "6.17"
- nodejs_version: "7.10"
- nodejs_version: "8.17"
- nodejs_version: "9.11"
- nodejs_version: "10.24"
- nodejs_version: "11.15"
- nodejs_version: "12.22"
- nodejs_version: "13.14"
- nodejs_version: "14.16"
- nodejs_version: "15.13"
cache:
- node_modules
install:
- ps: Install-Product node $env:nodejs_version
- if "%nodejs_version%" equ "0.8" npm rm --save-dev istanbul
- if exist node_modules npm prune
- if exist node_modules npm rebuild
# Install Node.js
- ps: >-
try { Install-Product node $env:nodejs_version -ErrorAction Stop }
catch { Update-NodeJsInstallation (Get-NodeJsLatestBuild $env:nodejs_version) }
# Configure npm
- ps: |
# Skip updating shrinkwrap / lock
npm config set shrinkwrap false
# Skip SSL validation on Node.js < 0.10
if ([int]$env:nodejs_version.split(".")[0] -eq 0 -and [int]$env:nodejs_version.split(".")[1] -lt 10) {
npm config set strict-ssl false
}
# Remove all non-test dependencies
- ps: |
# Remove coverage dependency
npm rm --silent --save-dev nyc
# Remove lint dependencies
cmd.exe /c "node -pe `"Object.keys(require('./package').devDependencies).join('\n')`"" | `
sls "^eslint(-|$)" | `
%{ npm rm --silent --save-dev $_ }
# Setup Node.js version-specific dependencies
- ps: |
# mocha for testing
# - use 2.x for Node.js < 0.10
# - use 3.x for Node.js < 4
# - use 5.x for Node.js < 6
# - use 6.x for Node.js < 8
# - use 7.x for Node.js < 10
if ([int]$env:nodejs_version.split(".")[0] -eq 0 -and [int]$env:nodejs_version.split(".")[1] -lt 10) {
npm install --silent --save-dev mocha@2.5.3
} elseif ([int]$env:nodejs_version.split(".")[0] -lt 4) {
npm install --silent --save-dev mocha@3.5.3
} elseif ([int]$env:nodejs_version.split(".")[0] -lt 6) {
npm install --silent --save-dev mocha@5.2.0
} elseif ([int]$env:nodejs_version.split(".")[0] -lt 8) {
npm install --silent --save-dev mocha@6.2.2
} elseif ([int]$env:nodejs_version.split(".")[0] -lt 10) {
npm install --silent --save-dev mocha@7.2.0
}
- ps: |
# mocha for testing
# - use 1.1.0 for Node.js < 0.10
# - use 2.0.0 for Node.js < 4
# - use 3.4.2 for Node.js < 6
if ([int]$env:nodejs_version.split(".")[0] -eq 0 -and [int]$env:nodejs_version.split(".")[1] -lt 10) {
npm install --silent --save-dev supertest@1.1.0
} elseif ([int]$env:nodejs_version.split(".")[0] -lt 4) {
npm install --silent --save-dev supertest@2.0.0
} elseif ([int]$env:nodejs_version.split(".")[0] -lt 6) {
npm install --silent --save-dev supertest@3.4.2
}
# Update Node.js modules
- ps: |
# Prune & rebuild node_modules
if (Test-Path -Path node_modules) {
npm prune
npm rebuild
}
# Install Node.js modules
- npm install
build: off
test_script:
- node --version
- npm --version
- set npm_test_command=test
- for /f %%l in ('npm -ps ls istanbul') do set npm_test_command=test-ci
- npm run %npm_test_command%
# Output version data
- ps: |
node --version
npm --version
# Run test script
- npm test
version: "{build}"

View File

@@ -107,10 +107,14 @@ function serveIndex(root, options) {
return;
}
// get dir
var dir = getRequestedDir(req)
// bad request
if (dir === null) return next(createError(400))
// parse URLs
var url = parseUrl(req);
var originalUrl = parseUrl.original(req);
var dir = decodeURIComponent(url.pathname);
var originalDir = decodeURIComponent(originalUrl.pathname);
// join / normalize from root dir
@@ -180,14 +184,9 @@ serveIndex.html = function _html(req, res, files, next, dir, showUp, icons, path
}
// stat all files
stat(path, files, function (err, stats) {
stat(path, files, function (err, fileList) {
if (err) return next(err);
// combine the stats into the file list
var fileList = files.map(function (file, i) {
return { name: file, stat: stats[i] };
});
// sort file list
fileList.sort(fileSort);
@@ -218,16 +217,42 @@ serveIndex.html = function _html(req, res, files, next, dir, showUp, icons, path
* Respond with application/json.
*/
serveIndex.json = function _json(req, res, files) {
send(res, 'application/json', JSON.stringify(files))
serveIndex.json = function _json (req, res, files, next, dir, showUp, icons, path) {
// stat all files
stat(path, files, function (err, fileList) {
if (err) return next(err)
// sort file list
fileList.sort(fileSort)
// serialize
var body = JSON.stringify(fileList.map(function (file) {
return file.name
}))
send(res, 'application/json', body)
})
};
/**
* Respond with text/plain.
*/
serveIndex.plain = function _plain(req, res, files) {
send(res, 'text/plain', (files.join('\n') + '\n'))
serveIndex.plain = function _plain (req, res, files, next, dir, showUp, icons, path) {
// stat all files
stat(path, files, function (err, fileList) {
if (err) return next(err)
// sort file list
fileList.sort(fileSort)
// serialize
var body = fileList.map(function (file) {
return file.name
}).join('\n') + '\n'
send(res, 'text/plain', body)
})
};
/**
@@ -237,7 +262,7 @@ serveIndex.plain = function _plain(req, res, files) {
function createHtmlFileList(files, dir, useIcons, view) {
var html = '<ul id="files" class="view-' + escapeHtml(view) + '">'
+ (view == 'details' ? (
+ (view === 'details' ? (
'<li class="header">'
+ '<span class="name">Name</span>'
+ '<span class="size">Size</span>'
@@ -327,6 +352,22 @@ function fileSort(a, b) {
String(a.name).toLocaleLowerCase().localeCompare(String(b.name).toLocaleLowerCase());
}
/**
* Get the requested directory from request.
*
* @param req
* @return {string}
* @api private
*/
function getRequestedDir (req) {
try {
return decodeURIComponent(parseUrl(req).pathname)
} catch (e) {
return null
}
}
/**
* Map html `dir`, returning a linked path.
*/
@@ -375,7 +416,7 @@ function iconLookup(filename) {
// try by mime type
if (icons[mimetype]) {
return {
className: 'icon-' + mimetype.replace('/', '-'),
className: 'icon-' + mimetype.replace('/', '-').replace('+', '_'),
fileName: icons[mimetype]
};
}
@@ -485,7 +526,7 @@ function normalizeSlashes(path) {
function removeHidden(files) {
return files.filter(function(file){
return '.' != file[0];
return file[0] !== '.'
});
}
@@ -507,8 +548,12 @@ function send (res, type, body) {
}
/**
* Stat all files and return array of stat
* in same order.
* Stat all files and return array of objects in the form
* `{ name, stat }`.
*
* @param {Array} files
* @return {Array}
* @api private
*/
function stat(dir, files, cb) {
@@ -522,7 +567,10 @@ function stat(dir, files, cb) {
if (err && err.code !== 'ENOENT') return done(err);
// pass ENOENT as null stat, not error
done(null, stat || null);
done(null, {
name: file,
stat: stat || null
})
});
});
});
@@ -540,6 +588,7 @@ var icons = {
'folder': 'folder.png',
// generic mime type icons
'font': 'font.png',
'image': 'image.png',
'text': 'page_white_text.png',
'video': 'film.png',
@@ -550,7 +599,6 @@ var icons = {
'+zip': 'box.png',
// specific mime type icons
'application/font-woff': 'font.png',
'application/javascript': 'page_white_code_red.png',
'application/json': 'page_white_code.png',
'application/msword': 'page_white_word.png',
@@ -564,7 +612,6 @@ var icons = {
'application/vnd.oasis.opendocument.text': 'page_white_word.png',
'application/x-7z-compressed': 'box.png',
'application/x-sh': 'application_xp_terminal.png',
'application/x-font-ttf': 'font.png',
'application/x-msaccess': 'page_white_database.png',
'application/x-shockwave-flash': 'page_white_flash.png',
'application/x-sql': 'page_white_database.png',
@@ -618,7 +665,6 @@ var icons = {
'.map': 'map.png',
'.msi': 'box.png',
'.mv4': 'film.png',
'.otf': 'font.png',
'.pdb': 'page_white_database.png',
'.php': 'page_white_php.png',
'.pl': 'page_white_code.png',

View File

@@ -1,24 +1,30 @@
{
"name": "serve-index",
"description": "Serve directory listings",
"version": "1.9.0",
"version": "1.9.1",
"author": "Douglas Christopher Wilson <doug@somethingdoug.com>",
"license": "MIT",
"repository": "expressjs/serve-index",
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/express"
},
"dependencies": {
"accepts": "~1.3.3",
"accepts": "~1.3.7",
"batch": "0.6.1",
"debug": "2.6.8",
"debug": "2.6.9",
"escape-html": "~1.0.3",
"http-errors": "~1.6.1",
"mime-types": "~2.1.15",
"parseurl": "~1.3.1"
"http-errors": "~1.8.0",
"mime-types": "~2.1.29",
"parseurl": "~1.3.3"
},
"devDependencies": {
"after": "0.8.2",
"istanbul": "0.4.5",
"mocha": "2.5.3",
"supertest": "1.1.0"
"eslint": "7.23.0",
"eslint-plugin-markdown": "2.0.0",
"mocha": "10.4.0",
"nyc": "15.1.0",
"supertest": "7.0.0"
},
"files": [
"public/",
@@ -30,8 +36,9 @@
"node": ">= 0.8.0"
},
"scripts": {
"lint": "eslint .",
"test": "mocha --reporter spec --bail --check-leaks test/",
"test-ci": "istanbul cover node_modules/mocha/bin/_mocha --report lcovonly -- --reporter spec --check-leaks test/",
"test-cov": "istanbul cover node_modules/mocha/bin/_mocha -- --reporter dot --check-leaks test/"
"test-ci": "nyc --reporter=lcov --reporter=text npm test",
"test-cov": "nyc --reporter=html --reporter=text npm test"
}
}

0
test/fixtures/collect/sample.svg vendored Normal file
View File

View File

@@ -21,92 +21,102 @@ describe('serveIndex(root)', function () {
var server = createServer()
request(server)
.get('/')
.expect('Content-Type', 'text/html; charset=utf-8')
.expect(200, done)
.get('/')
.expect('Content-Type', 'text/html; charset=utf-8')
.expect(200, done)
})
it('should include security header', function (done) {
var server = createServer()
request(server)
.get('/')
.expect('X-Content-Type-Options', 'nosniff')
.expect(200, done)
.get('/')
.expect('X-Content-Type-Options', 'nosniff')
.expect(200, done)
})
it('should serve a directory index', function (done) {
var server = createServer()
request(server)
.get('/')
.expect(200, /todo\.txt/, done)
.get('/')
.expect(200, /todo\.txt/, done)
})
it('should work with HEAD requests', function (done) {
var server = createServer()
request(server)
.head('/')
.expect(200, '', done)
.head('/')
.expect(200)
.expect(shouldNotHaveBody())
.end(done)
})
it('should work with OPTIONS requests', function (done) {
var server = createServer()
request(server)
.options('/')
.expect('Allow', 'GET, HEAD, OPTIONS')
.expect(200, done)
.options('/')
.expect('Allow', 'GET, HEAD, OPTIONS')
.expect(200, done)
})
it('should deny POST requests', function (done) {
var server = createServer()
request(server)
.post('/')
.expect(405, done)
.post('/')
.expect(405, done)
})
it('should deny path will NULL byte', function (done) {
var server = createServer()
request(server)
.get('/%00')
.expect(400, done)
.get('/%00')
.expect(400, done)
})
it('should deny path that does not decode', function (done) {
var server = createServer()
request(server)
.head('/%FF')
.expect(400, done)
})
it('should deny path outside root', function (done) {
var server = createServer()
request(server)
.get('/../')
.expect(403, done)
.get('/../')
.expect(403, done)
})
it('should skip non-existent paths', function (done) {
var server = createServer()
request(server)
.get('/bogus')
.expect(404, 'Not Found', done)
.get('/bogus')
.expect(404, 'Not Found', done)
})
it('should treat an ENAMETOOLONG as a 414', function (done) {
var path = Array(11000).join('foobar')
var server = createServer()
var dir = path.join(fixtures, Array(10000).join('/foobar'))
var server = createServer(dir)
request(server)
.get('/' + path)
.expect(414, done)
.get('/')
.expect(414, done)
})
it('should skip non-directories', function (done) {
var server = createServer()
request(server)
.get('/nums')
.expect(404, 'Not Found', done)
.get('/nums')
.expect(404, 'Not Found', done)
})
describe('when given Accept: header', function () {
@@ -115,26 +125,46 @@ describe('serveIndex(root)', function () {
var server = createServer()
request(server)
.get('/')
.set('Accept', 'application/json')
.expect('Content-Type', /json/)
.expect(/g# %3 o & %2525 %37 dir/)
.expect(/users/)
.expect(/file #1\.txt/)
.expect(/nums/)
.expect(/todo\.txt/)
.expect(/さくら\.txt/)
.expect(200, done)
.get('/')
.set('Accept', 'application/json')
.expect('Content-Type', /json/)
.expect(/g# %3 o & %2525 %37 dir/)
.expect(/users/)
.expect(/file #1\.txt/)
.expect(/nums/)
.expect(/todo\.txt/)
.expect(/さくら\.txt/)
.expect(200, done)
});
it('should include security header', function (done) {
var server = createServer()
request(server)
.get('/')
.set('Accept', 'application/json')
.expect('X-Content-Type-Options', 'nosniff')
.expect(200, done)
.get('/')
.set('Accept', 'application/json')
.expect('X-Content-Type-Options', 'nosniff')
.expect(200, done)
})
it('should sort folders first', function (done) {
request(createServer())
.get('/')
.set('Accept', 'application/json')
.expect(200)
.expect('Content-Type', 'application/json; charset=utf-8')
.expect([
'#directory',
'collect',
'g# %3 o & %2525 %37 dir',
'users',
'file #1.txt',
'foo & bar',
'nums',
'todo.txt',
'さくら.txt'
])
.end(done)
})
});
@@ -143,67 +173,67 @@ describe('serveIndex(root)', function () {
var server = createServer()
request(server)
.get('/')
.set('Accept', 'text/html')
.expect(200)
.expect('Content-Type', 'text/html; charset=utf-8')
.expect(/<a href="\/g%23%20%253%20o%20%26%20%252525%20%2537%20dir"/)
.expect(/<a href="\/users"/)
.expect(/<a href="\/file%20%231.txt"/)
.expect(/<a href="\/todo.txt"/)
.expect(/<a href="\/%E3%81%95%E3%81%8F%E3%82%89\.txt"/)
.end(done);
.get('/')
.set('Accept', 'text/html')
.expect(200)
.expect('Content-Type', 'text/html; charset=utf-8')
.expect(/<a href="\/g%23%20%253%20o%20%26%20%252525%20%2537%20dir"/)
.expect(/<a href="\/users"/)
.expect(/<a href="\/file%20%231.txt"/)
.expect(/<a href="\/todo.txt"/)
.expect(/<a href="\/%E3%81%95%E3%81%8F%E3%82%89\.txt"/)
.end(done)
});
it('should include security header', function (done) {
var server = createServer()
request(server)
.get('/')
.set('Accept', 'text/html')
.expect('X-Content-Type-Options', 'nosniff')
.expect(200, done)
.get('/')
.set('Accept', 'text/html')
.expect('X-Content-Type-Options', 'nosniff')
.expect(200, done)
})
it('should property escape file names', function (done) {
var server = createServer()
request(server)
.get('/')
.set('Accept', 'text/html')
.expect(200)
.expect('Content-Type', 'text/html; charset=utf-8')
.expect(/<a href="\/foo%20%26%20bar"/)
.expect(/foo &amp; bar/)
.expect(bodyDoesNotContain('foo & bar'))
.end(done);
.get('/')
.set('Accept', 'text/html')
.expect(200)
.expect('Content-Type', 'text/html; charset=utf-8')
.expect(/<a href="\/foo%20%26%20bar"/)
.expect(/foo &amp; bar/)
.expect(bodyDoesNotContain('foo & bar'))
.end(done)
});
it('should sort folders first', function (done) {
var server = createServer()
request(server)
.get('/')
.set('Accept', 'text/html')
.expect(200)
.expect('Content-Type', 'text/html; charset=utf-8')
.end(function (err, res) {
if (err) done(err);
var body = res.text.split('</h1>')[1];
var urls = body.split(/<a href="([^"]*)"/).filter(function(s, i){ return i%2; });
assert.deepEqual(urls, [
'/%23directory',
'/collect',
'/g%23%20%253%20o%20%26%20%252525%20%2537%20dir',
'/users',
'/file%20%231.txt',
'/foo%20%26%20bar',
'/nums',
'/todo.txt',
'/%E3%81%95%E3%81%8F%E3%82%89.txt'
]);
done();
});
.get('/')
.set('Accept', 'text/html')
.expect(200)
.expect('Content-Type', 'text/html; charset=utf-8')
.expect(function (res) {
var urls = res.text
.split('</h1>')[1]
.split(/<a href="([^"]*)"/).filter(function (s, i) { return i % 2 })
assert.deepEqual(urls, [
'/%23directory',
'/collect',
'/g%23%20%253%20o%20%26%20%252525%20%2537%20dir',
'/users',
'/file%20%231.txt',
'/foo%20%26%20bar',
'/nums',
'/todo.txt',
'/%E3%81%95%E3%81%8F%E3%82%89.txt'
])
})
.end(done)
});
});
@@ -212,26 +242,47 @@ describe('serveIndex(root)', function () {
var server = createServer()
request(server)
.get('/')
.set('Accept', 'text/plain')
.expect(200)
.expect('Content-Type', 'text/plain; charset=utf-8')
.expect(/users/)
.expect(/g# %3 o & %2525 %37 dir/)
.expect(/file #1.txt/)
.expect(/todo.txt/)
.expect(/さくら\.txt/)
.end(done);
.get('/')
.set('Accept', 'text/plain')
.expect(200)
.expect('Content-Type', 'text/plain; charset=utf-8')
.expect(/users/)
.expect(/g# %3 o & %2525 %37 dir/)
.expect(/file #1.txt/)
.expect(/todo.txt/)
.expect(/さくら\.txt/)
.end(done)
});
it('should include security header', function (done) {
var server = createServer()
request(server)
.get('/')
.set('Accept', 'text/plain')
.expect('X-Content-Type-Options', 'nosniff')
.expect(200, done)
.get('/')
.set('Accept', 'text/plain')
.expect('X-Content-Type-Options', 'nosniff')
.expect(200, done)
})
it('should sort folders first', function (done) {
request(createServer())
.get('/')
.set('Accept', 'text/plain')
.expect(200)
.expect('Content-Type', 'text/plain; charset=utf-8')
.expect([
'#directory',
'collect',
'g# %3 o & %2525 %37 dir',
'users',
'file #1.txt',
'foo & bar',
'nums',
'todo.txt',
'さくら.txt',
''
].join('\n'))
.end(done)
})
});
@@ -240,9 +291,9 @@ describe('serveIndex(root)', function () {
var server = createServer()
request(server)
.get('/')
.set('Accept', 'application/x-bogus')
.expect(406, done)
.get('/')
.set('Accept', 'application/x-bogus')
.expect(406, done)
});
});
});
@@ -252,26 +303,26 @@ describe('serveIndex(root)', function () {
var server = createServer()
request(server)
.get('/')
.expect(bodyDoesNotContain('.hidden'))
.expect(200, done)
.get('/')
.expect(bodyDoesNotContain('.hidden'))
.expect(200, done)
});
it('should filter hidden files', function (done) {
var server = createServer('test/fixtures', {'hidden': false})
request(server)
.get('/')
.expect(bodyDoesNotContain('.hidden'))
.expect(200, done)
.get('/')
.expect(bodyDoesNotContain('.hidden'))
.expect(200, done)
});
it('should not filter hidden files', function (done) {
var server = createServer('test/fixtures', {'hidden': true})
request(server)
.get('/')
.expect(200, /\.hidden/, done)
.get('/')
.expect(200, /\.hidden/, done)
});
});
@@ -287,9 +338,9 @@ describe('serveIndex(root)', function () {
}
request(server)
.get('/')
.expect(bodyDoesNotContain('foo'))
.expect(200, cb)
.get('/')
.expect(bodyDoesNotContain('foo'))
.expect(200, cb)
});
it('should filter after hidden filter', function (done) {
@@ -304,8 +355,8 @@ describe('serveIndex(root)', function () {
}
request(server)
.get('/')
.expect(200, done)
.get('/')
.expect(200, done)
});
it('should filter directory paths', function (done) {
@@ -320,8 +371,8 @@ describe('serveIndex(root)', function () {
}
request(server)
.get('/users')
.expect(200, cb)
.get('/users')
.expect(200, cb)
});
});
@@ -330,16 +381,17 @@ describe('serveIndex(root)', function () {
var server = createServer(fixtures, {'icons': true})
request(server)
.get('/collect')
.expect(/data:image\/png/)
.expect(/icon-default/)
.expect(/icon-directory/)
.expect(/icon-image/)
.expect(/icon-txt/)
.expect(/icon-application-pdf/)
.expect(/icon-video/)
.expect(/icon-xml/)
.expect(200, done)
.get('/collect')
.expect(/data:image\/png/)
.expect(/icon-default/)
.expect(/icon-directory/)
.expect(/icon-image/)
.expect(/icon-image-svg_xml/)
.expect(/icon-txt/)
.expect(/icon-application-pdf/)
.expect(/icon-video/)
.expect(/icon-xml/)
.expect(200, done)
});
});
@@ -352,39 +404,39 @@ describe('serveIndex(root)', function () {
it('should respond with file list', function (done) {
request(server)
.get('/')
.set('Accept', 'text/html')
.expect(/<a href="\/g%23%20%253%20o%20%26%20%252525%20%2537%20dir"/)
.expect(/<a href="\/users"/)
.expect(/<a href="\/file%20%231.txt"/)
.expect(/<a href="\/todo.txt"/)
.expect(200, done)
.get('/')
.set('Accept', 'text/html')
.expect(/<a href="\/g%23%20%253%20o%20%26%20%252525%20%2537%20dir"/)
.expect(/<a href="\/users"/)
.expect(/<a href="\/file%20%231.txt"/)
.expect(/<a href="\/todo.txt"/)
.expect(200, done)
});
it('should respond with testing template sentence', function (done) {
request(server)
.get('/')
.set('Accept', 'text/html')
.expect(200, /This is the test template/, done)
.get('/')
.set('Accept', 'text/html')
.expect(200, /This is the test template/, done)
});
it('should have default styles', function (done) {
request(server)
.get('/')
.set('Accept', 'text/html')
.expect(200, /ul#files/, done)
.get('/')
.set('Accept', 'text/html')
.expect(200, /ul#files/, done)
});
it('should list directory twice', function (done) {
request(server)
.get('/users/')
.set('Accept', 'text/html')
.expect(function (res) {
var occurances = res.text.match(/directory \/users\//g)
if (occurances && occurances.length === 2) return
throw new Error('directory not listed twice')
})
.expect(200, done)
.get('/users/')
.set('Accept', 'text/html')
.expect(function (res) {
var occurances = res.text.match(/directory \/users\//g)
if (occurances && occurances.length === 2) return
throw new Error('directory not listed twice')
})
.expect(200, done)
});
});
@@ -395,9 +447,9 @@ describe('serveIndex(root)', function () {
}});
request(server)
.get('/')
.set('Accept', 'text/html')
.expect(200, 'This is a template.', done);
.get('/')
.set('Accept', 'text/html')
.expect(200, 'This is a template.', done)
});
it('should handle render errors', function (done) {
@@ -406,9 +458,9 @@ describe('serveIndex(root)', function () {
}});
request(server)
.get('/')
.set('Accept', 'text/html')
.expect(500, 'boom!', done);
.get('/')
.set('Accept', 'text/html')
.expect(500, 'boom!', done)
});
it('should provide "directory" local', function (done) {
@@ -417,9 +469,9 @@ describe('serveIndex(root)', function () {
}});
request(server)
.get('/users/')
.set('Accept', 'text/html')
.expect(200, '"/users/"', done);
.get('/users/')
.set('Accept', 'text/html')
.expect(200, '"/users/"', done)
});
it('should provide "displayIcons" local', function (done) {
@@ -428,9 +480,9 @@ describe('serveIndex(root)', function () {
}});
request(server)
.get('/users/')
.set('Accept', 'text/html')
.expect(200, 'false', done);
.get('/users/')
.set('Accept', 'text/html')
.expect(200, 'false', done)
});
it('should provide "fileList" local', function (done) {
@@ -442,10 +494,10 @@ describe('serveIndex(root)', function () {
}});
request(server)
.get('/users/')
.set('Accept', 'text/html')
.expect('[{"name":"..","stat":true},{"name":"#dir","stat":true},{"name":"index.html","stat":true},{"name":"tobi.txt","stat":true}]')
.expect(200, done);
.get('/users/')
.set('Accept', 'text/html')
.expect('[{"name":"..","stat":true},{"name":"#dir","stat":true},{"name":"index.html","stat":true},{"name":"tobi.txt","stat":true}]')
.expect(200, done)
});
it('should provide "path" local', function (done) {
@@ -454,9 +506,9 @@ describe('serveIndex(root)', function () {
}});
request(server)
.get('/users/')
.set('Accept', 'text/html')
.expect(200, JSON.stringify(path.join(fixtures, 'users/')), done);
.get('/users/')
.set('Accept', 'text/html')
.expect(200, JSON.stringify(path.join(fixtures, 'users/')), done)
});
it('should provide "style" local', function (done) {
@@ -465,9 +517,9 @@ describe('serveIndex(root)', function () {
}});
request(server)
.get('/users/')
.set('Accept', 'text/html')
.expect(200, /#files \.icon \.name/, done);
.get('/users/')
.set('Accept', 'text/html')
.expect(200, /#files \.icon \.name/, done)
});
it('should provide "viewName" local', function (done) {
@@ -476,9 +528,9 @@ describe('serveIndex(root)', function () {
}});
request(server)
.get('/users/')
.set('Accept', 'text/html')
.expect(200, '"tiles"', done);
.get('/users/')
.set('Accept', 'text/html')
.expect(200, '"tiles"', done)
});
});
});
@@ -496,9 +548,9 @@ describe('serveIndex(root)', function () {
}
request(server)
.get('/')
.set('Accept', 'text/html')
.expect(200, 'called', done)
.get('/')
.set('Accept', 'text/html')
.expect(200, 'called', done)
});
it('should get file list', function (done) {
@@ -513,9 +565,9 @@ describe('serveIndex(root)', function () {
}
request(server)
.get('/')
.set('Accept', 'text/html')
.expect(200, '<b>3 text files</b>', done)
.get('/')
.set('Accept', 'text/html')
.expect(200, '<b>3 text files</b>', done)
});
it('should get dir name', function (done) {
@@ -527,9 +579,9 @@ describe('serveIndex(root)', function () {
}
request(server)
.get('/users/')
.set('Accept', 'text/html')
.expect(200, '<b>/users/</b>', done)
.get('/users/')
.set('Accept', 'text/html')
.expect(200, '<b>/users/</b>', done)
});
it('should get template path', function (done) {
@@ -541,9 +593,9 @@ describe('serveIndex(root)', function () {
}
request(server)
.get('/users/')
.set('Accept', 'text/html')
.expect(200, 'true', done)
.get('/users/')
.set('Accept', 'text/html')
.expect(200, 'true', done)
});
it('should get template with tokens', function (done) {
@@ -555,13 +607,13 @@ describe('serveIndex(root)', function () {
}
request(server)
.get('/users/')
.set('Accept', 'text/html')
.expect(/{directory}/)
.expect(/{files}/)
.expect(/{linked-path}/)
.expect(/{style}/)
.expect(200, done)
.get('/users/')
.set('Accept', 'text/html')
.expect(/{directory}/)
.expect(/{files}/)
.expect(/{linked-path}/)
.expect(/{style}/)
.expect(200, done)
});
it('should get stylesheet path', function (done) {
@@ -573,9 +625,9 @@ describe('serveIndex(root)', function () {
}
request(server)
.get('/users/')
.set('Accept', 'text/html')
.expect(200, 'true', done)
.get('/users/')
.set('Accept', 'text/html')
.expect(200, 'true', done)
});
});
@@ -591,9 +643,9 @@ describe('serveIndex(root)', function () {
}
request(server)
.get('/')
.set('Accept', 'text/plain')
.expect(200, 'called', done)
.get('/')
.set('Accept', 'text/plain')
.expect(200, 'called', done)
});
});
@@ -609,9 +661,9 @@ describe('serveIndex(root)', function () {
}
request(server)
.get('/')
.set('Accept', 'application/json')
.expect(200, '"called"', done)
.get('/')
.set('Accept', 'application/json')
.expect(200, '"called"', done)
});
});
});
@@ -621,81 +673,82 @@ describe('serveIndex(root)', function () {
var server = createServer()
request(server)
.get('/users/')
.set('Accept', 'text/html')
.expect(200)
.expect('Content-Type', 'text/html; charset=utf-8')
.expect(/<a href="\/users\/index.html"/)
.expect(/<a href="\/users\/tobi.txt"/)
.end(done);
.get('/users/')
.set('Accept', 'text/html')
.expect(200)
.expect('Content-Type', 'text/html; charset=utf-8')
.expect(/<a href="\/users\/index.html"/)
.expect(/<a href="\/users\/tobi.txt"/)
.end(done)
});
it('should include link to parent directory', function (done) {
var server = createServer()
request(server)
.get('/users')
.end(function (err, res) {
if (err) return done(err);
var body = res.text.split('</h1>')[1];
var urls = body.split(/<a href="([^"]*)"/).filter(function(s, i){ return i%2; });
assert.deepEqual(urls, [
'/',
'/users/%23dir',
'/users/index.html',
'/users/tobi.txt'
]);
done();
});
.get('/users')
.expect(200)
.expect(function (res) {
var urls = res.text
.split('</h1>')[1]
.split(/<a href="([^"]*)"/).filter(function (s, i) { return i % 2 })
assert.deepEqual(urls, [
'/',
'/users/%23dir',
'/users/index.html',
'/users/tobi.txt'
])
})
.end(done)
});
it('should work for directory with #', function (done) {
var server = createServer()
request(server)
.get('/%23directory/')
.set('Accept', 'text/html')
.expect(200)
.expect('Content-Type', 'text/html; charset=utf-8')
.expect(/<a href="\/%23directory"/)
.expect(/<a href="\/%23directory\/index.html"/)
.end(done);
.get('/%23directory/')
.set('Accept', 'text/html')
.expect(200)
.expect('Content-Type', 'text/html; charset=utf-8')
.expect(/<a href="\/%23directory"/)
.expect(/<a href="\/%23directory\/index.html"/)
.end(done)
});
it('should work for directory with special chars', function (done) {
var server = createServer()
request(server)
.get('/g%23%20%253%20o%20%26%20%252525%20%2537%20dir/')
.set('Accept', 'text/html')
.expect(200)
.expect('Content-Type', 'text/html; charset=utf-8')
.expect(/<a href="\/g%23%20%253%20o%20%26%20%252525%20%2537%20dir"/)
.expect(/<a href="\/g%23%20%253%20o%20%26%20%252525%20%2537%20dir\/empty.txt"/)
.end(done);
.get('/g%23%20%253%20o%20%26%20%252525%20%2537%20dir/')
.set('Accept', 'text/html')
.expect(200)
.expect('Content-Type', 'text/html; charset=utf-8')
.expect(/<a href="\/g%23%20%253%20o%20%26%20%252525%20%2537%20dir"/)
.expect(/<a href="\/g%23%20%253%20o%20%26%20%252525%20%2537%20dir\/empty.txt"/)
.end(done)
});
it('should property escape directory names', function (done) {
var server = createServer()
request(server)
.get('/g%23%20%253%20o%20%26%20%252525%20%2537%20dir/')
.set('Accept', 'text/html')
.expect(200)
.expect('Content-Type', 'text/html; charset=utf-8')
.expect(/<a href="\/g%23%20%253%20o%20%26%20%252525%20%2537%20dir"/)
.expect(/g# %3 o &amp; %2525 %37 dir/)
.expect(bodyDoesNotContain('g# %3 o & %2525 %37 dir'))
.end(done);
.get('/g%23%20%253%20o%20%26%20%252525%20%2537%20dir/')
.set('Accept', 'text/html')
.expect(200)
.expect('Content-Type', 'text/html; charset=utf-8')
.expect(/<a href="\/g%23%20%253%20o%20%26%20%252525%20%2537%20dir"/)
.expect(/g# %3 o &amp; %2525 %37 dir/)
.expect(bodyDoesNotContain('g# %3 o & %2525 %37 dir'))
.end(done)
});
it('should not work for outside root', function (done) {
var server = createServer()
request(server)
.get('/../support/')
.set('Accept', 'text/html')
.expect(403, done);
.get('/../support/')
.set('Accept', 'text/html')
.expect(403, done)
});
});
@@ -707,12 +760,12 @@ describe('serveIndex(root)', function () {
it('should respond with appropriate embedded styles', function (done) {
request(server)
.get('/')
.set('Accept', 'text/html')
.expect(200)
.expect('Content-Type', 'text/html; charset=utf-8')
.expect(/color: #00ff00;/)
.end(done);
.get('/')
.set('Accept', 'text/html')
.expect(200)
.expect('Content-Type', 'text/html; charset=utf-8')
.expect(/color: #00ff00;/)
.end(done)
});
});
@@ -724,14 +777,14 @@ describe('serveIndex(root)', function () {
it('should respond with file list', function (done) {
request(server)
.get('/')
.set('Accept', 'application/json')
.expect('Content-Type', /json/)
.expect(/users/)
.expect(/file #1\.txt/)
.expect(/nums/)
.expect(/todo\.txt/)
.expect(200, done)
.get('/')
.set('Accept', 'application/json')
.expect('Content-Type', /json/)
.expect(/users/)
.expect(/file #1\.txt/)
.expect(/nums/)
.expect(/todo\.txt/)
.expect(200, done)
});
});
@@ -744,21 +797,21 @@ describe('serveIndex(root)', function () {
it('should respond with file list', function (done) {
var dest = relative.split(path.sep).join('/');
request(server)
.get('/' + dest + '/')
.set('Accept', 'application/json')
.expect('Content-Type', /json/)
.expect(/users/)
.expect(/file #1\.txt/)
.expect(/nums/)
.expect(/todo\.txt/)
.expect(200, done)
.get('/' + dest + '/')
.set('Accept', 'application/json')
.expect('Content-Type', /json/)
.expect(/users/)
.expect(/file #1\.txt/)
.expect(/nums/)
.expect(/todo\.txt/)
.expect(200, done)
});
it('should not allow serving outside root', function (done) {
request(server)
.get('/../')
.set('Accept', 'text/html')
.expect(403, done);
.get('/../')
.set('Accept', 'text/html')
.expect(403, done)
});
});
});
@@ -793,3 +846,9 @@ function bodyDoesNotContain(text) {
assert.equal(res.text.indexOf(text), -1)
}
}
function shouldNotHaveBody () {
return function (res) {
assert.ok(res.text === '' || res.text === undefined)
}
}