@webda/aws
Version:
Webda AWS Services implementation
417 lines • 16.4 kB
JavaScript
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
import { suite, test } from "@testdeck/mocha";
import { Bean, getCommonJS, HttpContext, Route, Service, WebdaError } from "@webda/core";
import { TestApplication } from "@webda/core/lib/test.js";
import * as assert from "assert";
import * as fs from "fs";
import { checkLocalStack, WebdaAwsTest } from "../index.spec.js";
import { LambdaServer } from "./lambdaserver.js";
const { __dirname } = getCommonJS(import.meta.url);
let ExceptionExecutor = class ExceptionExecutor extends Service {
initRoutes() {
super.initRoutes();
this.addRoute("/broken/{type}", ["GET"], this._brokenRoute);
this.addRoute("/route/string", ["GET"], this.onString);
}
async _brokenRoute(ctx) {
if (ctx.parameters.type === "unauthorized") {
throw new WebdaError.Unauthorized("OnPurpose");
}
else if (ctx.parameters.type === "401") {
throw 401;
}
else if (ctx.parameters.type === "Error") {
throw new Error();
}
}
async onString(ctx) {
ctx.write(`CodeCoverage${ctx.getParameters().test || ""}`);
}
async onParamString(ctx) {
ctx.write(`CodeCoverage${ctx.getParameters().uuid}${ctx.getParameters().test || ""}`);
}
};
__decorate([
Route("/route/broken/{type}")
], ExceptionExecutor.prototype, "_brokenRoute", null);
__decorate([
Route("/route/string{?test}")
], ExceptionExecutor.prototype, "onString", null);
__decorate([
Route("/route/param/{uuid}{?test?}")
], ExceptionExecutor.prototype, "onParamString", null);
ExceptionExecutor = __decorate([
Bean
], ExceptionExecutor);
let LambdaHandlerTest = class LambdaHandlerTest extends WebdaAwsTest {
constructor() {
super(...arguments);
this.context = {};
this.badCheck = false;
}
async before() {
await checkLocalStack();
let app = new TestApplication(this.getTestConfiguration());
app.addService("Test/AWSEvents", (await import("../../test/moddas/awsevents.js")).AWSEventsHandler);
await app.load();
this.webda = this.handler = new LambdaServer(app);
await this.webda.init();
this.webda.registerRequestFilter({
checkRequest: async () => true
});
this.evt = {
httpMethod: "GET",
headers: {
Cookie: "webda=plop;",
"X-Forwarded-Port": "443",
"X-Forwarded-Proto": "https"
},
requestContext: {
identity: {}
},
path: "/prefix/route/string",
resource: "/route/string",
body: JSON.stringify({})
};
this.debugMailer = this.handler.getService("DebugMailer");
}
async checkRequestNoRequestFilter() {
await this.handler.init();
// @ts-ignore
this.handler._requestFilters = [];
this.ensureGoodCSRF();
this.evt.queryStringParameters = { test: "Plop" };
let res = await this.handler.handleRequest(this.evt, this.context);
// No filter return ok now
assert.strictEqual(res.statusCode, 200);
}
async checkRequestRefusedRequest() {
await this.handler.init();
// @ts-ignore
this.handler._requestFilters = [];
this.ensureGoodCSRF();
this.evt.queryStringParameters = { test: "Plop" };
this.handler.registerRequestFilter({
checkRequest: async () => false
});
let res = await this.handler.handleRequest(this.evt, this.context);
assert.strictEqual(res.statusCode, 403);
}
async checkRequestRedirect() {
await this.handler.init();
// @ts-ignore
this.handler._requestFilters = [];
this.ensureGoodCSRF();
this.evt.queryStringParameters = { test: "Plop" };
this.handler.registerRequestFilter({
checkRequest: async () => {
throw new WebdaError.Redirect("Need Auth", "https://google.com");
}
});
let res = await this.handler.handleRequest(this.evt, this.context);
assert.strictEqual(res.statusCode, 302);
console.log(res);
assert.strictEqual(res.headers.Location, "https://google.com");
}
async handleRequestCustomLaunch() {
await this.handler.handleRequest({
command: "launch",
service: "DebugMailer",
method: "send",
args: ["test"]
}, undefined);
assert.strictEqual(this.debugMailer.sent[0], "test");
}
async handleRequestCustomLaunchBadService() {
await this.handler.handleRequest({
command: "launch",
service: "DebugMailers",
method: "send",
args: ["test"]
}, undefined);
assert.strictEqual(this.debugMailer.sent.length, 0);
}
async handleRequestCustomLaunchBadMethod() {
await this.handler.handleRequest({
command: "launch",
service: "DebugMailer",
method: "sends"
}, undefined);
assert.strictEqual(this.debugMailer.sent.length, 0);
}
async handleRequestKnownRoute() {
this.ensureGoodCSRF();
let res = await this.handler.handleRequest(this.evt, this.context);
assert.strictEqual(res.body, "CodeCoverage");
}
async handleRequestIdHeader() {
this.ensureGoodCSRF();
this.handler.getConfiguration().parameters.lambdaRequestHeader = "x-webda-request-id";
let res = await this.handler.handleRequest(this.evt, {
...this.context,
awsRequestId: "toto"
});
assert.strictEqual(res.body, "CodeCoverage");
assert.strictEqual(res.headers["x-webda-request-id"], "toto");
}
async handleRequestKnownRouteWithParamAndQuery() {
this.ensureGoodCSRF();
this.evt.queryStringParameters = { test: "Plop" };
this.evt.path = "/prefix/route/param/myid";
this.evt.resource = "/route/param/{uuid}";
this.evt.pathParameters = { uuid: "myid" };
let res = await this.handler.handleRequest(this.evt, this.context);
assert.strictEqual(res.body, "CodeCoveragemyidPlop");
}
async handleRequestKnownRouteWithParam() {
this.ensureGoodCSRF();
this.evt.path = "/prefix/route/param/myid";
this.evt.resource = "/route/param/{uuid}";
this.evt.pathParameters = { uuid: "myid" };
let res = await this.handler.handleRequest(this.evt, this.context);
assert.strictEqual(res.body, "CodeCoveragemyid");
}
async handleRequestKnownRouteWithQuery() {
this.ensureGoodCSRF();
this.evt.queryStringParameters = { test: "Plop" };
let res = await this.handler.handleRequest(this.evt, this.context);
assert.strictEqual(res.body, "CodeCoveragePlop");
}
async handleRequestUnknownRoute() {
this.ensureGoodCSRF();
this.evt.path = "/route/unknown";
this.evt.resource = "/route/unknown";
delete this.evt.headers.Cookie;
let res = await this.handler.handleRequest(this.evt, this.context);
assert.strictEqual(res.statusCode, 404);
}
async handleRequestThrow401() {
this.ensureGoodCSRF();
this.evt.path = "/route/broken/401";
this.evt.resource = "/route/broken/401";
let res = await this.handler.handleRequest(this.evt, this.context);
assert.strictEqual(res.statusCode, 401);
this.evt.path = "/route/broken/unauthorized";
this.evt.resource = "/route/broken/unauthorized";
res = await this.handler.handleRequest(this.evt, this.context);
assert.strictEqual(res.statusCode, 401);
}
async handleRequestThrowError() {
this.ensureGoodCSRF();
this.evt.path = "/route/broken/Error";
let res = await this.handler.handleRequest(this.evt, this.context);
assert.strictEqual(res.statusCode, 500);
}
async handleRequestOPTIONS() {
this.ensureGoodCSRF();
this.evt.httpMethod = "OPTIONS";
let res = await this.handler.handleRequest(this.evt, this.context);
assert.strictEqual(res.statusCode, 204);
assert.strictEqual(res.headers["Access-Control-Allow-Methods"], "GET,OPTIONS");
}
async handleRequestOPTIONSWith404() {
this.ensureGoodCSRF();
this.evt.path = "/route/unknown";
this.evt.httpMethod = "OPTIONS";
let res = await this.handler.handleRequest(this.evt, this.context);
assert.strictEqual(res.statusCode, 404);
}
async cov() {
this.ensureGoodCSRF();
this.evt.headers["X-Forwarded-Port"] = "wew";
this.evt.headers["Content-Type"] = "text/plain";
this.evt.body = "{wew''";
// Should fallback on port 443
await this.handler.handleRequest(this.evt, this.context);
}
async handleRequestQueryParams() {
// TODO Check parameter retrieval
this.evt.queryStringParameters = {
test: "plop"
};
this.evt.headers.Origin = "https://test.webda.io";
this.evt.headers.Host = "test.webda.io";
await this.handler.handleRequest(this.evt, this.context);
}
async handleRequestOrigin() {
this.evt.headers.Origin = "https://test.webda.io";
this.evt.headers.Host = "test.webda.io";
let wait = false;
this.handler.on("Webda.Result", () => {
return new Promise((resolve, reject) => {
// Delay 100ms to ensure it waited
setTimeout(() => {
wait = true;
resolve();
}, 100);
});
});
let res = await this.handler.handleRequest(this.evt, this.context);
assert.strictEqual(res.headers["Access-Control-Allow-Origin"], this.evt.headers.Origin);
assert.strictEqual(wait, true);
}
async handleRequestOriginCSRF() {
this.evt.headers.Origin = "https://test3.webda.io";
this.evt.headers.Host = "test3.webda.io";
let res = await this.handler.handleRequest(this.evt, this.context);
assert.strictEqual(res.statusCode, 401);
}
async handleRequestRefererCSRF() {
this.evt.headers.Referer = "https://test3.webda.io";
this.evt.headers.Host = "test3.webda.io";
this.evt.headers.origin = "test3.webda.io";
let res = await this.handler.handleRequest(this.evt, this.context);
assert.strictEqual(res.statusCode, 401);
}
async handleRequestRefererNoCORS() {
// No more fallback on referer for CORS
// BUt request should be served as no CORS is requested (lack of Origin)
this.evt.headers.Referer = "https://test.webda.io";
this.evt.headers.Host = "test.webda.io";
let res = await this.handler.handleRequest(this.evt, this.context);
assert.strictEqual(res.headers["Access-Control-Allow-Origin"], undefined);
assert.strictEqual(res.statusCode, 200);
}
async handleRequestHardStopCheckRequest() {
this.evt.headers.Referer = "https://test.webda.io";
this.evt.headers.Host = "test.webda.io";
this.handler.registerRequestFilter(this);
let res = await this.handler.handleRequest(this.evt, this.context);
assert.strictEqual(res.statusCode, 410);
this.badCheck = true;
res = await this.handler.handleRequest(this.evt, this.context);
assert.strictEqual(res.statusCode, 500);
this.newExcept = true;
res = await this.handler.handleRequest(this.evt, this.context);
assert.strictEqual(res.statusCode, 429);
}
async checkRequest() {
if (this.newExcept) {
throw new WebdaError.TooManyRequests("Too many requests");
}
if (this.badCheck) {
throw new Error("Unknown");
}
throw 410;
}
ensureGoodCSRF() {
this.evt.headers.Origin = "https://test.webda.io";
this.evt.headers.Host = "test.webda.io";
}
async awsEvents() {
let service = this.handler.getService("awsEvents");
let files = fs.readdirSync(__dirname + "/../../test/aws-events");
for (let f in files) {
let file = files[f];
let event = JSON.parse(fs.readFileSync(__dirname + "/../../test/aws-events/" + file).toString());
await this.handler.handleRequest(event, this.context);
if (file === "api-gateway-aws-proxy.json") {
assert.strictEqual(service.getEvents().length, 0, "API Gateway should go through the normal request handling");
}
else {
assert.notStrictEqual(service.getEvents().length, 0, "Should have get some events:" + JSON.stringify(event));
}
}
}
/**
* Wildcard path from API Gateway were missing the prefix
*
* @see https://github.com/loopingz/webda.io/issues/193
*/
async computePrefix() {
let httpContext = new HttpContext("test.webda.io", "GET", "/prefix/static1234/test/subfolder/index.html");
this.handler.computePrefix({
path: "/prefix/static1234/test/subfolder/index.html",
resource: "/static1234/{path+}",
pathParameters: {
path: "test/subfolder/index.html"
}
}, httpContext);
assert.strictEqual(httpContext.getRelativeUri(), "/static1234/test/subfolder/index.html");
assert.strictEqual(httpContext.prefix, "/prefix");
}
};
__decorate([
test
], LambdaHandlerTest.prototype, "checkRequestNoRequestFilter", null);
__decorate([
test
], LambdaHandlerTest.prototype, "checkRequestRefusedRequest", null);
__decorate([
test
], LambdaHandlerTest.prototype, "checkRequestRedirect", null);
__decorate([
test
], LambdaHandlerTest.prototype, "handleRequestCustomLaunch", null);
__decorate([
test
], LambdaHandlerTest.prototype, "handleRequestCustomLaunchBadService", null);
__decorate([
test
], LambdaHandlerTest.prototype, "handleRequestCustomLaunchBadMethod", null);
__decorate([
test
], LambdaHandlerTest.prototype, "handleRequestKnownRoute", null);
__decorate([
test
], LambdaHandlerTest.prototype, "handleRequestIdHeader", null);
__decorate([
test
], LambdaHandlerTest.prototype, "handleRequestKnownRouteWithParamAndQuery", null);
__decorate([
test
], LambdaHandlerTest.prototype, "handleRequestKnownRouteWithParam", null);
__decorate([
test
], LambdaHandlerTest.prototype, "handleRequestKnownRouteWithQuery", null);
__decorate([
test
], LambdaHandlerTest.prototype, "handleRequestUnknownRoute", null);
__decorate([
test
], LambdaHandlerTest.prototype, "handleRequestThrow401", null);
__decorate([
test
], LambdaHandlerTest.prototype, "handleRequestThrowError", null);
__decorate([
test
], LambdaHandlerTest.prototype, "handleRequestOPTIONS", null);
__decorate([
test
], LambdaHandlerTest.prototype, "handleRequestOPTIONSWith404", null);
__decorate([
test
], LambdaHandlerTest.prototype, "cov", null);
__decorate([
test
], LambdaHandlerTest.prototype, "handleRequestQueryParams", null);
__decorate([
test
], LambdaHandlerTest.prototype, "handleRequestOrigin", null);
__decorate([
test
], LambdaHandlerTest.prototype, "handleRequestOriginCSRF", null);
__decorate([
test
], LambdaHandlerTest.prototype, "handleRequestRefererCSRF", null);
__decorate([
test
], LambdaHandlerTest.prototype, "handleRequestRefererNoCORS", null);
__decorate([
test
], LambdaHandlerTest.prototype, "handleRequestHardStopCheckRequest", null);
__decorate([
test
], LambdaHandlerTest.prototype, "awsEvents", null);
__decorate([
test
], LambdaHandlerTest.prototype, "computePrefix", null);
LambdaHandlerTest = __decorate([
suite
], LambdaHandlerTest);
//# sourceMappingURL=lambdaserver.spec.js.map