Node.js: a shim for overriding "http" and "websocket" modules.
Also added stubs for Server.address()
This was done to prevent crashes in some popular frameworks like express
Supports both CommonJS and the new ES Modules system syntax e.g:
app.js:
const http = require('http')
app.mjs:
import http from "http"
Usage on Node 14.16.x and higher:
{
"type": "external",
"processes": {"spare": 0},
"working_directory": '/project',
"executable": "/usr/bin/env",
"arguments": [
"node",
"--loader",
"unit-http/require_shim.mjs"
"--require",
"unit-http/require_shim",
"app.js"
]
}
Usage on Node 14.15.x and lower:
{
"type": "external",
"processes": {"spare": 0},
"working_directory": '/project',
"executable": "/usr/bin/env",
"arguments": [
"node",
"--require",
"unit-http/require_shim",
"app.js"
]
}
This commit is contained in:
@@ -31,6 +31,12 @@ NGINX Unit updated to 1.24.0.
|
|||||||
date="" time=""
|
date="" time=""
|
||||||
packager="Andrei Belov <defan@nginx.com>">
|
packager="Andrei Belov <defan@nginx.com>">
|
||||||
|
|
||||||
|
<change type="feature">
|
||||||
|
<para>
|
||||||
|
a shim for automatic overriding "http" and "websocket" modules in Node.js.
|
||||||
|
</para>
|
||||||
|
</change>
|
||||||
|
|
||||||
<change type="feature">
|
<change type="feature">
|
||||||
<para>
|
<para>
|
||||||
ability to limit serving of static files by MIME types.
|
ability to limit serving of static files by MIME types.
|
||||||
|
|||||||
@@ -5,19 +5,22 @@
|
|||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const server = require('unit-http/http_server');
|
const {
|
||||||
|
Server,
|
||||||
const { Server } = server;
|
ServerRequest,
|
||||||
|
ServerResponse,
|
||||||
|
} = require('./http_server');
|
||||||
|
|
||||||
function createServer (requestHandler) {
|
function createServer (requestHandler) {
|
||||||
return new Server(requestHandler);
|
return new Server(requestHandler);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const http = require("http")
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
|
...http,
|
||||||
Server,
|
Server,
|
||||||
STATUS_CODES: server.STATUS_CODES,
|
|
||||||
createServer,
|
createServer,
|
||||||
IncomingMessage: server.ServerRequest,
|
IncomingMessage: ServerRequest,
|
||||||
ServerResponse: server.ServerResponse
|
ServerResponse,
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -444,17 +444,30 @@ Server.prototype.setTimeout = function setTimeout(msecs, callback) {
|
|||||||
Server.prototype.listen = function (...args) {
|
Server.prototype.listen = function (...args) {
|
||||||
this.unit.listen();
|
this.unit.listen();
|
||||||
|
|
||||||
const cb = args.pop();
|
if (typeof args[args.length - 1] === 'function') {
|
||||||
|
this.once('listening', args[args.length - 1]);
|
||||||
if (typeof cb === 'function') {
|
|
||||||
this.once('listening', cb);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
this.emit('listening');
|
/*
|
||||||
|
* Some express.js apps use the returned server object inside the listening
|
||||||
|
* callback, so we timeout the listening event to occur after this function
|
||||||
|
* returns.
|
||||||
|
*/
|
||||||
|
setImmediate(function() {
|
||||||
|
this.emit('listening')
|
||||||
|
}.bind(this))
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Server.prototype.address = function () {
|
||||||
|
return {
|
||||||
|
family: "IPv4",
|
||||||
|
address: "127.0.0.1",
|
||||||
|
port: 80
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Server.prototype.emit_request = function (req, res) {
|
Server.prototype.emit_request = function (req, res) {
|
||||||
if (req._websocket_handshake && this._upgradeListenerCount > 0) {
|
if (req._websocket_handshake && this._upgradeListenerCount > 0) {
|
||||||
this.emit('upgrade', req, req.socket);
|
this.emit('upgrade', req, req.socket);
|
||||||
@@ -530,7 +543,6 @@ function connectionListener(socket) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
STATUS_CODES: http.STATUS_CODES,
|
|
||||||
Server,
|
Server,
|
||||||
ServerResponse,
|
ServerResponse,
|
||||||
ServerRequest,
|
ServerRequest,
|
||||||
|
|||||||
27
src/nodejs/unit-http/require_shim.js
Normal file
27
src/nodejs/unit-http/require_shim.js
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
// can only be ran as part of a --require param on the node process
|
||||||
|
if (module.parent && module.parent.id === "internal/preload") {
|
||||||
|
const { Module } = require("module")
|
||||||
|
|
||||||
|
if (!Module.prototype.require.__unit_shim) {
|
||||||
|
const http = require("./http")
|
||||||
|
const websocket = require("./websocket")
|
||||||
|
|
||||||
|
const original = Module.prototype.require;
|
||||||
|
|
||||||
|
Module.prototype.require = function (id) {
|
||||||
|
switch(id) {
|
||||||
|
case "http":
|
||||||
|
case "unit-http":
|
||||||
|
return http
|
||||||
|
|
||||||
|
case "websocket":
|
||||||
|
case "unit-http/websocket":
|
||||||
|
return websocket
|
||||||
|
}
|
||||||
|
|
||||||
|
return original.apply(this, arguments);
|
||||||
|
}
|
||||||
|
|
||||||
|
Module.prototype.require.__unit_shim = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
18
src/nodejs/unit-http/require_shim.mjs
Normal file
18
src/nodejs/unit-http/require_shim.mjs
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
// must be ran as part of a --loader or --experimental-loader param
|
||||||
|
export async function resolve(specifier, context, defaultResolver) {
|
||||||
|
switch (specifier) {
|
||||||
|
case "websocket":
|
||||||
|
return {
|
||||||
|
url: new URL("./websocket.js", import.meta.url).href,
|
||||||
|
format: "cjs"
|
||||||
|
}
|
||||||
|
|
||||||
|
case "http":
|
||||||
|
return {
|
||||||
|
url: new URL("./http.js", import.meta.url).href,
|
||||||
|
format: "cjs"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return defaultResolver(specifier, context, defaultResolver)
|
||||||
|
}
|
||||||
3
test/node/404/app.js
Executable file → Normal file
3
test/node/404/app.js
Executable file → Normal file
@@ -1,7 +1,6 @@
|
|||||||
#!/usr/bin/env node
|
|
||||||
|
|
||||||
var fs = require('fs');
|
var fs = require('fs');
|
||||||
|
|
||||||
require('unit-http').createServer(function (req, res) {
|
require('http').createServer(function (req, res) {
|
||||||
res.writeHead(404, {}).end(fs.readFileSync('404.html'));
|
res.writeHead(404, {}).end(fs.readFileSync('404.html'));
|
||||||
}).listen(7080);
|
}).listen(7080);
|
||||||
|
|||||||
3
test/node/basic/app.js
Executable file → Normal file
3
test/node/basic/app.js
Executable file → Normal file
@@ -1,6 +1,5 @@
|
|||||||
#!/usr/bin/env node
|
|
||||||
|
|
||||||
require('unit-http').createServer(function (req, res) {
|
require('http').createServer(function (req, res) {
|
||||||
res.writeHead(200, {'Content-Length': 12, 'Content-Type': 'text/plain'})
|
res.writeHead(200, {'Content-Length': 12, 'Content-Type': 'text/plain'})
|
||||||
.end('Hello World\n');
|
.end('Hello World\n');
|
||||||
}).listen(7080);
|
}).listen(7080);
|
||||||
|
|||||||
3
test/node/double_end/app.js
Executable file → Normal file
3
test/node/double_end/app.js
Executable file → Normal file
@@ -1,5 +1,4 @@
|
|||||||
#!/usr/bin/env node
|
|
||||||
|
|
||||||
require('unit-http').createServer(function (req, res) {
|
require('http').createServer(function (req, res) {
|
||||||
res.end().end();
|
res.end().end();
|
||||||
}).listen(7080);
|
}).listen(7080);
|
||||||
|
|||||||
3
test/node/get_header_names/app.js
Executable file → Normal file
3
test/node/get_header_names/app.js
Executable file → Normal file
@@ -1,6 +1,5 @@
|
|||||||
#!/usr/bin/env node
|
|
||||||
|
|
||||||
require('unit-http').createServer(function (req, res) {
|
require('http').createServer(function (req, res) {
|
||||||
res.setHeader('DATE', ['date1', 'date2']);
|
res.setHeader('DATE', ['date1', 'date2']);
|
||||||
res.setHeader('X-Header', 'blah');
|
res.setHeader('X-Header', 'blah');
|
||||||
res.setHeader('X-Names', res.getHeaderNames());
|
res.setHeader('X-Names', res.getHeaderNames());
|
||||||
|
|||||||
3
test/node/get_header_type/app.js
Executable file → Normal file
3
test/node/get_header_type/app.js
Executable file → Normal file
@@ -1,6 +1,5 @@
|
|||||||
#!/usr/bin/env node
|
|
||||||
|
|
||||||
require('unit-http').createServer(function (req, res) {
|
require('http').createServer(function (req, res) {
|
||||||
res.setHeader('X-Number', 100);
|
res.setHeader('X-Number', 100);
|
||||||
res.setHeader('X-Type', typeof(res.getHeader('X-Number')));
|
res.setHeader('X-Type', typeof(res.getHeader('X-Number')));
|
||||||
res.end();
|
res.end();
|
||||||
|
|||||||
3
test/node/get_variables/app.js
Executable file → Normal file
3
test/node/get_variables/app.js
Executable file → Normal file
@@ -1,6 +1,5 @@
|
|||||||
#!/usr/bin/env node
|
|
||||||
|
|
||||||
require('unit-http').createServer(function (req, res) {
|
require('http').createServer(function (req, res) {
|
||||||
let query = require('url').parse(req.url, true).query;
|
let query = require('url').parse(req.url, true).query;
|
||||||
res.setHeader('X-Var-1', query.var1);
|
res.setHeader('X-Var-1', query.var1);
|
||||||
res.setHeader('X-Var-2', query.var2);
|
res.setHeader('X-Var-2', query.var2);
|
||||||
|
|||||||
3
test/node/has_header/app.js
Executable file → Normal file
3
test/node/has_header/app.js
Executable file → Normal file
@@ -1,6 +1,5 @@
|
|||||||
#!/usr/bin/env node
|
|
||||||
|
|
||||||
require('unit-http').createServer(function (req, res) {
|
require('http').createServer(function (req, res) {
|
||||||
res.setHeader('X-Has-Header', res.hasHeader(req.headers['x-header']) + '');
|
res.setHeader('X-Has-Header', res.hasHeader(req.headers['x-header']) + '');
|
||||||
res.end();
|
res.end();
|
||||||
}).listen(7080);
|
}).listen(7080);
|
||||||
|
|||||||
3
test/node/header_name_case/app.js
Executable file → Normal file
3
test/node/header_name_case/app.js
Executable file → Normal file
@@ -1,6 +1,5 @@
|
|||||||
#!/usr/bin/env node
|
|
||||||
|
|
||||||
require('unit-http').createServer(function (req, res) {
|
require('http').createServer(function (req, res) {
|
||||||
res.setHeader('X-Header', '1');
|
res.setHeader('X-Header', '1');
|
||||||
res.setHeader('X-header', '2');
|
res.setHeader('X-header', '2');
|
||||||
res.setHeader('X-HEADER', '3');
|
res.setHeader('X-HEADER', '3');
|
||||||
|
|||||||
3
test/node/header_name_valid/app.js
Executable file → Normal file
3
test/node/header_name_valid/app.js
Executable file → Normal file
@@ -1,6 +1,5 @@
|
|||||||
#!/usr/bin/env node
|
|
||||||
|
|
||||||
require('unit-http').createServer(function (req, res) {
|
require('http').createServer(function (req, res) {
|
||||||
res.writeHead(200, {});
|
res.writeHead(200, {});
|
||||||
res.setHeader('@$', 'test');
|
res.setHeader('@$', 'test');
|
||||||
res.end();
|
res.end();
|
||||||
|
|||||||
3
test/node/header_value_object/app.js
Executable file → Normal file
3
test/node/header_value_object/app.js
Executable file → Normal file
@@ -1,6 +1,5 @@
|
|||||||
#!/usr/bin/env node
|
|
||||||
|
|
||||||
require('unit-http').createServer(function (req, res) {
|
require('http').createServer(function (req, res) {
|
||||||
res.setHeader('X-Header', {});
|
res.setHeader('X-Header', {});
|
||||||
res.end();
|
res.end();
|
||||||
}).listen(7080);
|
}).listen(7080);
|
||||||
|
|||||||
3
test/node/mirror/app.js
Executable file → Normal file
3
test/node/mirror/app.js
Executable file → Normal file
@@ -1,6 +1,5 @@
|
|||||||
#!/usr/bin/env node
|
|
||||||
|
|
||||||
require('unit-http').createServer(function (req, res) {
|
require('http').createServer(function (req, res) {
|
||||||
let body = '';
|
let body = '';
|
||||||
req.on('data', chunk => {
|
req.on('data', chunk => {
|
||||||
body += chunk.toString();
|
body += chunk.toString();
|
||||||
|
|||||||
3
test/node/post_variables/app.js
Executable file → Normal file
3
test/node/post_variables/app.js
Executable file → Normal file
@@ -1,6 +1,5 @@
|
|||||||
#!/usr/bin/env node
|
|
||||||
|
|
||||||
require('unit-http').createServer(function (req, res) {
|
require('http').createServer(function (req, res) {
|
||||||
let body = '';
|
let body = '';
|
||||||
req.on('data', chunk => {
|
req.on('data', chunk => {
|
||||||
body += chunk.toString();
|
body += chunk.toString();
|
||||||
|
|||||||
3
test/node/promise_end/app.js
Executable file → Normal file
3
test/node/promise_end/app.js
Executable file → Normal file
@@ -1,8 +1,7 @@
|
|||||||
#!/usr/bin/env node
|
|
||||||
|
|
||||||
var fs = require('fs');
|
var fs = require('fs');
|
||||||
|
|
||||||
require('unit-http').createServer(function (req, res) {
|
require('http').createServer(function (req, res) {
|
||||||
res.write('blah');
|
res.write('blah');
|
||||||
|
|
||||||
Promise.resolve().then(() => {
|
Promise.resolve().then(() => {
|
||||||
|
|||||||
3
test/node/promise_handler/app.js
Executable file → Normal file
3
test/node/promise_handler/app.js
Executable file → Normal file
@@ -1,8 +1,7 @@
|
|||||||
#!/usr/bin/env node
|
|
||||||
|
|
||||||
var fs = require('fs');
|
var fs = require('fs');
|
||||||
|
|
||||||
require('unit-http').createServer(function (req, res) {
|
require('http').createServer(function (req, res) {
|
||||||
res.end();
|
res.end();
|
||||||
|
|
||||||
if (req.headers['x-write-call']) {
|
if (req.headers['x-write-call']) {
|
||||||
|
|||||||
3
test/node/remove_header/app.js
Executable file → Normal file
3
test/node/remove_header/app.js
Executable file → Normal file
@@ -1,6 +1,5 @@
|
|||||||
#!/usr/bin/env node
|
|
||||||
|
|
||||||
require('unit-http').createServer(function (req, res) {
|
require('http').createServer(function (req, res) {
|
||||||
res.setHeader('X-Header', 'test');
|
res.setHeader('X-Header', 'test');
|
||||||
res.setHeader('Was-Header', res.hasHeader('X-Header').toString());
|
res.setHeader('Was-Header', res.hasHeader('X-Header').toString());
|
||||||
|
|
||||||
|
|||||||
6
test/node/require_shim/es_modules_http/app.mjs
Normal file
6
test/node/require_shim/es_modules_http/app.mjs
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
import http from "http"
|
||||||
|
|
||||||
|
http.createServer(function (req, res) {
|
||||||
|
res.writeHead(200, {'Content-Length': 12, 'Content-Type': 'text/plain'})
|
||||||
|
.end('Hello World\n');
|
||||||
|
}).listen(7080);
|
||||||
1
test/node/require_shim/es_modules_http_indirect/app.js
Normal file
1
test/node/require_shim/es_modules_http_indirect/app.js
Normal file
@@ -0,0 +1 @@
|
|||||||
|
import("./module.mjs")
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
import http from "http"
|
||||||
|
|
||||||
|
http.createServer(function (req, res) {
|
||||||
|
res.writeHead(200, {'Content-Length': 12, 'Content-Type': 'text/plain'})
|
||||||
|
.end('Hello World\n');
|
||||||
|
}).listen(7080);
|
||||||
30
test/node/require_shim/es_modules_websocket/app.mjs
Normal file
30
test/node/require_shim/es_modules_websocket/app.mjs
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
import http from "http"
|
||||||
|
import websocket from "websocket"
|
||||||
|
|
||||||
|
let server = http.createServer(function() {});
|
||||||
|
let webSocketServer = websocket.server;
|
||||||
|
|
||||||
|
server.listen(7080, function() {});
|
||||||
|
|
||||||
|
var wsServer = new webSocketServer({
|
||||||
|
maxReceivedMessageSize: 0x1000000000,
|
||||||
|
maxReceivedFrameSize: 0x1000000000,
|
||||||
|
fragmentOutgoingMessages: false,
|
||||||
|
fragmentationThreshold: 0x1000000000,
|
||||||
|
httpServer: server,
|
||||||
|
});
|
||||||
|
|
||||||
|
wsServer.on('request', function(request) {
|
||||||
|
var connection = request.accept(null);
|
||||||
|
|
||||||
|
connection.on('message', function(message) {
|
||||||
|
if (message.type === 'utf8') {
|
||||||
|
connection.send(message.utf8Data);
|
||||||
|
} else if (message.type === 'binary') {
|
||||||
|
connection.send(message.binaryData);
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
connection.on('close', function(r) {});
|
||||||
|
});
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
import("./module.mjs")
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
import http from "http"
|
||||||
|
import websocket from "websocket"
|
||||||
|
|
||||||
|
let server = http.createServer(function() {});
|
||||||
|
let webSocketServer = websocket.server;
|
||||||
|
|
||||||
|
server.listen(7080, function() {});
|
||||||
|
|
||||||
|
var wsServer = new webSocketServer({
|
||||||
|
maxReceivedMessageSize: 0x1000000000,
|
||||||
|
maxReceivedFrameSize: 0x1000000000,
|
||||||
|
fragmentOutgoingMessages: false,
|
||||||
|
fragmentationThreshold: 0x1000000000,
|
||||||
|
httpServer: server,
|
||||||
|
});
|
||||||
|
|
||||||
|
wsServer.on('request', function(request) {
|
||||||
|
var connection = request.accept(null);
|
||||||
|
|
||||||
|
connection.on('message', function(message) {
|
||||||
|
if (message.type === 'utf8') {
|
||||||
|
connection.send(message.utf8Data);
|
||||||
|
} else if (message.type === 'binary') {
|
||||||
|
connection.send(message.binaryData);
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
connection.on('close', function(r) {});
|
||||||
|
});
|
||||||
1
test/node/require_shim/transitive_dependency/app.js
Normal file
1
test/node/require_shim/transitive_dependency/app.js
Normal file
@@ -0,0 +1 @@
|
|||||||
|
require("./transitive_http")
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
const http = require("http");
|
||||||
|
|
||||||
|
http.createServer(function (req, res) {
|
||||||
|
res.writeHead(200, {'Content-Length': 12, 'Content-Type': 'text/plain'})
|
||||||
|
.end('Hello World\n');
|
||||||
|
}).listen(7080);
|
||||||
|
|
||||||
|
module.exports = http;
|
||||||
4
test/node/require_shim/unit_http/app.js
Normal file
4
test/node/require_shim/unit_http/app.js
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
require("unit-http").createServer(function (req, res) {
|
||||||
|
res.writeHead(200, {'Content-Length': 12, 'Content-Type': 'text/plain'})
|
||||||
|
.end('Hello World\n');
|
||||||
|
}).listen(7080);
|
||||||
3
test/node/set_header_array/app.js
Executable file → Normal file
3
test/node/set_header_array/app.js
Executable file → Normal file
@@ -1,6 +1,5 @@
|
|||||||
#!/usr/bin/env node
|
|
||||||
|
|
||||||
require('unit-http').createServer(function (req, res) {
|
require('http').createServer(function (req, res) {
|
||||||
res.setHeader('Set-Cookie', ['tc=one,two,three', 'tc=four,five,six']);
|
res.setHeader('Set-Cookie', ['tc=one,two,three', 'tc=four,five,six']);
|
||||||
res.end();
|
res.end();
|
||||||
}).listen(7080);
|
}).listen(7080);
|
||||||
|
|||||||
3
test/node/status_message/app.js
Executable file → Normal file
3
test/node/status_message/app.js
Executable file → Normal file
@@ -1,5 +1,4 @@
|
|||||||
#!/usr/bin/env node
|
|
||||||
|
|
||||||
require('unit-http').createServer(function (req, res) {
|
require('http').createServer(function (req, res) {
|
||||||
res.writeHead(200, 'blah', {'Content-Type': 'text/plain'}).end();
|
res.writeHead(200, 'blah', {'Content-Type': 'text/plain'}).end();
|
||||||
}).listen(7080);
|
}).listen(7080);
|
||||||
|
|||||||
3
test/node/update_header/app.js
Executable file → Normal file
3
test/node/update_header/app.js
Executable file → Normal file
@@ -1,6 +1,5 @@
|
|||||||
#!/usr/bin/env node
|
|
||||||
|
|
||||||
require('unit-http').createServer(function (req, res) {
|
require('http').createServer(function (req, res) {
|
||||||
res.setHeader('X-Header', 'test');
|
res.setHeader('X-Header', 'test');
|
||||||
res.setHeader('X-Header', 'new');
|
res.setHeader('X-Header', 'new');
|
||||||
res.end();
|
res.end();
|
||||||
|
|||||||
3
test/node/variables/app.js
Executable file → Normal file
3
test/node/variables/app.js
Executable file → Normal file
@@ -1,6 +1,5 @@
|
|||||||
#!/usr/bin/env node
|
|
||||||
|
|
||||||
require('unit-http').createServer(function (req, res) {
|
require('http').createServer(function (req, res) {
|
||||||
let body = '';
|
let body = '';
|
||||||
req.on('data', chunk => {
|
req.on('data', chunk => {
|
||||||
body += chunk.toString();
|
body += chunk.toString();
|
||||||
|
|||||||
7
test/node/websockets/mirror/app.js
Executable file → Normal file
7
test/node/websockets/mirror/app.js
Executable file → Normal file
@@ -1,9 +1,6 @@
|
|||||||
#!/usr/bin/env node
|
|
||||||
|
|
||||||
server = require('unit-http').createServer(function() {});
|
server = require('http').createServer(function() {});
|
||||||
webSocketServer = require('unit-http/websocket').server;
|
webSocketServer = require('websocket').server;
|
||||||
//server = require('http').createServer(function() {});
|
|
||||||
//webSocketServer = require('websocket').server;
|
|
||||||
|
|
||||||
server.listen(7080, function() {});
|
server.listen(7080, function() {});
|
||||||
|
|
||||||
|
|||||||
7
test/node/websockets/mirror_fragmentation/app.js
Executable file → Normal file
7
test/node/websockets/mirror_fragmentation/app.js
Executable file → Normal file
@@ -1,9 +1,6 @@
|
|||||||
#!/usr/bin/env node
|
|
||||||
|
|
||||||
server = require('unit-http').createServer(function() {});
|
server = require('http').createServer(function() {});
|
||||||
webSocketServer = require('unit-http/websocket').server;
|
webSocketServer = require('websocket').server;
|
||||||
//server = require('http').createServer(function() {});
|
|
||||||
//webSocketServer = require('websocket').server;
|
|
||||||
|
|
||||||
server.listen(7080, function() {});
|
server.listen(7080, function() {});
|
||||||
|
|
||||||
|
|||||||
3
test/node/write_before_write_head/app.js
Executable file → Normal file
3
test/node/write_before_write_head/app.js
Executable file → Normal file
@@ -1,6 +1,5 @@
|
|||||||
#!/usr/bin/env node
|
|
||||||
|
|
||||||
require('unit-http').createServer(function (req, res) {
|
require('http').createServer(function (req, res) {
|
||||||
res.write('blah');
|
res.write('blah');
|
||||||
res.writeHead(200, {'Content-Type': 'text/plain'}).end();
|
res.writeHead(200, {'Content-Type': 'text/plain'}).end();
|
||||||
}).listen(7080);
|
}).listen(7080);
|
||||||
|
|||||||
3
test/node/write_buffer/app.js
Executable file → Normal file
3
test/node/write_buffer/app.js
Executable file → Normal file
@@ -1,6 +1,5 @@
|
|||||||
#!/usr/bin/env node
|
|
||||||
|
|
||||||
require('unit-http').createServer(function (req, res) {
|
require('http').createServer(function (req, res) {
|
||||||
res.writeHead(200, {'Content-Type': 'text/plain'})
|
res.writeHead(200, {'Content-Type': 'text/plain'})
|
||||||
.end(new Buffer([0x62, 0x75, 0x66, 0x66, 0x65, 0x72]));
|
.end(new Buffer([0x62, 0x75, 0x66, 0x66, 0x65, 0x72]));
|
||||||
}).listen(7080);
|
}).listen(7080);
|
||||||
|
|||||||
3
test/node/write_callback/app.js
Executable file → Normal file
3
test/node/write_callback/app.js
Executable file → Normal file
@@ -1,8 +1,7 @@
|
|||||||
#!/usr/bin/env node
|
|
||||||
|
|
||||||
var fs = require('fs');
|
var fs = require('fs');
|
||||||
|
|
||||||
require('unit-http').createServer(function (req, res) {
|
require('http').createServer(function (req, res) {
|
||||||
res.writeHead(200, {'Content-Type': 'text/plain'});
|
res.writeHead(200, {'Content-Type': 'text/plain'});
|
||||||
var a = 'world';
|
var a = 'world';
|
||||||
res.write('hello', 'utf8', function() {
|
res.write('hello', 'utf8', function() {
|
||||||
|
|||||||
3
test/node/write_multiple/app.js
Executable file → Normal file
3
test/node/write_multiple/app.js
Executable file → Normal file
@@ -1,6 +1,5 @@
|
|||||||
#!/usr/bin/env node
|
|
||||||
|
|
||||||
require('unit-http').createServer(function (req, res) {
|
require('http').createServer(function (req, res) {
|
||||||
res.writeHead(200, {'Content-Type': 'text/plain', 'Content-Length': 14});
|
res.writeHead(200, {'Content-Type': 'text/plain', 'Content-Length': 14});
|
||||||
res.write('write');
|
res.write('write');
|
||||||
res.write('write2');
|
res.write('write2');
|
||||||
|
|||||||
3
test/node/write_return/app.js
Executable file → Normal file
3
test/node/write_return/app.js
Executable file → Normal file
@@ -1,6 +1,5 @@
|
|||||||
#!/usr/bin/env node
|
|
||||||
|
|
||||||
require('unit-http').createServer(function (req, res) {
|
require('http').createServer(function (req, res) {
|
||||||
res.writeHead(200, {'Content-Type': 'text/plain'})
|
res.writeHead(200, {'Content-Type': 'text/plain'})
|
||||||
.end(res.write('body').toString());
|
.end(res.write('body').toString());
|
||||||
}).listen(7080);
|
}).listen(7080);
|
||||||
|
|||||||
@@ -9,13 +9,26 @@ from unit.utils import waitforfiles
|
|||||||
class TestNodeApplication(TestApplicationNode):
|
class TestNodeApplication(TestApplicationNode):
|
||||||
prerequisites = {'modules': {'node': 'all'}}
|
prerequisites = {'modules': {'node': 'all'}}
|
||||||
|
|
||||||
def test_node_application_basic(self):
|
def assert_basic_application(self):
|
||||||
self.load('basic')
|
|
||||||
|
|
||||||
resp = self.get()
|
resp = self.get()
|
||||||
assert resp['headers']['Content-Type'] == 'text/plain', 'basic header'
|
assert resp['headers']['Content-Type'] == 'text/plain', 'basic header'
|
||||||
assert resp['body'] == 'Hello World\n', 'basic body'
|
assert resp['body'] == 'Hello World\n', 'basic body'
|
||||||
|
|
||||||
|
def test_node_application_basic(self):
|
||||||
|
self.load('basic')
|
||||||
|
|
||||||
|
self.assert_basic_application()
|
||||||
|
|
||||||
|
def test_node_application_require_shim_unit_http(self):
|
||||||
|
self.load('require_shim/unit_http')
|
||||||
|
|
||||||
|
self.assert_basic_application()
|
||||||
|
|
||||||
|
def test_node_application_require_shim_transitive_dependency(self):
|
||||||
|
self.load('require_shim/transitive_dependency')
|
||||||
|
|
||||||
|
self.assert_basic_application()
|
||||||
|
|
||||||
def test_node_application_seq(self):
|
def test_node_application_seq(self):
|
||||||
self.load('basic')
|
self.load('basic')
|
||||||
|
|
||||||
|
|||||||
50
test/test_node_es_modules.py
Normal file
50
test/test_node_es_modules.py
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
import pytest
|
||||||
|
|
||||||
|
from distutils.version import LooseVersion
|
||||||
|
from unit.applications.lang.node import TestApplicationNode
|
||||||
|
from unit.applications.websockets import TestApplicationWebsocket
|
||||||
|
|
||||||
|
|
||||||
|
class TestNodeESModules(TestApplicationNode):
|
||||||
|
prerequisites = {
|
||||||
|
'modules': {
|
||||||
|
'node': lambda v: LooseVersion(v) >= LooseVersion("14.16.0")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
es_modules = True
|
||||||
|
ws = TestApplicationWebsocket()
|
||||||
|
|
||||||
|
def assert_basic_application(self):
|
||||||
|
resp = self.get()
|
||||||
|
assert resp['headers']['Content-Type'] == 'text/plain', 'basic header'
|
||||||
|
assert resp['body'] == 'Hello World\n', 'basic body'
|
||||||
|
|
||||||
|
def test_node_es_modules_require_shim_http(self):
|
||||||
|
self.load('require_shim/es_modules_http', name="app.mjs")
|
||||||
|
|
||||||
|
self.assert_basic_application()
|
||||||
|
|
||||||
|
def test_node_es_modules_require_shim_http_indirect(self):
|
||||||
|
self.load('require_shim/es_modules_http_indirect', name="app.js")
|
||||||
|
|
||||||
|
self.assert_basic_application()
|
||||||
|
|
||||||
|
def test_node_es_modules_require_shim_websockets(self):
|
||||||
|
self.load('require_shim/es_modules_websocket', name="app.mjs")
|
||||||
|
|
||||||
|
message = 'blah'
|
||||||
|
|
||||||
|
_, sock, _ = self.ws.upgrade()
|
||||||
|
|
||||||
|
self.ws.frame_write(sock, self.ws.OP_TEXT, message)
|
||||||
|
frame = self.ws.frame_read(sock)
|
||||||
|
|
||||||
|
assert message == frame['data'].decode('utf-8'), 'mirror'
|
||||||
|
|
||||||
|
self.ws.frame_write(sock, self.ws.OP_TEXT, message)
|
||||||
|
frame = self.ws.frame_read(sock)
|
||||||
|
|
||||||
|
assert message == frame['data'].decode('utf-8'), 'mirror 2'
|
||||||
|
|
||||||
|
sock.close()
|
||||||
@@ -7,15 +7,16 @@ from unit.utils import public_dir
|
|||||||
|
|
||||||
|
|
||||||
class TestApplicationNode(TestApplicationProto):
|
class TestApplicationNode(TestApplicationProto):
|
||||||
|
application_type = "node"
|
||||||
|
es_modules = False
|
||||||
|
|
||||||
def prepare_env(self, script):
|
def prepare_env(self, script):
|
||||||
# copy application
|
# copy application
|
||||||
|
|
||||||
shutil.copytree(
|
shutil.copytree(
|
||||||
option.test_dir + '/node/' + script, option.temp_dir + '/node'
|
option.test_dir + '/node/' + script, option.temp_dir + '/node'
|
||||||
)
|
)
|
||||||
|
|
||||||
# copy modules
|
# copy modules
|
||||||
|
|
||||||
shutil.copytree(
|
shutil.copytree(
|
||||||
option.current_dir + '/node/node_modules',
|
option.current_dir + '/node/node_modules',
|
||||||
option.temp_dir + '/node/node_modules',
|
option.temp_dir + '/node/node_modules',
|
||||||
@@ -26,6 +27,19 @@ class TestApplicationNode(TestApplicationProto):
|
|||||||
def load(self, script, name='app.js', **kwargs):
|
def load(self, script, name='app.js', **kwargs):
|
||||||
self.prepare_env(script)
|
self.prepare_env(script)
|
||||||
|
|
||||||
|
if self.es_modules:
|
||||||
|
arguments = [
|
||||||
|
"node",
|
||||||
|
"--loader",
|
||||||
|
"unit-http/require_shim.mjs",
|
||||||
|
"--require",
|
||||||
|
"unit-http/require_shim",
|
||||||
|
name,
|
||||||
|
]
|
||||||
|
|
||||||
|
else:
|
||||||
|
arguments = ["node", "--require", "unit-http/require_shim", name]
|
||||||
|
|
||||||
self._load_conf(
|
self._load_conf(
|
||||||
{
|
{
|
||||||
"listeners": {
|
"listeners": {
|
||||||
@@ -36,7 +50,8 @@ class TestApplicationNode(TestApplicationProto):
|
|||||||
"type": "external",
|
"type": "external",
|
||||||
"processes": {"spare": 0},
|
"processes": {"spare": 0},
|
||||||
"working_directory": option.temp_dir + '/node',
|
"working_directory": option.temp_dir + '/node',
|
||||||
"executable": name,
|
"executable": '/usr/bin/env',
|
||||||
|
"arguments": arguments,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1,6 +1,15 @@
|
|||||||
import os
|
import os
|
||||||
|
import subprocess
|
||||||
|
|
||||||
|
|
||||||
def check_node(current_dir):
|
def check_node(current_dir):
|
||||||
if os.path.exists(current_dir + '/node/node_modules'):
|
if not os.path.exists(current_dir + '/node/node_modules'):
|
||||||
return True
|
return None
|
||||||
|
|
||||||
|
try:
|
||||||
|
v_bytes = subprocess.check_output(['/usr/bin/env', 'node', '-v'])
|
||||||
|
|
||||||
|
return [str(v_bytes, 'utf-8').lstrip('v').rstrip()]
|
||||||
|
|
||||||
|
except subprocess.CalledProcessError:
|
||||||
|
return None
|
||||||
|
|||||||
Reference in New Issue
Block a user