{"id":18389592,"url":"https://github.com/anseki/node-static-alias","last_synced_at":"2025-04-07T02:34:34.395Z","repository":{"id":12834016,"uuid":"15509443","full_name":"anseki/node-static-alias","owner":"anseki","description":"Serve static file which is not requested file. (e.g. `file.min.js` is requested, serve `file.js`)","archived":false,"fork":false,"pushed_at":"2022-08-19T03:21:49.000Z","size":26,"stargazers_count":15,"open_issues_count":0,"forks_count":3,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-03-22T11:45:02.891Z","etag":null,"topics":["alias","directoryindex","file","http","httpd","javascript","log","min","mod-rewrite","server","static","test"],"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/anseki.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2013-12-29T14:17:43.000Z","updated_at":"2024-01-22T13:58:50.000Z","dependencies_parsed_at":"2022-09-07T22:24:03.418Z","dependency_job_id":null,"html_url":"https://github.com/anseki/node-static-alias","commit_stats":null,"previous_names":[],"tags_count":5,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/anseki%2Fnode-static-alias","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/anseki%2Fnode-static-alias/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/anseki%2Fnode-static-alias/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/anseki%2Fnode-static-alias/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/anseki","download_url":"https://codeload.github.com/anseki/node-static-alias/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247583515,"owners_count":20962048,"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":["alias","directoryindex","file","http","httpd","javascript","log","min","mod-rewrite","server","static","test"],"created_at":"2024-11-06T01:43:53.540Z","updated_at":"2025-04-07T02:34:29.380Z","avatar_url":"https://github.com/anseki.png","language":"JavaScript","readme":"# node-static-alias\n\n[![npm](https://img.shields.io/npm/v/node-static-alias.svg)](https://www.npmjs.com/package/node-static-alias) [![GitHub issues](https://img.shields.io/github/issues/anseki/node-static-alias.svg)](https://github.com/anseki/node-static-alias/issues) [![David](https://img.shields.io/david/anseki/node-static-alias.svg)](package.json) [![license](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE)\n\nServe static file which is not requested file. (e.g. `file.min.js` is requested, serve `file.js`)  \nnode-static-alias wraps (inherits) the useful module [node-static](https://github.com/cloudhead/node-static/), and this adds the [`alias`](#alias) option to that.  \nThis works like the [Alias](http://httpd.apache.org/docs/2.4/mod/mod_alias.html) mapping or the [mod_rewrite\n](http://httpd.apache.org/docs/2.4/mod/mod_rewrite.html) of Apache. It looks like [DirectoryIndex](http://httpd.apache.org/docs/2.4/mod/mod_dir.html#directoryindex) too. And this can check the file exists or not.\n\n+ Serve `file.js` instead of `file.min.js` which is not made yet, in the test phase.\n+ Serve the outside files of the document-root which are shared by multiple web sites in one machine.\n+ Serve the default page which is not `index.html` when *`/` is requested.\n\n## Synopsis\n\n```js\nvar staticAlias = require('node-static-alias');\n\n// Document-Root: './public' directory\nvar fileServer = new staticAlias.Server('./public', {\n  alias: {\n    match: '/path/to/file.min.js',\n    serve: '/path/to/file.js'\n  }\n});\n\nrequire('http').createServer(function(request, response) {\n  request.addListener('end', function() {\n    fileServer.serve(request, response);\n  }).resume();\n}).listen(8080);\n```\n\n## Usage\n\nThe [`alias`](#alias) option is added to the node-static via using `require('node-static-alias')` instead of `require('node-static')`. See [node-static](https://github.com/cloudhead/node-static/) to use it.\n\n### `alias`\n\nThe `alias` included in the constructor options is an Alias-Rule Object, or an array which includes multiple Alias-Rule Objects.\n\n```js\n  alias: {\n    match: /file\\.min\\.(?:js|css)$/,\n    serve: '/path/to/file.\u003c% suffix %\u003e'\n  }\n```\n\nOr\n\n```js\n  alias: [\n    {\n      match: '/path/to/file.min.js',\n      serve: '/path/to/file.js'\n    },\n    {\n      match: 'suffix=png',\n      serve: '../outer/\u003c% fileName %\u003e',\n      allowOutside: true\n    }\n  ]\n```\n\nThe Alias-Rule Object can have following properties.\n\n### `match`\n\n**Type:** string, RegExp, function or Array\n\nSpecify one of below or an Array which includes multiple things of those.  \nIf one or more things match, the [`serve`](#serve) is parsed. If anything doesn't match, it goes to next an Alias-Rule. If all Alias-Rules don't match, it tries to serve the requested file.\n\n+ **string:**  \nIf the requested path is equal to this string, it's matched.  \nOr, this can be `parameter=value` format (e.g. `suffix=png`). See [Parameters](#parameters). If the `value` is equal to the specified parameter, it's matched.\n\n```js\n  alias: [\n    {\n      match: '/path/to/file.min.js',\n      serve: '/path/to/file.js'\n    },\n    // Image files are not made yet.\n    {\n      match: 'suffix=png',\n      serve: '/path/to/dummy.png'\n    }\n  ]\n```\n\n+ **RegExp:**  \nThe RegExp which tests the requested path.\n\n```js\n  // These image files are not made yet.\n  alias: {\n    match: /\\/(?:foo|bar)\\.png$/,\n    serve: '/path/to/dummy.png'\n  }\n```\n\n+ **function:**  \nThe function which returns `true` or `false`.\nThe Object which has parameters is passed to this function. See [Parameters](#parameters). Also, current `request` instance and `response` instance are passed.  \nIn the function, `this` refers to own instance.\n\n```js\n  // Kick direct access from outside web site.\n  alias: {\n    match: function(params, request, response) {\n      console.log(request.url + ' was requested, in the path ' + this.root);\n      return params.suffix === 'jpg' \u0026\u0026\n        params.referer.indexOf('http://mysite.com/') !== 0;\n    },\n    serve: '/path/to/denial.jpg'\n  }\n```\n\n### `serve`\n\n**Type:** string, function or Array\n\nSpecify one of below or an Array which includes multiple things of those.  \nBy default, the first file which exists is chosen to try to serve. See [force](#force). If anything doesn't exist, it goes to next an Alias-Rule. If all files of Alias-Rules don't exist, it tries to serve the requested file.\n\n+ **string:**  \nThe absolute path or relative path from the document-root of the file to serve.  \nThis can include parameters like `\u003c% parameter %\u003e`. See [Parameters](#parameters).\n\n```js\n  // directoryIndex isn't index.html\n  alias: {\n    match: /\\/$/,\n    serve: '\u003c% absPath %\u003e/default.html'\n  }\n```\n\n*NOTE:* If the first character of this string is `/` (it might be parameter), this string is absolute path. This `/` doesn't point the document-root. It is the root of the local filesystem. If you want the relative path from the document-root, don't specify leading `/`, or add `.` to left of leading `/`.\n\n+ **function:**  \nThe function which returns the absolute path or relative path from the document-root of the file to serve.  \nThe Object which has parameters is passed to this function. See [Parameters](#parameters). Also, current `request` instance and `response` instance are passed.  \nIn the function, `this` refers to own instance.\n\n```js\n  // Minified files are not made yet.\n  alias: {\n    match: /\\.min\\.(?:js|css)$/,\n    serve: function(params, request, response) {\n      response.setHeader('X-serve-from', this.root);\n      return params.absDir + '/' +\n        params.basename.replace(/\\.min$/, '.') + params.suffix;\n    }\n  }\n```\n\n```js\n  // Compile unwatched SASS now.\n  alias: {\n    match: 'suffix=css',\n    serve: function(params) {\n      require('exec-sync')('sass ' +\n        params.absDir + '/' + params.basename + '.scss:' + params.absPath);\n      return params.absPath;\n    }\n  }\n```\n\n### `force`\n\n**Type:** boolean\n\nIf `true` is specified, the first file in the [`serve`](#serve) is chosen to try to serve without checking it's existing or not. And if it doesn't exist, a 404 error occurs. Default is `false`.  \nThis is used to prevent another file from being chosen unintentionally.\n\n### `allowOutside`\n\nIf `true` is specified, serving the outside files of the document-root is allowed. Default is `false`.\n\n```js\n  // Shared files.\n  alias: {\n    match: /^\\/common_lib/,\n    serve: '/path/to/lib/\u003c% fileName %\u003e',\n    allowOutside: true\n  }\n```\n\n*NOTE:* If you specify `true` in the public server, you should specify the absolute path to the [`serve`](#serve). Otherwise the user might access to the file that must be hidden from them.\n\n## Parameters\n\nThe string `parameter=value` can be specified to the [`match`](#match), and the string `\u003c% parameter %\u003e` can be specified to the [`serve`](#serve).  \nAnd also, the Object which has parameters is passed to function which specified to the [`match`](#match) and the [`serve`](#serve).  \nThese parameters are below.\n\n+ `reqUrl`  \nThe URL which is requested by the user. e.g. `/path/to/file.ext?key1=value1\u0026key2=value2`\n+ `reqPath`  \nThe path which is requested by the user. e.g. `/path/to/file.ext`  \nThis might be a directory. e.g. `/`\n+ `reqDir`  \nThe path to a directory which is part of `reqPath`. e.g. `/path/to`\n+ `absPath`  \nThe absolute path to a requested file. e.g. `/var/www/public/path/to/file.ext`\n+ `absDir`  \nThe absolute path to a directory which is part of `absPath`. e.g. `/var/www/public/path/to`\n+ `fileName`  \nThe file name of a requested file. e.g. `file.ext`  \nThis might be a directory name e.g. `to`  \nIf the document-root is requested, this is empty string.\n+ `basename`  \nThe part of the file name except file-suffix. (`.` isn't included) e.g. `file`\n+ `suffix`  \nThe part of the file name which is extracted file-suffix. (`.` isn't included) e.g. `ext`\n+ `reqQuery`  \nThe URL query string which is part of `reqUrl`. e.g. `key1=value1\u0026key2=value2`\n+ Parsed query string  \nPairs of a key beginning with a `query_` and a value. e.g. `query_key1`: `value1`, `query_key2`: `value2` from `reqQuery` above  \nAn array is extracted and each key is given `[INDEX]`. e.g. `query_key[0]`: `value1`, `query_key[1]`: `value2` from `key=value1\u0026key=value2`\n+ Request Headers  \nThe HTTP Request Headers from the client. These are lower-cased. e.g. `referer`, `user-agent`, etc.\n\n## Logging\n\nThe `logger` included in constructor options is a Logger instance of the standard Logging Library (e.g. [log4js](https://github.com/nomiddlename/log4js-node)) which has `info` method or `log` method.\n\n```js\nvar log4js = require('log4js');\nvar logger = log4js.getLogger('node-static-alias');\nlogger.setLevel(log4js.levels.INFO);\n\nvar fileServer = new staticAlias.Server('./public' {\n  alias: { ... },\n  logger: logger\n});\n```\n\nYou can specify a simple Object which has `info` method or `log` method (e.g. `console` or `util`).  \nMost easy:\n\n```js\nvar fileServer = new staticAlias.Server('./public' {\n  alias: { ... },\n  logger: console\n  //logger: require('util') // Add timestamp\n});\n```\n\nAdd project name: (But, you probably use your favorite library.)\n\n```js\nvar fileServer = new staticAlias.Server('./public' {\n  alias: { ... },\n  logger: {log: function() {\n    var util = require('util');\n    console.log('[node-static-alias] ' +  util.format.apply(util, arguments));\n  }}\n});\n```\n\nLog message example:\n\n```console\n(/) Requested: \"/var/public\"\n(/file.min.css) Requested: \"/var/public/file.min.css\"\n(/file.min.css) For Serve: \"/var/public/file.css\" alias[3] match[1] serve[0]\n(/file.min.js) Requested: \"/var/public/file.min.js\"\n(/file.min.js) For Serve: \"/var/public/file.js\" alias[2] match[0] serve[1]\n```\n\nThe `(path)` is the path which is requested by the user. The `[number]` means an index of an Array.\n\n## Files list in the Directory\n\nThis example generates a list of files and directories in requested directory when the user accessed the directory. This works like the [mod_autoindex](http://httpd.apache.org/docs/2.4/mod/mod_autoindex.html) of Apache.\n\nThat looks like:  \n![ss](ss.png)\n\nThe [statsFilelist](https://www.npmjs.com/package/stats-filelist) is required.\n\n```\nnpm install stats-filelist\n```\n\nLoad that and some core modules.\n\n```js\nvar filelist = require('stats-filelist'),\n  path = require('path'),\n  fs = require('fs');\n```\n\nSpecify for `alias`:\n\n```js\nalias: {\n  match: function(params) {\n    try {\n      return fs.statSync(params.absPath).isDirectory();\n    } catch (error) {\n      return false; // Ignore \"Not found\" etc.\n    }\n  },\n  serve: function(params) {\n    var indexPath = path.join(params.absPath, '.index.html');\n    fs.writeFileSync(indexPath,\n      '\u003chtml\u003e\u003cbody\u003e\u003cul\u003e' +\n      filelist.getSync(params.absPath, /^(?!.*[/\\\\]\\.index\\.html$).+$/, false)\n        .map(function(stat) {\n          var relPath = stat.name + (stat.isDirectory() ? '/' : '');\n          return '\u003cli\u003e\u003ca href=\"' + relPath + '\"\u003e' + relPath + '\u003c/a\u003e\u003c/li\u003e';\n        }).join('') +\n      '\u003c/ul\u003e\u003c/body\u003e\u003c/html\u003e');\n    return indexPath;\n  }\n}\n```\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fanseki%2Fnode-static-alias","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fanseki%2Fnode-static-alias","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fanseki%2Fnode-static-alias/lists"}