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