@authx/http-proxy-client
Advanced tools
Comparing version 1.0.0-beta.5 to 1.0.0-beta.6
@@ -115,2 +115,9 @@ /// <reference types="node" /> | ||
} | ||
export interface Metadata { | ||
request: IncomingMessage; | ||
response: ServerResponse; | ||
rule: undefined | Rule; | ||
behavior: undefined | Behavior; | ||
message: string; | ||
} | ||
export default class AuthXClientProxy extends EventEmitter { | ||
@@ -117,0 +124,0 @@ private readonly _config; |
@@ -20,3 +20,3 @@ "use strict"; | ||
return crypto_1.createHash("sha1") | ||
.update(scopes.join(" ")) | ||
.update([...scopes].sort().join(" ")) | ||
.digest("base64") | ||
@@ -33,6 +33,17 @@ .replace(/\+/g, "-") | ||
this._callback = async (request, response) => { | ||
const meta = { | ||
request: request, | ||
response: response, | ||
rule: undefined, | ||
behavior: undefined, | ||
message: "Request received." | ||
}; | ||
// Emit meta on request start. | ||
this.emit("request.start", meta); | ||
// Emit meta again on request finish. | ||
response.on("finish", () => { | ||
this.emit("request.finish", meta); | ||
}); | ||
const cookies = new cookies_1.default(request, response); | ||
function send(data) { | ||
// TODO: this shouldn't need to be cast through any | ||
// https://github.com/DefinitelyTyped/DefinitelyTyped/pull/34898 | ||
if (request.complete) { | ||
@@ -46,3 +57,3 @@ response.end(data); | ||
} | ||
const forward = (options) => { | ||
const forward = (options, rule, behavior) => { | ||
// Merge `set-cookie` header values with those set by the proxy. | ||
@@ -73,2 +84,5 @@ const setHeader = response.setHeader; | ||
} | ||
meta.message = "Request proxied."; | ||
meta.rule = rule; | ||
meta.behavior = behavior; | ||
this._proxy.web(request, response, options); | ||
@@ -80,4 +94,6 @@ }; | ||
response.statusCode = 503; | ||
meta.message = "Request handled by readiness endpoint: NOT READY."; | ||
return send("NOT READY"); | ||
} | ||
meta.message = "Request handled by readiness endpoint: READY."; | ||
response.statusCode = 200; | ||
@@ -96,2 +112,4 @@ return send("READY"); | ||
response.statusCode = 400; | ||
meta.message = | ||
"Request handled by client endpoint: display oauth errors."; | ||
return send(` | ||
@@ -117,2 +135,4 @@ <html> | ||
response.statusCode = 400; | ||
meta.message = | ||
"Request handled by client endpoint: display missing code error."; | ||
return send(` | ||
@@ -130,2 +150,5 @@ <html> | ||
method: "POST", | ||
headers: { | ||
"Content-Type": "application/json" | ||
}, | ||
body: JSON.stringify({ | ||
@@ -139,6 +162,3 @@ /* eslint-disable @typescript-eslint/camelcase */ | ||
/* eslint-enable @typescript-eslint/camelcase */ | ||
}), | ||
headers: { | ||
"Content-Type": "application/json" | ||
} | ||
}) | ||
}); | ||
@@ -165,7 +185,11 @@ if (tokenResponse.status !== 200) { | ||
cookies.set("authx.d"); | ||
meta.message = | ||
"Request handled by client endpoint: redirect after successful auth."; | ||
return send(); | ||
} | ||
catch (error) { | ||
console.error(error); | ||
this.emit("error", error); | ||
response.statusCode = 500; | ||
meta.message = | ||
"Request handled by client endpoint: display fetch error."; | ||
return send(` | ||
@@ -190,5 +214,7 @@ <html> | ||
: rule.behavior; | ||
// If behavior is `void`, then the custom function will handle responding | ||
// If behavior is `undefined`, then the custom function will handle responding | ||
// to the request. | ||
if (!behavior) { | ||
meta.message = "Request handled by custom behavior function."; | ||
meta.rule = rule; | ||
return; | ||
@@ -198,3 +224,3 @@ } | ||
if (!behavior.sendTokenToTargetWithScopes) { | ||
forward(behavior.proxyOptions); | ||
forward(behavior.proxyOptions, rule, behavior); | ||
return; | ||
@@ -216,3 +242,3 @@ } | ||
request.headers.authorization = `Bearer ${token}`; | ||
forward(behavior.proxyOptions); | ||
forward(behavior.proxyOptions, rule, behavior); | ||
return; | ||
@@ -222,3 +248,3 @@ } | ||
catch (error) { | ||
console.error(error); | ||
this.emit("error", error); | ||
} | ||
@@ -259,3 +285,3 @@ const refreshToken = cookies.get("authx.r"); | ||
request.headers.authorization = `Bearer ${refreshResponseBody.access_token}`; | ||
forward(behavior.proxyOptions); | ||
forward(behavior.proxyOptions, rule, behavior); | ||
return; | ||
@@ -265,3 +291,3 @@ } | ||
catch (error) { | ||
console.error(error); | ||
this.emit("error", error); | ||
} | ||
@@ -286,7 +312,11 @@ } | ||
response.statusCode = behavior.sendAuthorizationResponseAs || 303; | ||
meta.message = "Restricting access."; | ||
meta.rule = rule; | ||
meta.behavior = behavior; | ||
return send(); | ||
} | ||
console.warn(`No rules matched requested URL "${request.url}".`); | ||
this.emit("error", new Error(`No rules matched requested URL "${request.url}".`)); | ||
meta.message = "No rules matched requested URL."; | ||
response.statusCode = 404; | ||
response.end(); | ||
send(); | ||
}; | ||
@@ -293,0 +323,0 @@ this._config = config; |
@@ -52,4 +52,4 @@ { | ||
"lint": "prettier -c '**/*.{json,yml,md,ts}' && eslint src --ext ts", | ||
"prepare": "rm -rf dist && tsc", | ||
"prepare:development": "rm -rf dist && tsc --watch", | ||
"build": "rm -rf dist && tsc", | ||
"build:development": "rm -rf dist && tsc --watch", | ||
"test": "ava --verbose dist/*.test.js", | ||
@@ -59,3 +59,3 @@ "test:development": "ava --verbose dist/*.test.js --watch" | ||
"types": "./dist/index.d.ts", | ||
"version": "1.0.0-beta.5" | ||
"version": "1.0.0-beta.6" | ||
} |
@@ -147,8 +147,16 @@ import { createHash, randomBytes } from "crypto"; | ||
export interface Metadata { | ||
request: IncomingMessage; | ||
response: ServerResponse; | ||
rule: undefined | Rule; | ||
behavior: undefined | Behavior; | ||
message: string; | ||
} | ||
// We need a small key to identify this tokey that is safe for use as a cookie | ||
// key. We'll use a modified version of base64, as described by: | ||
// https://tools.ietf.org/html/rfc4648 | ||
function hashScopes(scopes: string[]): string { | ||
function hashScopes(scopes: ReadonlyArray<string>): string { | ||
return createHash("sha1") | ||
.update(scopes.join(" ")) | ||
.update([...scopes].sort().join(" ")) | ||
.digest("base64") | ||
@@ -186,8 +194,22 @@ .replace(/\+/g, "-") | ||
): Promise<void> => { | ||
const meta: Metadata = { | ||
request: request, | ||
response: response, | ||
rule: undefined, | ||
behavior: undefined, | ||
message: "Request received." | ||
}; | ||
// Emit meta on request start. | ||
this.emit("request.start", meta); | ||
// Emit meta again on request finish. | ||
response.on("finish", () => { | ||
this.emit("request.finish", meta); | ||
}); | ||
const cookies = new Cookies(request, response); | ||
function send(data?: string): void { | ||
// TODO: this shouldn't need to be cast through any | ||
// https://github.com/DefinitelyTyped/DefinitelyTyped/pull/34898 | ||
if ((request as any).complete) { | ||
if (request.complete) { | ||
response.end(data); | ||
@@ -200,5 +222,8 @@ } else { | ||
const forward = (options: ServerOptions): void => { | ||
const forward = ( | ||
options: ServerOptions, | ||
rule: Rule, | ||
behavior: Behavior | ||
): void => { | ||
// Merge `set-cookie` header values with those set by the proxy. | ||
const setHeader = response.setHeader; | ||
@@ -231,2 +256,5 @@ response.setHeader = function(name, value) { | ||
meta.message = "Request proxied."; | ||
meta.rule = rule; | ||
meta.behavior = behavior; | ||
this._proxy.web(request, response, options); | ||
@@ -239,5 +267,7 @@ }; | ||
response.statusCode = 503; | ||
meta.message = "Request handled by readiness endpoint: NOT READY."; | ||
return send("NOT READY"); | ||
} | ||
meta.message = "Request handled by readiness endpoint: READY."; | ||
response.statusCode = 200; | ||
@@ -261,2 +291,4 @@ return send("READY"); | ||
response.statusCode = 400; | ||
meta.message = | ||
"Request handled by client endpoint: display oauth errors."; | ||
return send(` | ||
@@ -287,2 +319,4 @@ <html> | ||
response.statusCode = 400; | ||
meta.message = | ||
"Request handled by client endpoint: display missing code error."; | ||
return send(` | ||
@@ -301,2 +335,5 @@ <html> | ||
method: "POST", | ||
headers: { | ||
"Content-Type": "application/json" | ||
}, | ||
body: JSON.stringify({ | ||
@@ -310,6 +347,3 @@ /* eslint-disable @typescript-eslint/camelcase */ | ||
/* eslint-enable @typescript-eslint/camelcase */ | ||
}), | ||
headers: { | ||
"Content-Type": "application/json" | ||
} | ||
}) | ||
}); | ||
@@ -349,6 +383,10 @@ | ||
meta.message = | ||
"Request handled by client endpoint: redirect after successful auth."; | ||
return send(); | ||
} catch (error) { | ||
console.error(error); | ||
this.emit("error", error); | ||
response.statusCode = 500; | ||
meta.message = | ||
"Request handled by client endpoint: display fetch error."; | ||
return send(` | ||
@@ -377,5 +415,7 @@ <html> | ||
// If behavior is `void`, then the custom function will handle responding | ||
// If behavior is `undefined`, then the custom function will handle responding | ||
// to the request. | ||
if (!behavior) { | ||
meta.message = "Request handled by custom behavior function."; | ||
meta.rule = rule; | ||
return; | ||
@@ -386,3 +426,3 @@ } | ||
if (!behavior.sendTokenToTargetWithScopes) { | ||
forward(behavior.proxyOptions); | ||
forward(behavior.proxyOptions, rule, behavior); | ||
return; | ||
@@ -409,7 +449,7 @@ } | ||
request.headers.authorization = `Bearer ${token}`; | ||
forward(behavior.proxyOptions); | ||
forward(behavior.proxyOptions, rule, behavior); | ||
return; | ||
} | ||
} catch (error) { | ||
console.error(error); | ||
this.emit("error", error); | ||
} | ||
@@ -464,7 +504,7 @@ | ||
forward(behavior.proxyOptions); | ||
forward(behavior.proxyOptions, rule, behavior); | ||
return; | ||
} | ||
} catch (error) { | ||
console.error(error); | ||
this.emit("error", error); | ||
} | ||
@@ -496,9 +536,16 @@ } | ||
response.statusCode = behavior.sendAuthorizationResponseAs || 303; | ||
meta.message = "Restricting access."; | ||
meta.rule = rule; | ||
meta.behavior = behavior; | ||
return send(); | ||
} | ||
console.warn(`No rules matched requested URL "${request.url}".`); | ||
this.emit( | ||
"error", | ||
new Error(`No rules matched requested URL "${request.url}".`) | ||
); | ||
meta.message = "No rules matched requested URL."; | ||
response.statusCode = 404; | ||
response.end(); | ||
send(); | ||
}; | ||
@@ -505,0 +552,0 @@ |
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
304051
7051