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

Build for release, auto-updater, website #65

Merged
merged 88 commits into from
May 17, 2022
Merged
Show file tree
Hide file tree
Changes from 71 commits
Commits
Show all changes
88 commits
Select commit Hold shift + click to select a range
96b38f4
Update build.js
terreng Feb 5, 2022
ec91462
Versions URL
terreng Feb 5, 2022
38c375c
Update banner
terreng Feb 5, 2022
680c0c3
Create 404.html
terreng Feb 5, 2022
fbbebf1
Update versions.json
terreng Feb 5, 2022
eeac1b8
Update check
terreng Feb 6, 2022
65536cc
Update check
terreng Feb 6, 2022
36733dc
Only show Stop & Quit button when Keep running when closed option is …
terreng Feb 10, 2022
341832b
Custom update banner text
terreng Feb 12, 2022
c5f0901
Add option to display update banner with high priority color
terreng Feb 12, 2022
96a0999
update build platforms
terreng Feb 19, 2022
251df84
Merge from main
terreng Mar 22, 2022
21f1b0f
Start working on VuePress static docs site
terreng Mar 22, 2022
88c3ac4
Add versions generate script to vue docs site
terreng Mar 22, 2022
425f9d1
Move to www
terreng Mar 22, 2022
54e0ffc
Revert "Move to www"
terreng Mar 22, 2022
081fa80
Update .gitignore
terreng Mar 22, 2022
4019961
Move to www
terreng Mar 22, 2022
e94f311
Move to www
terreng Mar 22, 2022
8233340
Remove template files
terreng Mar 22, 2022
05edcea
Fix build
terreng Mar 22, 2022
c94a46d
Update .gitignore
terreng Mar 22, 2022
6390818
Remove old site files
terreng Mar 22, 2022
cf3d4d1
Fixes
terreng Mar 22, 2022
4a4c034
App Settings
terreng Mar 22, 2022
9177639
Remove old docs
terreng Mar 22, 2022
b5fa7c7
Add guides
terreng Mar 22, 2022
6370daa
Add TODOS for home and download pages
terreng Mar 22, 2022
1ba2b1e
Update config.js
terreng Mar 22, 2022
a24339c
Update config.js
terreng Mar 23, 2022
48631a3
Merge branch 'main' into new-ui
terreng Mar 27, 2022
478f669
Update UI when IP(s) change
terreng Apr 1, 2022
d6b3c0d
Add HTTP compression option
terreng Apr 1, 2022
398311a
Remove compression option from UI
terreng Apr 1, 2022
d0ecf0e
Show an error when formatting error in config.json, instead of resett…
terreng Apr 1, 2022
8e04dd4
Remove compression option from docs
terreng Apr 1, 2022
02fa115
Update open_source_licenses.txt
terreng Apr 4, 2022
9023d48
Add favicon
terreng Apr 4, 2022
53264dd
Update build.js
terreng Apr 4, 2022
aa48b84
Favicon
terreng Apr 4, 2022
8797c28
add keywords meta tag
terreng Apr 4, 2022
2f5a601
Homepage features and footer
terreng Apr 4, 2022
7eaad2b
Add coming from wsc guide
terreng Apr 4, 2022
75352dc
Merge branch 'main' into new-ui
terreng Apr 5, 2022
0d810d4
Add ipv6 option
terreng Apr 5, 2022
fdd193a
Update wsc.md
terreng Apr 5, 2022
61f7782
indexOf -> includes
terreng Apr 6, 2022
a45f439
Merge branch 'main' into new-ui
terreng Apr 13, 2022
29cf606
Homepage
terreng Apr 16, 2022
a6e9c12
Update README.md
terreng Apr 17, 2022
cf58346
Update options docs
terreng Apr 17, 2022
b2da54a
Merge branch 'new-ui' of https://github.com/terreng/simple-web-server…
terreng Apr 17, 2022
f8636ec
Fixes
terreng Apr 19, 2022
beef3d9
fixes
ethanaobrien Apr 20, 2022
388ff25
fix url encoding
ethanaobrien Apr 21, 2022
85b30c7
Add config.json docs
terreng Apr 21, 2022
c7d1b93
Using HTTPS docs
terreng Apr 21, 2022
ed835c9
Catch errors with https create server
terreng Apr 21, 2022
6958a61
Update https.md
terreng May 11, 2022
dfde8e4
fix
Apr 28, 2022
696ab53
undo testing layout
ethanaobrien Apr 28, 2022
e5ea155
Add help page
terreng May 11, 2022
f7f6d71
finish coming from wsc page
terreng May 11, 2022
5fb19e0
Add Windows firewall prompt screenshot
terreng May 12, 2022
6970854
Add date and time to log messages
terreng May 12, 2022
1ec87c0
Add logs guide, add example config file, reorganize
terreng May 12, 2022
5cf7034
Add IPV6 option to docs
terreng May 12, 2022
6a8a917
Add option to enable logging, default to disabled, update docs
terreng May 12, 2022
ee684f4
Fix local logging on macOS
terreng May 12, 2022
beddd82
Apply b2a0e1e
terreng May 12, 2022
fb20243
Switch to electron-builder, www -> website
terreng May 13, 2022
8142881
Update package.json
terreng May 13, 2022
c9bc56c
Update WSC.js
terreng May 13, 2022
72f4074
Update package.json
terreng May 13, 2022
0b26612
Add Linux build
terreng May 13, 2022
3b3fb61
Update package.json
terreng May 13, 2022
673dd62
Update package.json
terreng May 13, 2022
a494934
Update index.js
terreng May 13, 2022
d415119
Update package.json
terreng May 13, 2022
2e3108d
Update README.md
terreng May 13, 2022
9f7629c
Update download instructions, add build from source instructions
terreng May 16, 2022
ca254cc
add download page and portable make commands
terreng May 17, 2022
14aee2a
Update package.json
terreng May 17, 2022
38f3e9d
update check: install source dependent links
terreng May 17, 2022
f423660
Update open_source_licenses.txt
terreng May 17, 2022
ebc0143
Update package.json
terreng May 17, 2022
dd737c3
Update package.json
terreng May 17, 2022
399b511
Update package.json
terreng May 17, 2022
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file removed .DS_Store
Binary file not shown.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,6 @@ images/.DS_Store
.DS_Store
www/docs
www/out
www/src/.vuepress/dist
dev/
dist/
30 changes: 6 additions & 24 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,33 +1,15 @@
# Simple Web Server

