UNPKG

2.8 kBJavaScriptView Raw
1const fs = require('fs');
2const path = require('path');
3const mime = require('../mime');
4const EventEmitter = require('events');
5const ResponseStream = require('./ResponseStream');
6
7const methods = {
8 GET: (filename, req) => {
9 req.end = () => {
10 const stream = should404(filename) ?
11 new ResponseStream().error(404, `ENOENT: no such file or directory, open '${filename}'`) :
12 fs.createReadStream(filename);
13 req.res = stream;
14 stream.headers = {
15 'content-length': 0,
16 'content-type': mime.lookup(path.extname(filename)),
17 };
18 stream.on('open', () => {
19 req.emit('response', stream);
20 });
21 if (stream instanceof ResponseStream) return;
22 stream.statusCode = 200;
23 stream.on('end', () => {
24 stream.headers['content-length'] = stream.bytesRead;
25 });
26 stream.on('error', (err) => {
27 stream.statusCode = 400;
28 stream.status = err.message;
29 });
30 };
31 },
32 POST: (filename, req) => {
33 const chunks = [];
34 req.write = (data) => {
35 chunks.push(data);
36 };
37 req.end = (data) => {
38 chunks.push(data);
39 const stream = fs.createWriteStream(filename);
40 const standin = new ResponseStream();
41 req.res = standin;
42 standin.headers = {
43 'content-length': 0,
44 'content-type': mime.lookup(path.extname(filename)),
45 };
46 stream.on('finish', () => {
47 req.emit('response', standin);
48 });
49 stream.on('open', () => {
50 (function write() {
51 const chunk = chunks.shift();
52 if (!chunk) return;
53 if (!stream.write(chunk)) {
54 stream.once('drain', write);
55 } else {
56 write();
57 }
58 }());
59 stream.end();
60 });
61 };
62 },
63 DELETE: (filename, req) => {
64 req.end = () => {
65 const stream = new ResponseStream();
66 req.res = stream;
67 stream.headers = {
68 'content-length': 0,
69 'content-type': mime.lookup(path.extname(filename)),
70 };
71 fs.unlink(filename, (err) => {
72 req.emit('response', err ? stream.error(400, err.message) : stream);
73 });
74 };
75 },
76};
77
78class Req extends EventEmitter {
79 constructor() {
80 super();
81 this._headers = {};
82 }
83
84 setHeader() {} // eslint-disable-line no-empty-function
85 getHeader() {} // eslint-disable-line no-empty-function
86}
87
88function request(options) {
89 const method = methods[options.method];
90 if (!method) throw new Error(`Invalid request method "${method}"`);
91 const filename = options.href.replace('file://', '');
92
93 const req = new Req();
94 method(filename, req, options);
95 return req;
96}
97
98function should404(p) {
99 try {
100 return fs.lstatSync(p).isDirectory();
101 } catch (err) {
102 return true;
103 }
104}
105
106module.exports = {
107 request,
108};