{"id":13493826,"url":"https://github.com/expressjs/serve-static","last_synced_at":"2025-05-14T21:02:22.725Z","repository":{"id":14743301,"uuid":"17464338","full_name":"expressjs/serve-static","owner":"expressjs","description":"Serve static files","archived":false,"fork":false,"pushed_at":"2025-05-01T18:04:18.000Z","size":431,"stargazers_count":1414,"open_issues_count":23,"forks_count":236,"subscribers_count":30,"default_branch":"master","last_synced_at":"2025-05-07T20:34:59.613Z","etag":null,"topics":["expressjs","javascript","middleware","nodejs","send","serve-files"],"latest_commit_sha":null,"homepage":null,"language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/expressjs.png","metadata":{"files":{"readme":"README.md","changelog":"HISTORY.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null},"funding":{"open_collective":"express"}},"created_at":"2014-03-06T03:07:17.000Z","updated_at":"2025-05-07T10:07:32.000Z","dependencies_parsed_at":"2024-12-23T20:07:16.518Z","dependency_job_id":"77acfbad-40bd-4c13-9db8-12dc92e15552","html_url":"https://github.com/expressjs/serve-static","commit_stats":{"total_commits":370,"total_committers":17,"mean_commits":"21.764705882352942","dds":0.08378378378378382,"last_synced_commit":"e2bf828a6899e18969e522ddce304fec497b058f"},"previous_names":[],"tags_count":68,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/expressjs%2Fserve-static","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/expressjs%2Fserve-static/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/expressjs%2Fserve-static/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/expressjs%2Fserve-static/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/expressjs","download_url":"https://codeload.github.com/expressjs/serve-static/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254050841,"owners_count":22006372,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["expressjs","javascript","middleware","nodejs","send","serve-files"],"created_at":"2024-07-31T19:01:19.173Z","updated_at":"2025-05-14T21:02:22.610Z","avatar_url":"https://github.com/expressjs.png","language":"JavaScript","funding_links":["https://opencollective.com/express"],"categories":["JavaScript","1. 后端开发","中间件"],"sub_categories":["1.2 框架"],"readme":"# serve-static\n\n[![NPM Version][npm-version-image]][npm-url]\n[![NPM Downloads][npm-downloads-image]][npm-url]\n[![CI][github-actions-ci-image]][github-actions-ci-url]\n[![Test Coverage][coveralls-image]][coveralls-url]\n\n## Install\n\nThis is a [Node.js](https://nodejs.org/en/) module available through the\n[npm registry](https://www.npmjs.com/). Installation is done using the\n[`npm install` command](https://docs.npmjs.com/getting-started/installing-npm-packages-locally):\n\n```sh\n$ npm install serve-static\n```\n\n## API\n\n```js\nvar serveStatic = require('serve-static')\n```\n\n### serveStatic(root, options)\n\nCreate a new middleware function to serve files from within a given root\ndirectory. The file to serve will be determined by combining `req.url`\nwith the provided root directory. When a file is not found, instead of\nsending a 404 response, this module will instead call `next()` to move on\nto the next middleware, allowing for stacking and fall-backs.\n\n#### Options\n\n##### acceptRanges\n\nEnable or disable accepting ranged requests, defaults to true.\nDisabling this will not send `Accept-Ranges` and ignore the contents\nof the `Range` request header.\n\n##### cacheControl\n\nEnable or disable setting `Cache-Control` response header, defaults to\ntrue. Disabling this will ignore the `immutable` and `maxAge` options.\n\n##### dotfiles\n\nSet how \"dotfiles\" are treated when encountered. A dotfile is a file\nor directory that begins with a dot (\".\"). Note this check is done on\nthe path itself without checking if the path actually exists on the\ndisk. If `root` is specified, only the dotfiles above the root are\nchecked (i.e. the root itself can be within a dotfile when set\nto \"deny\").\n\n  - `'allow'` No special treatment for dotfiles.\n  - `'deny'` Deny a request for a dotfile and 403/`next()`.\n  - `'ignore'` Pretend like the dotfile does not exist and 404/`next()`.\n\nThe default value is `'ignore'`.\n\n##### etag\n\nEnable or disable etag generation, defaults to true.\n\n##### extensions\n\nSet file extension fallbacks. When set, if a file is not found, the given\nextensions will be added to the file name and search for. The first that\nexists will be served. Example: `['html', 'htm']`.\n\nThe default value is `false`.\n\n##### fallthrough\n\nSet the middleware to have client errors fall-through as just unhandled\nrequests, otherwise forward a client error. The difference is that client\nerrors like a bad request or a request to a non-existent file will cause\nthis middleware to simply `next()` to your next middleware when this value\nis `true`. When this value is `false`, these errors (even 404s), will invoke\n`next(err)`.\n\nTypically `true` is desired such that multiple physical directories can be\nmapped to the same web address or for routes to fill in non-existent files.\n\nThe value `false` can be used if this middleware is mounted at a path that\nis designed to be strictly a single file system directory, which allows for\nshort-circuiting 404s for less overhead. This middleware will also reply to\nall methods.\n\nThe default value is `true`.\n\n##### immutable\n\nEnable or disable the `immutable` directive in the `Cache-Control` response\nheader, defaults to `false`. If set to `true`, the `maxAge` option should\nalso be specified to enable caching. The `immutable` directive will prevent\nsupported clients from making conditional requests during the life of the\n`maxAge` option to check if the file has changed.\n\n##### index\n\nBy default this module will send \"index.html\" files in response to a request\non a directory. To disable this set `false` or to supply a new index pass a\nstring or an array in preferred order.\n\n##### lastModified\n\nEnable or disable `Last-Modified` header, defaults to true. Uses the file\nsystem's last modified value.\n\n##### maxAge\n\nProvide a max-age in milliseconds for http caching, defaults to 0. This\ncan also be a string accepted by the [ms](https://www.npmjs.org/package/ms#readme)\nmodule.\n\n##### redirect\n\nRedirect to trailing \"/\" when the pathname is a dir. Defaults to `true`.\n\n##### setHeaders\n\nFunction to set custom headers on response. Alterations to the headers need to\noccur synchronously. The function is called as `fn(res, path, stat)`, where\nthe arguments are:\n\n  - `res` the response object\n  - `path` the file path that is being sent\n  - `stat` the stat object of the file that is being sent\n\n## Examples\n\n### Serve files with vanilla node.js http server\n\n```js\nvar finalhandler = require('finalhandler')\nvar http = require('http')\nvar serveStatic = require('serve-static')\n\n// Serve up public/ftp folder\nvar serve = serveStatic('public/ftp', { index: ['index.html', 'index.htm'] })\n\n// Create server\nvar server = http.createServer(function onRequest (req, res) {\n  serve(req, res, finalhandler(req, res))\n})\n\n// Listen\nserver.listen(3000)\n```\n\n### Serve all files as downloads\n\n```js\nvar contentDisposition = require('content-disposition')\nvar finalhandler = require('finalhandler')\nvar http = require('http')\nvar serveStatic = require('serve-static')\n\n// Serve up public/ftp folder\nvar serve = serveStatic('public/ftp', {\n  index: false,\n  setHeaders: setHeaders\n})\n\n// Set header to force download\nfunction setHeaders (res, path) {\n  res.setHeader('Content-Disposition', contentDisposition(path))\n}\n\n// Create server\nvar server = http.createServer(function onRequest (req, res) {\n  serve(req, res, finalhandler(req, res))\n})\n\n// Listen\nserver.listen(3000)\n```\n\n### Serving using express\n\n#### Simple\n\nThis is a simple example of using Express.\n\n```js\nvar express = require('express')\nvar serveStatic = require('serve-static')\n\nvar app = express()\n\napp.use(serveStatic('public/ftp', { index: ['default.html', 'default.htm'] }))\napp.listen(3000)\n```\n\n#### Multiple roots\n\nThis example shows a simple way to search through multiple directories.\nFiles are searched for in `public-optimized/` first, then `public/` second\nas a fallback.\n\n```js\nvar express = require('express')\nvar path = require('path')\nvar serveStatic = require('serve-static')\n\nvar app = express()\n\napp.use(serveStatic(path.join(__dirname, 'public-optimized')))\napp.use(serveStatic(path.join(__dirname, 'public')))\napp.listen(3000)\n```\n\n#### Different settings for paths\n\nThis example shows how to set a different max age depending on the served\nfile. In this example, HTML files are not cached, while everything else\nis for 1 day.\n\n```js\nvar express = require('express')\nvar path = require('path')\nvar serveStatic = require('serve-static')\n\nvar app = express()\n\napp.use(serveStatic(path.join(__dirname, 'public'), {\n  maxAge: '1d',\n  setHeaders: setCustomCacheControl\n}))\n\napp.listen(3000)\n\nfunction setCustomCacheControl (res, file) {\n  if (path.extname(file) === '.html') {\n    // Custom Cache-Control for HTML files\n    res.setHeader('Cache-Control', 'public, max-age=0')\n  }\n}\n```\n\n## License\n\n[MIT](LICENSE)\n\n[coveralls-image]: https://badgen.net/coveralls/c/github/expressjs/serve-static/master\n[coveralls-url]: https://coveralls.io/r/expressjs/serve-static?branch=master\n[github-actions-ci-image]: https://badgen.net/github/checks/expressjs/serve-static/master?label=linux\n[github-actions-ci-url]: https://github.com/expressjs/serve-static/actions/workflows/ci.yml\n[node-image]: https://badgen.net/npm/node/serve-static\n[node-url]: https://nodejs.org/en/download/\n[npm-downloads-image]: https://badgen.net/npm/dm/serve-static\n[npm-url]: https://npmjs.org/package/serve-static\n[npm-version-image]: https://badgen.net/npm/v/serve-static\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fexpressjs%2Fserve-static","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fexpressjs%2Fserve-static","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fexpressjs%2Fserve-static/lists"}