UNPKG

5.13 kBJavaScriptView Raw
1var fs = require('fs'),
2 path = require('path'),
3 union = require('union'),
4 ecstatic = require('ecstatic'),
5 httpProxy = require('http-proxy'),
6 corser = require('corser'),
7 colors = require('colors'),
8 logger = require('../util/logger'),
9 util = require('../util/util'),
10 php_fpm = require('./lib/php-fpm'),
11 contentTypesMap = require('./lib/contentType'),
12 findSimilarFile = require('./lib/findSimilarFile');
13
14exports.HttpServer = exports.HTTPServer = HttpServer;
15
16exports.createServer = function (options) {
17 return new HttpServer(options);
18}
19
20function HttpServer(options) {
21 options = options || {};
22 this.root = options['root']
23 this.headers = options.headers || {}
24 this.contentType = options.contentType || 'application/octet-stream'
25 // 允许跨域
26 this.headers['Access-Control-Allow-Origin'] = '*';
27 this.headers['Access-Control-Allow-Credentials'] = true;
28 this.headers['Access-Control-Allow-Headers'] = 'Origin, X-Requested-With, Content-Type, Accept, Range';
29
30 var before = options.before ? options.before.slice() : []
31
32 //记录访问日志
33 before.push(function (req, res, next) {
34 var err
35 try {
36 logger.http(req, res);
37 } catch(ex) {
38 ex.status = 503
39 err = ex
40 }
41 next(err)
42 })
43
44 //调用本地 php-fpm 解析 php 文件
45 if(options['php']){
46 var php = new php_fpm({
47 documentRoot: path.resolve(process.cwd(), this.root)
48 });
49 before.push(function (req, res, next) {
50 var err;
51 if(util.getFileExtension(req.url) == 'php') {
52 try {
53 php.run(req, function(phpParseErr, output){
54 if(output && output.indexOf('<b>Parse error</b>') > -1){
55 if(!phpParseErr){
56 phpParseErr = {}
57 }
58 if(!phpParseErr['stack']){
59 phpParseErr['stack'] = output
60 }
61 }
62 if(!phpParseErr){
63 res.setHeader('Content-Type', 'text/html');
64 res.write(output, "utf-8");
65 return res.end()
66 } else {
67 phpParseErr.status = 503
68 next(phpParseErr)
69 }
70 })
71 } catch(ex) {
72 ex.status = 503
73 err = ex
74 next(err)
75 }
76 } else {
77 next(err)
78 }
79 })
80 }
81
82 // favicon 图标处理.
83 before.push(function (req, res) {
84 if (req.url === '/favicon.ico') {
85 var icoPath = path.resolve( __dirname, './assets/images/favicon.ico' )
86 res.setHeader('Content-Type', 'image/x-icon');
87 res.write(fs.readFileSync(icoPath, "binary"), "binary");
88 return res.end()
89 }
90 res.emit('next');
91 });
92
93 //处理静态资源.
94 before.push(ecstatic({
95 root: this.root,
96 cache: 1,
97 showDir: true,
98 autoIndex: true,
99 gzip: false,
100 contentType: this.contentType,
101 handleError: typeof options.proxy !== 'string'
102 }));
103
104 //使用代理服务器
105 if (options.proxy && typeof options.proxy === 'string') {
106 var proxy = httpProxy.createProxyServer({});
107 proxy.on('error', function (err, req, res){})
108 proxy.on('proxyRes', function (proxyRes, req, res) {
109 console.log('proxy ', res['statusCode'], req.url)
110 })
111 before.push(function (req, res) {
112 proxy.web(req, res, {
113 target: options.proxy,
114 changeOrigin: true
115 })
116 })
117 }
118
119 //处理一部分特殊扩展名,以指定的内容类型响应。
120 // before.push(function (req, res) {
121 // let fileExt = util.getFileExtension(req.url)
122 // if(contentTypesMap[fileExt]){
123 // console.log(contentTypesMap[fileExt])
124 // res.setHeader('Content-Type', contentTypesMap[fileExt]);
125 // }
126 // res.emit('next');
127 // })
128
129 //创建内部的 union server
130 var unionOptions = {
131 before: before,
132 headers: this.headers,
133 onError: function (err, req, res) {
134 if(err.status == 404){
135 var cwd = process.cwd()
136 var filePath = cwd + req.url;
137 var similarFile = findSimilarFile(filePath)
138 if(similarFile){
139 res.writeHead(200, {}) //重置响应状态码
140 let fileContent = fs.readFileSync(similarFile['pathName'], 'utf-8');
141 res.write(fileContent, "utf-8");
142 err['transfer-url'] = similarFile['pathName'].replace(cwd, '')
143 logger.http(req, res, err)
144 return res.end()
145 } else {
146 logger.http(req, res, err)
147 return require('./lib/page/index.js')(404, req, res, err);
148 }
149 }
150 logger.http(req, res, err)
151 return require('./lib/page/index.js')(503, req, res, err);
152 }
153 }
154 if (options.ssl) {
155 unionOptions.https = {
156 cert: path.resolve(__dirname, './assets/pem/cert.pem'),
157 key: path.resolve(__dirname, './assets/pem/key.pem')
158 }
159 }
160 this.server = union.createServer(unionOptions)
161}
162
163HttpServer.prototype.listen = function () {
164 this.server.listen.apply(this.server, arguments)
165}
166
167HttpServer.prototype.close = function () {
168 return this.server.close()
169}