A super simple web server app for Windows and macOS, built using Electron and [send](https://www.npmjs.com/package/send).
[Download](https://simplewebserver.org/download/) • [Documentation](https://simplewebserver.org/docs/options.html) • [Build from source](https://simplewebserver.org/docs/build.html)

Inspired by [Web Server for Chrome](https://github.com/kzahel/web-server-chrome), which is going away.
Create local web servers in just a few clicks with an easy to use interface. Built with Electron.

Features:
- Easy to customize
- Run multiple web servers at the same time
- Supports Single Page Applications
- You can keep it running in the background
- Can run in the background

<img width="280" alt="Screen Shot 2021-07-13 at 8 21 25 PM" src="https://user-images.githubusercontent.com/11605395/125558961-d7d99d4e-8db0-44eb-832f-aba540e24c22.png">
![screenshots](https://user-images.githubusercontent.com/11605395/163694811-46e3b79c-a187-4c78-b622-6250a6d5d9d0.jpeg)

## Intallation

Download the archive for your platform here: https://github.com/terreng/web-server/releases

#### Windows
1. Extract the ZIP file somewhere (I recommend making a new folder for it at `C:\Program Files`)
2. Create a shortcut of `Simple Web Server.exe` or pin it to your taskbar

#### macOS
1. Extract the archive
2. Move `Simple Web Server.app` to your applications folder

## Building from this repository

Make sure you have git installed.
Run `npm install`.

To run: `npm start`

To package it up: `npm run make`
Simple Web Server is a continuation of [Web Server for Chrome](https://github.com/kzahel/web-server-chrome).
14 changes: 4 additions & 10 deletions WSC.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,16 +20,10 @@ WSC.DirectoryEntryHandler = handlers.DirectoryEntryHandler
WSC.BaseHandler = handlers.BaseHandler

var main_fs = new WSC.FileSystem(__dirname)
main_fs.getByPath('/directory-listing-template.html', function(file) {
file.text(function(data) {
WSC.template_data = data
})
})
main_fs.getByPath('/directory-listing-template-static.html', function(file) {
file.text(function(data) {
WSC.static_template_data = data
})
})
const fs = require('fs')
const path = require('path')
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the path and fs libraries are defined on global (see index.js)

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch, thanks!

WSC.template_data = fs.readFileSync(path.resolve(__dirname, "directory-listing-template.html"), "utf8");
WSC.static_template_data = fs.readFileSync(path.resolve(__dirname, "directory-listing-template-static.html"), "utf8");

module.exports = WSC;

Expand Down
30 changes: 26 additions & 4 deletions WSC/FileSystem.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@

function getByPath(path, callback, FileSystem) {
if (!path) {
if (typeof path == 'string') {
path = '/';
} else {
return null;
}
}
this.fs = FileSystem;
if (! (path.startsWith('/') || path.startsWith('\\'))) {
var path = '/' + path;
Expand All @@ -12,6 +19,9 @@ function getByPath(path, callback, FileSystem) {

getByPath.prototype = {
getFile: function() {
if (!this.path) {
return null;
}
var path = this.path
this.hidden = function(path) {
var a = path.split('/');
Expand All @@ -21,15 +31,15 @@ getByPath.prototype = {
}
}
return false;
}(path)
}(path);
try {
var stats = fs.statSync(path);
} catch(e) {
var error = e;
}
if (error) {
try {
if (error.path && typeof error.path == 'string' && error.errno == -4048) {
if (error.path && typeof error.path == 'string' && error.code === 'EPERM') {
var err = {};
err.path = error.path.replace(/\\/g, '/').replace(/\/\//g, '/');
if (error.path.endsWith('/')) {
Expand Down Expand Up @@ -99,6 +109,10 @@ getByPath.prototype = {
}.bind(this));
},
file: function(callback) {
if (!this.path) {
callback(null);
return null;
}
if (! callback) {
return;
}
Expand All @@ -121,6 +135,10 @@ getByPath.prototype = {
}.bind(this))
},
remove: function(callback) {
if (!this.path) {
callback(null);
return null;
}
if (! callback) {
callback = function() {};
}
Expand Down Expand Up @@ -154,6 +172,10 @@ getByPath.prototype = {
if (! callback) {
return;
}
if (!this.path) {
callback(null);
return null;
}
if (this.isFile) {
callback({error: 'Cannot preform on file'});
return;
Expand All @@ -174,7 +196,7 @@ getByPath.prototype = {
function getFileInfo() {
var file = new getByPath(this.origpath + '/' + files[i], function(file) {
results.push(file);
if (i != totalLength) {
if (i < totalLength) {
i++;
getFileInfo.bind(this)();
} else {
Expand Down Expand Up @@ -236,7 +258,7 @@ FileSystem.prototype = {
} catch(e) {
var error = e;
}
if (error && error.errno === -4058) {
if (error && error.code === 'ENOENT') {
try {
fs.writeFileSync(path, data);
} catch(e) {
Expand Down
2 changes: 0 additions & 2 deletions WSC/crypto.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@

module.exports = function() {
var data = { }
var cn = "WebServerForChrome" + (new Date()).toISOString();
Expand Down Expand Up @@ -63,4 +62,3 @@ module.exports = function() {
return data;
console.log('certificate created for \"' + cn + '\": \n');
};

38 changes: 19 additions & 19 deletions WSC/handlers.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ BaseHandler.prototype = {
},
error: async function(msg, httpCode) {
var defaultMsg = '<h1>' + httpCode + ' - ' + WSC.HTTPRESPONSES[httpCode] + '</h1>\n\n<p>' + msg + '</p>';
if (this.request.method == "HEAD") {
if (this.request.method === "HEAD") {
this.responseLength = 0;
this.writeHeaders(httpCode);
this.finish();
Expand Down Expand Up @@ -177,7 +177,7 @@ DirectoryEntryHandler.prototype = {
return
}
global.ConnetionS[this.request.ip]++
console.log(this.request.ip + ':', 'Request',this.request.method, this.request.uri)
console.log("["+(new Date()).toLocaleString()+"]", this.request.ip + ':', 'Request',this.request.method, this.request.uri)
/*
if (this.app.opts.optIpBlocking && this.app.opts.optIpBlockList) {
var file = await this.fs.asyncGetByPath(this.app.opts.optIpBlockList)
Expand Down Expand Up @@ -229,7 +229,7 @@ DirectoryEntryHandler.prototype = {

if (this.app.opts.spa) {
if (!this.request.uri.match(/.*\.[\d\w]+$/)) {
console.log("Single page rewrite rule matched", this.request.uri);
//console.log("Single page rewrite rule matched", this.request.uri);
this.rewrite_to = this.app.opts.rewriteTo || "/index.html";
}
}
Expand Down Expand Up @@ -343,7 +343,7 @@ DirectoryEntryHandler.prototype = {
},
delete: function() {
async function deleteMain() {
var entry = await this.fs.asyncGetByPath(this.request.path);
var entry = await this.fs.asyncGetByPath(this.request.origpath);
if (entry.error) {
this.writeHeaders(404);
this.finish();
Expand Down Expand Up @@ -508,7 +508,7 @@ DirectoryEntryHandler.prototype = {
},
put: function() {
async function putMain() {
var entry = await this.fs.asyncGetByPath(this.request.path)
var entry = await this.fs.asyncGetByPath(this.request.origpath)
if (entry.error) {
var file = this.fs.createWriteStream(this.request.origpath)
file.on('error', function (err) {
Expand Down Expand Up @@ -596,13 +596,13 @@ DirectoryEntryHandler.prototype = {
this.entry = entry;
async function excludedothtmlcheck() {
if (this.app.opts.excludeDotHtml && this.request.path != '' && ! this.request.origpath.endsWith("/")) {
var file = await this.fs.asyncGetByPath(this.request.path+'.html');
var file = await this.fs.asyncGetByPath(this.request.origpath+'.html');
if (! file.error && file.isFile) {
this.setHeader('content-type','text/html; charset=utf-8');
this.renderFileContents(file);
return;
}
var file = await this.fs.asyncGetByPath(this.request.path+'.htm');
var file = await this.fs.asyncGetByPath(this.request.origpath+'.htm');
if (! file.error && file.isFile) {
this.setHeader('content-type','text/html; charset=utf-8');
this.renderFileContents(file);
Expand Down Expand Up @@ -630,7 +630,7 @@ DirectoryEntryHandler.prototype = {
if (this.entry.error.code == 'EPERM') {
this.error('', 403);
} else {
this.error('entry not found: ' + (this.rewrite_to || this.request.path), 404);
this.error('entry not found: ' + (this.rewrite_to || this.request.path).htmlEscape(), 404);
}
} else if (this.entry.isFile) {
this.renderFileContents(this.entry);
Expand Down Expand Up @@ -855,8 +855,8 @@ DirectoryEntryHandler.prototype = {
var data = await file.textPromise();
var html = [dataa];
for (var w=0; w<results.length; w++) {
var rawname = results[w].name;
var name = encodeURIComponent(results[w].name);
var rawname = results[w].name.replaceAll('\\', '\\\\').replaceAll('"', '\\"');
var name = encodeURIComponent(results[w].name).replaceAll('\\', '\\\\').replaceAll('"', '\\"');
var isdirectory = results[w].isDirectory;
var modified = WSC.utils.lastModified(results[w].modificationTime);
var filesize = results[w].size;
Expand Down Expand Up @@ -1024,7 +1024,7 @@ DirectoryEntryHandler.prototype = {
}
var filerequest = this.request.origpath;
if (this.app.opts.excludeDotHtml) {
var file = await this.fs.asyncGetByPath(this.request.path+'.html');
var file = await this.fs.asyncGetByPath(this.request.origpath+'.html');
if (! file.error) {
if (this.request.origpath.endsWith("/")) {
htaccessMain.bind(this)('');
Expand All @@ -1036,7 +1036,7 @@ DirectoryEntryHandler.prototype = {
htaccessMain.bind(this)(filerequested);
return;
}
var file = await this.fs.asyncGetByPath(this.request.path+'.htm');
var file = await this.fs.asyncGetByPath(this.request.origpath+'.htm');
if (! file.error) {
if (this.request.origpath.endsWith("/")) {
htaccessMain.bind(this)('');
Expand Down Expand Up @@ -1109,7 +1109,7 @@ DirectoryEntryHandler.prototype = {
}
var compression = false;
var stream = this.fs.createReadStream(entry.fullPath, {start: fileOffset,end: fileEndOffset});
if (this.request.headers['accept-encoding'] && this.app.opts.compressResponses) {
if (this.request.headers['accept-encoding'] && this.app.opts.compression) {
var ac = this.request.headers['accept-encoding'];
if (ac.includes('br') || ac.includes('gzip') || ac.includes('deflate')) {
compression = true;
Expand All @@ -1124,11 +1124,11 @@ DirectoryEntryHandler.prototype = {
this.setHeader('Content-Encoding', 'deflate');
compresionStream = zlib.createDeflate();
} else {
console.log('this.. shouldnt be possible');
//console.log('this.. shouldnt be possible');
this.res.end();
return;
}
pipeline(stream, compresionStream, this.res, function(e) {console.warn('error', e); this.res.end()}.bind(this))
pipeline(stream, compresionStream, this.res, function(err) {if (err) {console.warn('Compression Error:', err); this.res.end()}}.bind(this))
}
}
this.writeHeaders(code);
Expand Down Expand Up @@ -1199,8 +1199,8 @@ DirectoryEntryHandler.prototype = {
html.push('<script>onHasParentDirectory();</script>');
}
for (var w=0; w<results.length; w++) {
var rawname = results[w].name;
var name = encodeURIComponent(results[w].name);
var rawname = results[w].name.replaceAll('\\', '\\\\').replaceAll('"', '\\"');
var name = encodeURIComponent(results[w].name).replaceAll('\\', '\\\\').replaceAll('"', '\\"');
var isdirectory = results[w].isDirectory;
var modified = WSC.utils.lastModified(results[w].modificationTime);
var filesize = results[w].size;
Expand Down Expand Up @@ -1228,8 +1228,8 @@ DirectoryEntryHandler.prototype = {
html.push('<script>onHasParentDirectory();</script>');
}
for (var w=0; w<results.length; w++) {
var rawname = results[w].name;
var name = encodeURIComponent(results[w].name);
var rawname = results[w].name.replaceAll('\\', '\\\\').replaceAll('"', '\\"');
var name = encodeURIComponent(results[w].name).replaceAll('\\', '\\\\').replaceAll('"', '\\"');
var isdirectory = results[w].isDirectory;
var modified = WSC.utils.lastModified(results[w].modificationTime);
var filesize = results[w].size;
Expand Down
21 changes: 12 additions & 9 deletions WSC/utils.js
Original file line number Diff line number Diff line change
@@ -1,27 +1,30 @@
String.prototype.htmlEscape = function() {
return this.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&#039;")
return this.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&#039;");
}
if (!String.prototype.replaceAll) {
String.prototype.replaceAll = function(a, b) {
return this.split(a).join(b);
}
}

module.exports = {
humanFileSize: function(bytes, si=false, dp=1) {
humanFileSize: function(bytes) {
if (! bytes) {
return ''
return '';
}
//from https://stackoverflow.com/questions/10420352/converting-file-size-in-bytes-to-human-readable-string/10420404
const thresh = si ? 1000 : 1024;
const thresh = 1024;
if (Math.abs(bytes) < thresh) {
return bytes + ' B';
}
const units = si
? ['kB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB']
: ['KiB', 'MiB', 'GiB', 'TiB', 'PiB', 'EiB', 'ZiB', 'YiB'];
const units = ['KiB', 'MiB', 'GiB', 'TiB', 'PiB', 'EiB', 'ZiB', 'YiB'];
let u = -1;
const r = 10**dp;
const r = 10;
do {
bytes /= thresh;
++u;
} while (Math.round(Math.abs(bytes) * r) / r >= thresh && u < units.length - 1);
return bytes.toFixed(dp) + ' ' + units[u];
return bytes.toFixed(1) + ' ' + units[u];
},
lastModified: function(modificationTime) {
if (! modificationTime) {
Expand Down
Binary file removed dist/Windows.zip
Binary file not shown.
Binary file removed dist/macOS.zip
Binary file not shown.
1 change: 0 additions & 1 deletion docs/config.md

This file was deleted.

Loading