-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathweb.js
More file actions
151 lines (136 loc) · 3.87 KB
/
web.js
File metadata and controls
151 lines (136 loc) · 3.87 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
'use strict';
globalThis.MODULE = require('./common/module.js');
const path = require('path');
const fs = require('fs');
const xmldom = require('xmldom');
require('./common/DOM.js');
require('./operation.js');
require('./web/browser/common.js');
require('./web/API.js');
MODULE.define(
null,
[ 'common', 'API'],
function (common, API) {
const certificate_file = 'certificate.pem';
const key_file = 'key.pem';
const BODY_LENGTH_LIMIT = 1048576;
var port = Number.parseInt(process.env['PORT']);
const server = (
function () {
try {
fs.accessSync(certificate_file, fs.constants.R_OK);
fs.accessSync(key_file, fs.constants.R_OK);
} catch (error) {
port = port || 443;
console.info('HTTP on', port);
return require('http').createServer();
}
port = port || 80;
console.info('HTTPS on', port);
return require('http2').createSecureServer(
{
cert: fs.readFileSync(certificate_file),
key: fs.readFileSync(key_file),
allowHTTP1: true
}
);
}()
);
const type_extension = {
__proto__: null,
'.xhtml': 'application/xhtml+xml',
'.css': 'text/css; charset=UTF-8',
'.js': 'application/javascript; charset=UTF-8'
};
function type_file(file) {
for (const extension in type_extension)
if (file.endsWith(extension))
return type_extension[extension];
return null;
}
function respond_file(response, file) {
const type = type_file(file);
if (type === null)
return response.writeHead(404).end();
return fs.readFile(
path.join(file),
(error, content) => {
if (error !== null) {
return response.writeHead(404).end();
} else {
response.setHeader('Content-Type', type);
response.writeHead(200);
return response.end(content);
}
}
);
}
function handle_GET(response, request) {
const rawpath = new URL(request.url, 'http://[::1]').pathname;
if (!rawpath.startsWith('/'))
return response.writeHead(404).end();
const pathname = rawpath === '/' ? '/index.xhtml' : path.normalize(rawpath);
const type = type_file(pathname);
if (type === null)
return response.writeHead(404).end();
if (pathname.startsWith('/common/') || pathname.startsWith('/browser/'))
return respond_file(response, path.join(__dirname, pathname));
else
return respond_file(response, path.join(__dirname, 'web', 'browser', pathname));
}
async function handle_XML(response, request, body) {
const pathname = new URL(request.url, 'http://[::1]').pathname;
if (pathname !== common.API_URL) {
response.setHeader('Content-Type', 'text/plain; charset=US-ASCII');
return response.writeHead(404).end();
}
const xml = (new xmldom.DOMParser).parseFromString(body.toString());
return API.dispatch(response, xml);
}
function handle_POST(response, request) {
const data_collection = new Array;
request.on(
'end',
async function () {
if (data_collection === null) {
response.setHeader('Content-Type', 'text/plain; charset=US-ASCII');
return response.writeHead(500).end();
}
const body = Buffer.concat(data_collection);
if (request.headers['content-type'] === 'text/xml')
return handle_XML(response, request, body);
return response.writeHead(400).end();
}
);
request.on(
'data',
function (data) {
if (data_collection === null) {
response.setHeader('Content-Type', 'text/plain; charset=US-ASCII');
return response.writeHead(500).end();
}
if (data_collection.reduce((length, chunk) => length + chunk.length, 0) > BODY_LENGTH_LIMIT) {
data_collection = null;
request.destory();
response.setHeader('Content-Type', 'text/plain; charset=US-ASCII');
return response.writeHead(413).end();
}
return data_collection.push(data);
}
);
}
server.on(
'request',
function (request, response) {
switch (request.method) {
case 'GET':
return handle_GET(response, request);
case 'POST':
return handle_POST(response, request);
default:
return response.writeHead(405).end();
}
}
);
server.listen(port);
});