Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

added two parameters: only-get-or-head and check-index #16

Merged
merged 13 commits into from
Sep 21, 2022
12 changes: 11 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -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`
Expand All @@ -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:
Expand Down Expand Up @@ -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",
Expand Down
10 changes: 10 additions & 0 deletions action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
22 changes: 16 additions & 6 deletions main.js
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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 = '.';
Expand All @@ -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 = {
Expand All @@ -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 });
Expand Down
84 changes: 50 additions & 34 deletions server.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ const path = require('path');
const process = require('process');
const fs = require('fs');


function deploy(config, ready) {
const server = http.createServer();

Expand All @@ -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 = {};
}
Expand All @@ -26,7 +31,6 @@ function deploy(config, ready) {
cwd += path.sep;
}


function toPosixPath(url) {
return path.posix.join(...url.split(path.sep));
}
Expand All @@ -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;
Expand All @@ -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('<pre>\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(`<a href="${parentLink}">..</a>\n`);
}

for (const file of fs.readdirSync(requestedFile)) {
const fullPath = requestedFile + file;
response.write(`<a href="/${toPosixPath(fullPath.slice(cwd.length))}">${file}</a>\n`);
}
response.write('</pre>');
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('<pre>\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(`<a href="${parentLink}">..</a>\n`);
}

for (const file of fs.readdirSync(requestedFile)) {
const fullPath = requestedFile + file;
response.write(`<a href="/${toPosixPath(fullPath.slice(cwd.length))}">${file}</a>\n`);
}
response.write('</pre>');
response.end();
return;
}
}

const contentType = path.extname(requestedFile).slice(1);
Expand All @@ -118,5 +135,4 @@ function deploy(config, ready) {
});
}


exports.deploy = deploy;