diff --git a/README.md b/README.md index bc6828c..3a47327 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # http-server-action --- -An action that spawns an http server to serve files. +An action that spawns an http server to serve files. ## Inputs ### `directory` @@ -12,6 +12,12 @@ Port that should be used (default is `8080`) (*optional*) ### `no-cache` No-Cache determiantes wheter the server sets the Cache-Control header or not (default is `false`) (*optional*) +### `index-files` +If set and directory is requested, look for those files, instead of show directory listing (default is EMPTY, sample is `["index.html", "index.htm"]`) (*optional*) + +### `allowed-methods` +Throw HTTP-Error 405 on other methods than the methods given (default is `["GET", "HEAD"]`) (*optional*) + ### `content-types` A JSON object of content-types that should be served (*optional*) Default: @@ -45,6 +51,10 @@ steps: directory: ${{ github.workspace }} port: 8080 no-cache: false + index-files: | + ["index.html", "index.htm"] + allowed-methods: | + ["GET", "HEAD"] content-types: | { "appcache": "text/cache-manifest", diff --git a/action.yml b/action.yml index 7bd7797..4bfabb8 100644 --- a/action.yml +++ b/action.yml @@ -18,6 +18,16 @@ inputs: description: 'Whether to set the Cache-Control header or not' required: false default: false + index-files: + description: 'If set and directory is requested, look for those files, instead of show directory listing' + required: false + default: | + [] + allowed-methods: + description: 'Throw HTTP-Error 405 on other methods than the methods given' + required: false + default: | + ["GET", "HEAD"] content-types: description: 'Content Types to serve' required: false diff --git a/main.js b/main.js index 8db8ff6..d8e94ee 100644 --- a/main.js +++ b/main.js @@ -2,7 +2,6 @@ const process = require('process'); const core = require('@actions/core'); const server = require('./server.js'); - if (process.argv.length === 3 && process.argv[2] === 'serve') { process.on('SIGTERM', () => { process.exit(0); @@ -27,16 +26,15 @@ if (process.argv.length === 3 && process.argv[2] === 'serve') { return; } - - let config = { root: null, port: null, noCache: null, - contentTypes: null, + indexFiles: null, + allowedMethods: null, + contentTypes: null }; - config.root = core.getInput('directory'); if (config.root === null || config.root.length == 0) { config.root = '.'; @@ -61,6 +59,13 @@ if (config.noCache === null || config.noCache.length == 0) { config.noCache = config.noCache === 'true'; } +config.indexFiles = core.getInput('index-files'); +if (config.indexFiles === null || config.indexFiles.length == 0) { + config.indexFiles = []; +} else { + config.indexFiles = JSON.parse(config.indexFiles); +} + config.contentTypes = core.getInput('content-types'); if (config.contentTypes === null || config.contentTypes.length == 0) { config.contentTypes = { @@ -81,7 +86,12 @@ if (config.contentTypes === null || config.contentTypes.length == 0) { config.contentTypes = JSON.parse(config.contentTypes); } - +config.allowedMethods = core.getInput('allowed-methods'); +if (config.allowedMethods === null || config.allowedMethods.length == 0) { + config.allowedMethods = ['GET', 'HEAD']; +} else { + config.allowedMethods = JSON.parse(config.allowedMethods); +} const cp = require('child_process'); const child = cp.fork(__filename, ['serve'], { detached: true, silent: true }); diff --git a/server.js b/server.js index 4889da2..e77051c 100644 --- a/server.js +++ b/server.js @@ -3,7 +3,6 @@ const path = require('path'); const process = require('process'); const fs = require('fs'); - function deploy(config, ready) { const server = http.createServer(); @@ -16,6 +15,12 @@ function deploy(config, ready) { if (config.noCache === undefined || config.noCache === null) { config.noCache = false; } + if (config.indexFiles === undefined || config.indexFiles === null) { + config.indexFiles = []; + } + if (config.allowedMethods === undefined || config.allowedMethods === null) { + config.allowedMethods = ['GET', 'HEAD']; + } if (config.contentTypes === undefined || config.contentTypes === null || config.contentTypes.length == 0) { config.contentTypes = {}; } @@ -26,7 +31,6 @@ function deploy(config, ready) { cwd += path.sep; } - function toPosixPath(url) { return path.posix.join(...url.split(path.sep)); } @@ -39,7 +43,7 @@ function deploy(config, ready) { ); } - if (request.method !== 'GET' && request.method !== 'HEAD') { + if (!config.allowedMethods.includes(request.method)) { response.writeHead(405, 'Method Not Allowed'); response.end(); return; @@ -60,38 +64,51 @@ function deploy(config, ready) { } } - const stat = fs.statSync(requestedFile); + let stat = fs.statSync(requestedFile); if (stat.isDirectory()) { - if (!requestedFile.endsWith(path.sep)) { - requestedFile += path.sep; - } - response.writeHead(200, 'OK', { 'Content-Type': 'text/html' }); - if (request.method === 'HEAD') { - response.end(); - return; - } - response.write('
\n');
-
-            let parentDir = path.resolve(path.normalize(path.join(requestedFile, '..')));
-            if (!parentDir.endsWith(path.sep)) {
-                parentDir += path.sep;
-            }
-            if (parentDir.startsWith(cwd)) {
-                let parentLink = '/' + toPosixPath(parentDir.slice(cwd.length));
-                if (parentLink === '/.') {
-                    parentLink = '/';
-                }
-                response.write(`..\n`);
-            }
-
-            for (const file of fs.readdirSync(requestedFile)) {
-                const fullPath = requestedFile + file;
-                response.write(`${file}\n`);
-            }
-            response.write('
'); - response.end(); - return; + if (!requestedFile.endsWith(path.sep)) { + requestedFile += path.sep; + } + const noIndexFound = config.indexFiles.every(elem => { + const indexFile = requestedFile + elem; + if(fs.existsSync(indexFile)){ + requestedFile = indexFile; + stat = fs.statSync(requestedFile); + return false; + } + return true; + }); + + if(noIndexFound) { + response.writeHead(200, 'OK', { 'Content-Type': 'text/html' }); + + if (request.method === 'HEAD') { + response.end(); + return; + } + response.write('
\n');
+
+		let parentDir = path.resolve(path.normalize(path.join(requestedFile, '..')));
+		if (!parentDir.endsWith(path.sep)) {
+			parentDir += path.sep;
+		}
+		if (parentDir.startsWith(cwd)) {
+			let parentLink = '/' + toPosixPath(parentDir.slice(cwd.length));
+			if (parentLink === '/.') {
+				parentLink = '/';
+			}
+			response.write(`..\n`);
+		}
+
+		for (const file of fs.readdirSync(requestedFile)) {
+			const fullPath = requestedFile + file;
+			response.write(`${file}\n`);
+		}
+		response.write('
'); + response.end(); + return; + } } const contentType = path.extname(requestedFile).slice(1); @@ -118,5 +135,4 @@ function deploy(config, ready) { }); } - exports.deploy = deploy; \ No newline at end of file