sandbox node core http module in a service worker.
this is part of a security focused research project I am currently working on. as it usually goes for security software, this can be used for good or evil. this can also harm your computer or browser and cause you inconvenience. I do not take any responsibility for any damages caused by this software. proceed at your own risk. absolutely no warranty is provided. you may brick your browser if you do not know how to use this library properly.
if you are new, it is not all hopeless. make sure you understand the intricacies of service workers and its security implications before using this library.
in building progressive web apps and performing client side testing and caching, it is immensely helpful to have something like express or socket.io available in order to reuse packages on npm made for various http interaction needs.
using this library in a bundler allows reuse of applications made for node.js in terms of interaction with the core http module.
creating the http server this way does not involve a network adapter and is thus accessible where environment is restricted. sending requests in browsers is also local and does not involve any network adapter (including loopback).
this library is designed to be used in a bundler like webpack. fakettp is a drop in replacement for node's http module. two requirements should be met to use it in a bundler successfully:
- alias
http
tofakettp
in your bundler config. - provide fallbacks for anything else that your code may use from node core.
example webpack config:
npm install fakettp --save-dev
module.exports = {
resolve: {
plugins: [
new webpack.ProvidePlugin({
process: "process/browser",
Buffer: ["buffer", "Buffer"],
URL: ["url", "URL"],
}),
],
fallback: {
http: require.resolve("fakettp"),
util: require.resolve("util/"),
events: require.resolve("events/"),
buffer: require.resolve("buffer/"),
assert: require.resolve("assert/"),
stream: require.resolve("stream-browserify"),
}
},
};
you can use configuration of this repository as reference.
check out the examples that are known to work in samples folder and the webpack config for this repository.
you can create a server and listen like so:
const server = FAKETTP.createServer().on("request", (req, res) => {
req.on('data', (chunk) => {
console.log(`Received ${chunk.length} bytes of data in request body.`);
console.log(`Request chunk: ${chunk.toString()}`);
});
req.on('end', () => {
console.log('No more data in request body.');
});
res.writeHead(200, { 'Content-Type': 'text/plain' });
res.end('{"yo":"nice"}');
}).listen(443, "google.com");
after that all requests will be intercepted and handled by the service worker.
the host and port to watch for can be configured by passing options to listen
.
you can for example send a request to the server like so:
async function postData(data = {}, url = "https://google.com/fake.html") {
const response = await fetch(url, {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(data),
});
return response.json();
}
postData({ answer: "browser" }).then((data) => {
console.log(data);
});
you can also close the server like so:
server.close();
and if you attempt to send a request after that, you will get an error:
npm test
to run tests.npm run build
to build the project.npm run serve
to start webpack dev server.npm run watch
to watch for changes and rebuild.npx http-serve --cors dist
to run production build.
working samples:
ext/samples/express.ts
: express app with a dynamic route.ext/samples/express-post.ts
: express app with a post route.ext/samples/express-static.ts
: express app with static files.ext/samples/socket-io.ts
: express app with socket io.ext/samples/remote-context
: shows the usage offakettp.html
.
this is what is known to work good enough for most use cases:
http.createServer([options][, requestListener])
one instance per sessionhttp.METHODS
through stream-httphttp.STATUS_CODES
through stream-httphttp.get(options[, callback])
through stream-httphttp.get(url[, options][, callback])
through stream-httphttp.request(options[, callback])
through stream-httphttp.request(url[, options][, callback])
through stream-http- class:
http.ClientRequest
through stream-http - class:
http.Server
- event:
'close'
- event:
'connection'
- event:
'request'
server.close([callback])
server.listen()
server.listen(port[, host][, callback])
server.listening
- event:
- class:
http.ServerResponse
- event:
'close'
- event:
'finish'
response.end([data][, encoding][, callback])
response.finished
response.getHeader(name)
response.getHeaderNames()
response.getHeaders()
response.hasHeader(name)
response.headersSent
response.removeHeader(name)
response.setHeader(name, value)
response.socket
response.statusCode
response.statusMessage
response.write(chunk[, encoding][, callback])
response.writeHead(statusCode[, statusMessage][, headers])
- event:
- class:
http.IncomingMessage
- event:
'close'
message.complete
message.destroy([error])
message.headers
message.httpVersion
message.method
message.rawHeaders
message.socket
message.statusCode
message.statusMessage
message.url
message.connection
- event:
- class:
net.Socket
- event:
'close'
- event:
'data'
- event:
'drain'
- event:
'end'
- event:
'error'
socket.address()
socket.remoteAddress
socket.remoteFamily
socket.remotePort
socket.bufferSize
socket.bytesRead
socket.bytesWritten
socket.destroy([exception])
socket.destroyed
socket.end([data][, encoding][, callback])
socket.write(data[, encoding][, callback])
- event:
- fakettp cannot be hosted on a cdn and must be served from the same origin.
- fakettp works best in chromium based browsers due to support discrepancies.
- fakettp only works in secure contexts and localhost for development purposes.
- fakettp does not support history navigations that result in crossing origins.
- fakettp listening on root domain is not advised due to history complications.
- fakettp can currently have only one instance active and listening at a time.