1 |
|
2 |
|
3 | var path = require("path")
|
4 |
|
5 |
|
6 | module.exports = function createStatic(_root, _opts) {
|
7 | var root = path.resolve(_root)
|
8 | , opts = Object.assign({
|
9 | index: "index.html",
|
10 | maxAge: 31536000, // One year
|
11 | rangeSize: 500 * 1024,
|
12 | cacheControl: {
|
13 | "cache.manifest": 0,
|
14 | "worker.js": 0
|
15 | }
|
16 | }, _opts)
|
17 |
|
18 | if (opts.cacheControl) {
|
19 | var map = {}
|
20 | Object.each(opts.cacheControl, function(time, file) {
|
21 | map[path.resolve(root, file)] = time
|
22 | })
|
23 | opts.cacheControl = map
|
24 | }
|
25 |
|
26 | return function(req, res, next) {
|
27 | var file
|
28 | , method = req.method
|
29 |
|
30 | if (method !== "GET" && method !== "HEAD") {
|
31 | res.setHeader("Allow", "GET, HEAD")
|
32 | return res.sendStatus(405) // Method not allowed
|
33 | }
|
34 |
|
35 | if (req.url === "/" && !opts.index) {
|
36 | return res.sendStatus(404)
|
37 | }
|
38 |
|
39 | try {
|
40 | file = path.resolve(root, (
|
41 | req.url === "/" ?
|
42 | opts.index :
|
43 | "." + decodeURIComponent(req.url.split("?")[0].replace(/\+/g, " "))
|
44 | ))
|
45 | } catch (e) {
|
46 | return res.sendStatus(400)
|
47 | }
|
48 |
|
49 | if (file.slice(0, root.length) !== root) {
|
50 | return res.sendStatus(404)
|
51 | }
|
52 | res.sendFile(file, opts, function(err) {
|
53 | if (err && (err.name === "EISDIR" || err.name === "ERANGE" )) {
|
54 | res.sendStatus(err.code)
|
55 | } else {
|
56 | next()
|
57 | }
|
58 | })
|
59 | }
|
60 | }
|
61 |
|
62 |
|
63 |
|
64 |
|
65 | /*
|
66 |
|
67 | 300 Multiple Choices
|
68 | --------------------
|
69 | // https://www.w3.org/Style/Examples/007/figures.h
|
70 |
|
71 | The document name you requested (/Style/Examples/007/figures.) could not be found on this server. However, we found documents with names similar to the one you requested.
|
72 | Available documents:
|
73 | - /Style/Examples/007/figures.it.html.redirect (common basename)
|
74 |
|
75 | Please consider informing the owner of the __referring page__ about the broken link.
|
76 |
|
77 | - It is possible to communicate the list using a set of Link header fields [RFC5988],
|
78 | each with a relationship of "alternate".
|
79 | - https://tools.ietf.org/html/rfc2295 Transparent Content Negotiation in HTTP
|
80 | https://tools.ietf.org/html/draft-ietf-http-alternates-01
|
81 | Alternates: {"http://x.org/paper.1" 0.9 {type text/html} {language en}}, {"http://x.org/paper.2" 0.7 {type text/html} {language fr}}
|
82 |
|
83 |
|
84 | 406 Not Acceptable
|
85 | ------------------
|
86 |
|
87 | It is not what anyone would expect, but if you're sure:
|
88 | you can for example use a custom header like Accept-confirm: confirm-delete, and return 406 Not Acceptable if the Accept-confirm header is not what you expect.
|
89 |
|
90 |
|
91 | This is done through the following code:
|
92 |
|
93 | <a href="javascript:void(0);"
|
94 | onclick="document.execCommand('SaveAs',true,'file.html');"
|
95 | >Save this page</a>
|
96 |
|
97 | However, usually you want to save another file, the file a hyperlink leads to. To do that javascript is not enough (at least there is no such standard way) and something must be done on the server.
|
98 | Forcing SaveAs using the HTTP header
|
99 |
|
100 | In order to force the browser to show SaveAs dialog when clicking a hyperlink you have to include the following header in HTTP response of the file to be downloaded:
|
101 |
|
102 | Content-Disposition: attachment; filename="<file name.ext>"
|
103 |
|
104 | Where <file name.ext> is the filename you want to appear in SaveAs dialog (like finances.xls or mortgage.pdf) - without < and > symbols.
|
105 |
|
106 | You have to keep the following in mind:
|
107 |
|
108 | The filename should be in US-ASCII charset and shouldn't contain special characters: < > \ " / : | ? * space.
|
109 | The filename should not have any directory path information specified.
|
110 | The filename should be enclosed in double quotes but most browsers will support file names without double quotes.
|
111 | Ancient browsers also required the following (not needed nowadays, but for a fool proof solution might be worth doing):
|
112 |
|
113 | Content-Type header should be before Content-Disposition.
|
114 | Content-Type header should refer to an unknown MIME type (at least until the older browsers go away).
|
115 |
|
116 |
|
117 |
|
118 | Try downloading files with Content-disposition
|
119 |
|
120 | Try the header support in your browser, click here:
|
121 |
|
122 | Text file with Content-Type of application/x-unknown.
|
123 |
|
124 | */
|
125 |
|
126 |
|
127 |
|
128 |
|