Skip to content

Commit 7232110

Browse files
authored
feat: non existent domain support (#17)
* chore: added support for async onError handlers in proxy * feat: added support for header and response modification when dns resolution fails
1 parent 815f4cf commit 7232110

File tree

5 files changed

+63
-18
lines changed

5 files changed

+63
-18
lines changed

src/components/proxy-middleware/helpers/proxy_ctx_helper.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ export const get_original_request_headers = (ctx) => {
2020

2121
export const get_original_response_headers = (ctx) => {
2222
// TODO: This needs to be fetched from ctx.clientToProxy headers
23-
return ctx.serverToProxyResponse.headers;
23+
return ctx?.serverToProxyResponse?.headers || {};
2424
};
2525

2626
export const is_request_preflight = (ctx) => {

src/components/proxy-middleware/index.js

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,39 @@ class ProxyMiddlewareManager {
132132
this.rulesHelper
133133
);
134134

135+
ctx.onError(async function (ctx, err, kind, callback) {
136+
// Should only modify response body & headers
137+
ctx.rq_response_body = "" + kind + ": " + err, "utf8";
138+
const { action_result_objs, continue_request } = await rules_middleware.on_response(ctx);
139+
140+
// Only modify response if any modify_response action is applied
141+
const modifyResponseActionExist = action_result_objs.some((action_result_obj) => action_result_obj?.action?.action === "modify_response")
142+
143+
if(modifyResponseActionExist) {
144+
const statusCode = ctx.rq_response_status_code || 404;
145+
const responseHeaders = getResponseHeaders(ctx) || {}
146+
ctx.proxyToClientResponse.writeHead(
147+
statusCode,
148+
http.STATUS_CODES[statusCode],
149+
responseHeaders
150+
);
151+
ctx.proxyToClientResponse.end(ctx.rq_response_body);
152+
153+
ctx.rq.set_final_response({
154+
status_code: statusCode,
155+
headers: responseHeaders,
156+
body: ctx.rq_response_body,
157+
});
158+
logger_middleware.send_network_log(
159+
ctx,
160+
rules_middleware.action_result_objs,
161+
GLOBAL_CONSTANTS.REQUEST_STATE.COMPLETE
162+
)
163+
}
164+
165+
return callback();
166+
})
167+
135168
let request_body_chunks = [];
136169
ctx.onRequestData(async function (ctx, chunk, callback) {
137170
if (chunk) {

src/components/proxy-middleware/rule_action_processor/processors/modify_header_processor.js

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ const process_modify_header_action = (action, ctx) => {
66
const allowed_handlers = [
77
PROXY_HANDLER_TYPE.ON_REQUEST,
88
PROXY_HANDLER_TYPE.ON_RESPONSE,
9+
PROXY_HANDLER_TYPE.ON_ERROR,
910
];
1011

1112
if (!allowed_handlers.includes(ctx.currentHandler)) {
@@ -14,7 +15,7 @@ const process_modify_header_action = (action, ctx) => {
1415

1516
if (ctx.currentHandler == PROXY_HANDLER_TYPE.ON_REQUEST) {
1617
modify_request_headers(action, ctx);
17-
} else if (ctx.currentHandler == PROXY_HANDLER_TYPE.ON_RESPONSE) {
18+
} else if (ctx.currentHandler === PROXY_HANDLER_TYPE.ON_RESPONSE || ctx.currentHandler === PROXY_HANDLER_TYPE.ON_ERROR) {
1819
modify_response_headers(action, ctx);
1920
}
2021
return build_action_processor_response(action, true);
@@ -35,6 +36,8 @@ const modify_request_headers = (action, ctx) => {
3536
};
3637

3738
const modify_response_headers = (action, ctx) => {
39+
ctx.serverToProxyResponse = ctx.serverToProxyResponse || {}
40+
ctx.serverToProxyResponse.headers = ctx.serverToProxyResponse.headers || {}
3841
// {"header1":"val1", "header2":"val2"}
3942
const originalResponseHeadersObject = ctx.serverToProxyResponse.headers;
4043
// ["header1","header2"]

src/components/proxy-middleware/rule_action_processor/processors/modify_response_processor.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ import { getFunctionFromString } from "../../../../utils";
1313
const { types } = require("util");
1414

1515
const process_modify_response_action = async (action, ctx) => {
16-
const allowed_handlers = [PROXY_HANDLER_TYPE.ON_RESPONSE_END];
16+
const allowed_handlers = [PROXY_HANDLER_TYPE.ON_RESPONSE_END, PROXY_HANDLER_TYPE.ON_ERROR];
1717

1818
if (!allowed_handlers.includes(ctx.currentHandler)) {
1919
return build_action_processor_response(action, false);
@@ -82,9 +82,9 @@ const modify_response_using_code = async (action, ctx) => {
8282
? ctx.clientToProxyRequest.method
8383
: null
8484
: null,
85-
response: ctx.rq_response_body,
85+
response: ctx?.rq_response_body,
8686
url: get_request_url(ctx),
87-
responseType: ctx.serverToProxyResponse.headers["content-type"],
87+
responseType: ctx?.serverToProxyResponse?.headers?.["content-type"],
8888
requestHeaders: ctx.clientToProxyRequest.headers,
8989
requestData: parseJsonBody(ctx.rq?.final_request?.body) || null,
9090
};

src/lib/proxy/lib/proxy.ts

Lines changed: 22 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ const PROXY_HANDLER_TYPE = {
5555
ON_RESPONSE_HEADERS: "ON_RESPONSE_HEADERS",
5656
ON_RESPONSE_DATA: "ON_RESPONSE_DATA",
5757
ON_RESPONSE_END: "ON_RESPONSE_END",
58+
ON_ERROR: "ON_ERROR",
5859
};
5960

6061
module.exports.PROXY_HANDLER_TYPE = PROXY_HANDLER_TYPE;
@@ -635,21 +636,29 @@ Proxy.prototype.onCertificateMissing = function (ctx, files, callback) {
635636
};
636637

637638
Proxy.prototype._onError = function (kind, ctx, err) {
638-
this.onErrorHandlers.forEach(function (handler) {
639-
return handler(ctx, err, kind);
640-
});
641-
if (ctx) {
642-
ctx.onErrorHandlers.forEach(function (handler) {
643-
return handler(ctx, err, kind);
644-
});
639+
if(ctx) {
640+
ctx.currentHandler = PROXY_HANDLER_TYPE.ON_ERROR;
641+
}
645642

646-
if (ctx.proxyToClientResponse && !ctx.proxyToClientResponse.headersSent) {
647-
ctx.proxyToClientResponse.writeHead(504, "Proxy Error");
648-
}
649-
if (ctx.proxyToClientResponse && !ctx.proxyToClientResponse.finished) {
650-
ctx.proxyToClientResponse.end("" + kind + ": " + err, "utf8");
643+
async.forEach(
644+
this.onErrorHandlers.concat(ctx?.onErrorHandlers || []),
645+
function (fn, callback) {
646+
if (fn) {
647+
return fn(ctx, err, kind, callback);
648+
}
649+
callback();
650+
},
651+
function() {
652+
if(ctx) {
653+
if (ctx.proxyToClientResponse && !ctx.proxyToClientResponse.headersSent) {
654+
ctx.proxyToClientResponse.writeHead(504, "Proxy Error");
655+
}
656+
if (ctx.proxyToClientResponse && !ctx.proxyToClientResponse.finished) {
657+
ctx.proxyToClientResponse.end("" + kind + ": " + err, "utf8");
658+
}
659+
}
651660
}
652-
}
661+
);
653662
};
654663

655664
Proxy.prototype._onWebSocketServerConnect = function (isSSL, ws, upgradeReq) {

0 commit comments

Comments
 (0)