diff --git a/package.json b/package.json index df075d1..1dc68e1 100644 --- a/package.json +++ b/package.json @@ -17,7 +17,7 @@ "dev": "nodemon -e ts -w ./src -x pnpm run watch -z ./contracts -p 3000", "watch": "node --loader ts-node/esm src/index.ts", "test": "pnpm e2e && jest", - "start": "node --loader ts-node/esm src/index.ts -z ./tests/fixtures -p 3000", + "start": "node --loader ts-node/esm src/index.ts -z ./tests/fixtures -p 3000 --public-directory ./public", "e2e": "start-server-and-test http-get://0.0.0.0:3000 'pnpm stepci run ./tests/workflow.stepci.yml'" }, "engines": { diff --git a/public/.hello_world.keys.json b/public/.hello_world.keys.json new file mode 100644 index 0000000..798d2d8 --- /dev/null +++ b/public/.hello_world.keys.json @@ -0,0 +1,3 @@ +{ + "check_for_query_param": "hello" +} \ No newline at end of file diff --git a/public/.hello_world.slang b/public/.hello_world.slang new file mode 100644 index 0000000..13d9a95 --- /dev/null +++ b/public/.hello_world.slang @@ -0,0 +1,6 @@ +Given I have a 'string' named 'query_param' +and I have a 'string' named 'check_for_query_param' + +When I verify 'query_param' is equal to 'check_for_query_param' + +Then print the data \ No newline at end of file diff --git a/public/hello_world b/public/hello_world new file mode 100644 index 0000000..6d32cfd --- /dev/null +++ b/public/hello_world @@ -0,0 +1,8 @@ + + + Benvenuto + + +
Hello World!
+ + \ No newline at end of file diff --git a/public/hello_world.metadata.json b/public/hello_world.metadata.json new file mode 100644 index 0000000..c801b8d --- /dev/null +++ b/public/hello_world.metadata.json @@ -0,0 +1,4 @@ +{ + "contentType": "text/html", + "precondition": ".hello_world" +} \ No newline at end of file diff --git a/src/index.ts b/src/index.ts index cf95452..becb5ee 100644 --- a/src/index.ts +++ b/src/index.ts @@ -26,7 +26,7 @@ import { openapiTemplate } from './openapi.js'; import { SlangroomManager } from './slangroom.js'; -import { getSchema, validateData } from './utils.js'; +import { getSchema, validateData, getQueryParams } from './utils.js'; import { readFileContent, readJsonObject } from './fileUtils.js'; import { execute as slangroomChainExecute } from '@dyne/slangroom-chain'; dotenv.config(); @@ -148,6 +148,14 @@ Then print the 'result' return app; }; +const runPrecondition = async (preconditionPath: string, data: Record) => { + const s = SlangroomManager.getInstance(); + const zen = fs.readFileSync(preconditionPath+".slang").toString(); + const keys = fs.existsSync(preconditionPath+".keys.json") ? + JSON.parse(fs.readFileSync(preconditionPath+".keys.json")) : null; + await s.execute(zen, {data, keys}); +}; + Dir.ready(async () => { let listen_socket: us_listen_socket; @@ -159,10 +167,32 @@ Dir.ready(async () => { const { publicDirectory } = config; if (publicDirectory) { - app.get('/*', (res, req) => { + app.get('/*', async (res, req) => { + if (req.getUrl().replace(/^\/+/g, '/').startsWith('/.')) return res.writeStatus('404 Not Found').end('Not found'); let file = path.join(publicDirectory, req.getUrl()); if (fs.existsSync(file)) { - const contentType = mime.getType(file) || 'application/json'; + let contentType = mime.getType(file) || 'application/json'; + if(fs.existsSync(file+'.metadata.json')) { + let publicMetadata + try { + publicMetadata = JSON.parse(fs.readFileSync(file+'.metadata.json')); + } catch (e) { + L.fatal(e); + res.writeStatus('422 UNPROCESSABLE ENTITY').end('Malformed metadata file'); + return; + } + if(publicMetadata.contentType) contentType = publicMetadata.contentType + if(publicMetadata.precondition) { + try{ + const data: Record = getQueryParams(req); + await runPrecondition(path.join(publicDirectory, publicMetadata.precondition), data); + } catch(e) { + L.fatal(e); + res.writeStatus('403 FORBIDDEN').end() + return; + } + } + } res.writeHeader('Access-Control-Allow-Origin', '*') .writeHeader('Content-Type', contentType); res.end(fs.readFileSync(file)); @@ -263,11 +293,8 @@ const generateRoutes = (app: TemplatedApp) => { } } if (metadata.precondition) { - const zen = await readFileContent(metadata.precondition+".slang"); - const keys = fs.existsSync(metadata.precondition+".keys.json") ? - await readJsonObject(metadata.precondition+".keys.json") : null; try { - await s.execute(zen, {data, keys}); + await runPrecondition(metadata.precondition, data); } catch (e) { LOG.fatal(e); res.writeStatus('403 FORBIDDEN').end((e as Error).message) @@ -411,14 +438,7 @@ const generateRoutes = (app: TemplatedApp) => { }); try { - const data: Record = {}; - const q = req.getQuery(); - if (q) { - q.split('&').map((r) => { - const [k, v] = r.split('='); - data[k] = v; - }); - } + const data: Record = getQueryParams(req); execZencodeAndReply(res, data, headers); } catch (e) { LOG.fatal(e); diff --git a/src/utils.ts b/src/utils.ts index 14e5f3b..8a69c99 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -135,3 +135,15 @@ function createAjv(): Ajv { addFormats.default(ajv); return ajv; } + +export const getQueryParams = (req): Record => { + const data: Record = {}; + const q = req.getQuery(); + if (q) { + q.split('&').map((r) => { + const [k, v] = r.split('='); + data[k] = v; + }); + } + return data; +} \ No newline at end of file diff --git a/tests/workflow.stepci.yml b/tests/workflow.stepci.yml index fbebad1..07af30f 100644 --- a/tests/workflow.stepci.yml +++ b/tests/workflow.stepci.yml @@ -89,7 +89,7 @@ tests: method: GET check: status: 404 - body:

File Not Found


uWebSockets/20 Server + body: Not found broken: steps: @@ -382,3 +382,23 @@ tests: status: 200 json: say_hi: hello + + public_dir: + steps: + - name: public with wrong precondition + http: + url: http://${{env.host}}/hello_world?query_param=wrong_param + method: GET + check: + status: 403 + - name: public with right precondition + http: + url: http://${{env.host}}/hello_world?query_param=hello + method: GET + check: + status: 200 + selctors: + title: Benvenuto + body: Hello World! + headers: + Content-Type: text/html \ No newline at end of file