@mikkel-ol/tunnelmole
Version:
Tunnelmole, an open source ngrok alternative. Instant public URLs for any http/https based application. Available as a command line application or as an NPM dependency for your code. Stable and maintained. Good test coverage. Works behind firewalls
77 lines (67 loc) • 2.31 kB
text/typescript
import HostipWebSocket from "../websocket/host-ip-websocket.js";
import ForwardedRequestMessage from "../messages/forwarded-request-message.js";
import http from "http";
import ForwardedResponseMessage from "../messages/forwarded-response-message.js";
import { forwardedResponse } from "../messages/types.js";
import log from "../logging/log.js";
import { Options } from "../options.js";
export default async function forwardedRequest(
forwardedRequestMessage: ForwardedRequestMessage,
websocket: HostipWebSocket,
options: Options,
) {
const port = options.port;
const { requestId, url, headers } = forwardedRequestMessage;
// @todo: Once GET is working, add support for all HTTP methods
const requestOptions: http.RequestOptions = {
hostname: "localhost",
method: forwardedRequestMessage.method,
port: port,
path: url,
headers,
};
const request = http.request(
requestOptions,
(response: http.IncomingMessage) => {
let responseBody: Buffer;
response.on("data", (chunk: Buffer) => {
if (typeof responseBody === "undefined") {
responseBody = chunk;
} else {
responseBody = Buffer.concat([responseBody, chunk]);
}
});
/**
* If you see this callback being called more than once, this is probably normal especially if a browser initiated the request
* Most browsers will make more than one request, for example an extra one for favicon.ico
*/
response.on("end", () => {
//@ts-ignore
const forwardedResponseMessage: ForwardedResponseMessage = {
type: forwardedResponse,
requestId,
statusCode: response.statusCode,
url,
headers: response.headers,
body: "",
};
if (Buffer.isBuffer(responseBody)) {
forwardedResponseMessage.body = responseBody.toString("base64");
}
websocket.sendMessage(forwardedResponseMessage);
});
},
);
// Send the request body if its not empty
if (forwardedRequestMessage.body !== "") {
const requestBody: Buffer = Buffer.from(
forwardedRequestMessage.body,
"base64",
);
request.write(requestBody);
}
request.on("error", (error: any) => {
log(error);
});
request.end();
}