Non gemtext static files
* Static file handler now attempts to use "file-type" if it is available to read the magic bytes of a file and get Mime type * Fixed a crash if the client closed the socket prematurely * Move README to gmi
This commit is contained in:
parent
7761c18fd5
commit
2dabbc0969
|
@ -1 +1,2 @@
|
|||
*.pem
|
||||
node_modules
|
||||
|
|
|
@ -220,6 +220,9 @@ export default class GeminiServer {
|
|||
}
|
||||
}
|
||||
});
|
||||
|
||||
// This can be just ECONNRESET
|
||||
socket.on("error", console.error);
|
||||
});
|
||||
server.listen(1965);
|
||||
}
|
||||
|
|
|
@ -23,7 +23,7 @@ A `relativePath` is the difference between a `basePath` and a `urlPath`. It's no
|
|||
|
||||
Sometimes these paths will include their hostnames
|
||||
|
||||
A path in the pathRegistry is a `p`, which is an object with a hostname, a basePath, and a handler
|
||||
A path in the pathRegistry is a `p`, which is an object with a hostname, a basePath, and a handler
|
||||
|
||||
|
||||
|
||||
|
@ -44,4 +44,4 @@ openssl x509 -req -in csr.pem -signkey private-key.pem -out public-cert.pem
|
|||
It's possible to imagine a situation where astronomical theater is behind a proxy and the proxy doesn't do address translation, passing the raw gemini request to us.
|
||||
In this case, our behavior is undefined.
|
||||
|
||||
Similarly, SNI is not supported with IP addresses.
|
||||
Similarly, SNI is not supported with IP addresses.
|
|
@ -57,8 +57,8 @@ server.registerPath("localhost/allFiles", new ExampleHandler());
|
|||
// We will provide some convenient handlers for static, CGI, and reverse proxy
|
||||
|
||||
//if the passed file is a single file, it's a file. If it's a directory, all sub-files are auto-included
|
||||
server.registerPath("localhost/static/about.gmi", new StaticHandler("/tmp/content/about.gmi" /*, {options}*/));
|
||||
server.registerPath("localhost/static", new StaticHandler("/tmp/content/" /*, {options}*/));
|
||||
server.registerPath("localhost/static/about.gmi", new StaticHandler("README.gmi" /*, {options}*/));
|
||||
server.registerPath("localhost/static", new StaticHandler("static/" /*, {options}*/));
|
||||
// server.registerPath("localhost/static", new StaticHandler("/tmp/yourmom/" /*, {options}*/));
|
||||
|
||||
//The file passed to CGI handler must exist and be executable at run time
|
||||
|
|
|
@ -3,6 +3,9 @@ import * as fs from "fs";
|
|||
|
||||
import DefaultHandler from "./default.js";
|
||||
|
||||
let fileTypeFromFile;
|
||||
import("file-type").then(ft => fileTypeFromFile = ft.default.fromFile).catch(console.error);
|
||||
|
||||
export default class StaticHandler extends DefaultHandler {
|
||||
constructor(basePath, directoryList = false) {
|
||||
super();
|
||||
|
@ -18,7 +21,7 @@ export default class StaticHandler extends DefaultHandler {
|
|||
|
||||
// This is the handler
|
||||
// url is the URL object, with url.pathname being the path. p is the 'client-side' basepath
|
||||
handle (url, p) {
|
||||
async handle (url, p, socket) {
|
||||
const relativePath = path.relative(p, url.pathname);
|
||||
//Concat and normalize the passed URL as being relative to the base path
|
||||
const toServe = path.join(this.basePath, relativePath);
|
||||
|
@ -32,7 +35,7 @@ export default class StaticHandler extends DefaultHandler {
|
|||
if (fs.statSync(toServe).isDirectory()) {
|
||||
console.log(`File is a directory and directoryList is ${this.directoryList}.`);
|
||||
if (this.directoryList) {
|
||||
|
||||
//TODO: Static content directory listing
|
||||
} else {
|
||||
return "51 Not Found\r\n";
|
||||
}
|
||||
|
@ -43,9 +46,31 @@ export default class StaticHandler extends DefaultHandler {
|
|||
return "51 Not Found\r\n";
|
||||
}
|
||||
|
||||
//TODO: import mmmagic
|
||||
let mimeType = "text/gemini";
|
||||
|
||||
if (fileTypeFromFile) {
|
||||
const type = await fileTypeFromFile(toServe);
|
||||
// `type` will be undefined if the file is plaintext
|
||||
// In which case we want to fall down to serving plaintext
|
||||
if (type) {
|
||||
mimeType = type.mime;
|
||||
}
|
||||
}
|
||||
|
||||
//TODO: some file-ending based logic, please
|
||||
//So we can serve md and txt
|
||||
|
||||
|
||||
//TODO: convert line endings
|
||||
const data = fs.readFileSync(toServe);
|
||||
return "20 text/gemini\r\n" + data;
|
||||
// I read somewhere that `readFileSync` on every request is a bad idea, but I don't care
|
||||
socket.write(`20 ${mimeType}\r\n`);
|
||||
const fileReader = fs.createReadStream(toServe);
|
||||
//This function (handle) needs to return after we're done writing the file to the stream
|
||||
//Because the place that called this is going to handle .end() the socket
|
||||
//So we don't end the socket here, and we make a promise to wait for the reader to end before returning
|
||||
//It would be great if we could just not return from this function but I don't think that's how this works
|
||||
fileReader.pipe(socket, {end: false});
|
||||
await new Promise((res, rej) => fileReader.on("end", res));
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,275 @@
|
|||
{
|
||||
"name": "astronomical-theater",
|
||||
"version": "v2.0.5",
|
||||
"lockfileVersion": 2,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "astronomical-theater",
|
||||
"version": "v2.0.5",
|
||||
"license": "CC0-1.0",
|
||||
"optionalDependencies": {
|
||||
"file-type": "^16.5.3"
|
||||
}
|
||||
},
|
||||
"node_modules/@tokenizer/token": {
|
||||
"version": "0.3.0",
|
||||
"resolved": "https://registry.npmjs.org/@tokenizer/token/-/token-0.3.0.tgz",
|
||||
"integrity": "sha512-OvjF+z51L3ov0OyAU0duzsYuvO01PH7x4t6DJx+guahgTnBHkhJdG7soQeTSFLWN3efnHyibZ4Z8l2EuWwJN3A==",
|
||||
"optional": true
|
||||
},
|
||||
"node_modules/file-type": {
|
||||
"version": "16.5.3",
|
||||
"resolved": "https://registry.npmjs.org/file-type/-/file-type-16.5.3.tgz",
|
||||
"integrity": "sha512-uVsl7iFhHSOY4bEONLlTK47iAHtNsFHWP5YE4xJfZ4rnX7S1Q3wce09XgqSC7E/xh8Ncv/be1lNoyprlUH/x6A==",
|
||||
"optional": true,
|
||||
"dependencies": {
|
||||
"readable-web-to-node-stream": "^3.0.0",
|
||||
"strtok3": "^6.2.4",
|
||||
"token-types": "^4.1.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sindresorhus/file-type?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/ieee754": {
|
||||
"version": "1.2.1",
|
||||
"resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz",
|
||||
"integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==",
|
||||
"funding": [
|
||||
{
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/feross"
|
||||
},
|
||||
{
|
||||
"type": "patreon",
|
||||
"url": "https://www.patreon.com/feross"
|
||||
},
|
||||
{
|
||||
"type": "consulting",
|
||||
"url": "https://feross.org/support"
|
||||
}
|
||||
],
|
||||
"optional": true
|
||||
},
|
||||
"node_modules/inherits": {
|
||||
"version": "2.0.4",
|
||||
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
|
||||
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
|
||||
"optional": true
|
||||
},
|
||||
"node_modules/peek-readable": {
|
||||
"version": "4.0.1",
|
||||
"resolved": "https://registry.npmjs.org/peek-readable/-/peek-readable-4.0.1.tgz",
|
||||
"integrity": "sha512-7qmhptnR0WMSpxT5rMHG9bW/mYSR1uqaPFj2MHvT+y/aOUu6msJijpKt5SkTDKySwg65OWG2JwTMBlgcbwMHrQ==",
|
||||
"optional": true,
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
},
|
||||
"funding": {
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/Borewit"
|
||||
}
|
||||
},
|
||||
"node_modules/readable-stream": {
|
||||
"version": "3.6.0",
|
||||
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz",
|
||||
"integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==",
|
||||
"optional": true,
|
||||
"dependencies": {
|
||||
"inherits": "^2.0.3",
|
||||
"string_decoder": "^1.1.1",
|
||||
"util-deprecate": "^1.0.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 6"
|
||||
}
|
||||
},
|
||||
"node_modules/readable-web-to-node-stream": {
|
||||
"version": "3.0.2",
|
||||
"resolved": "https://registry.npmjs.org/readable-web-to-node-stream/-/readable-web-to-node-stream-3.0.2.tgz",
|
||||
"integrity": "sha512-ePeK6cc1EcKLEhJFt/AebMCLL+GgSKhuygrZ/GLaKZYEecIgIECf4UaUuaByiGtzckwR4ain9VzUh95T1exYGw==",
|
||||
"optional": true,
|
||||
"dependencies": {
|
||||
"readable-stream": "^3.6.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
},
|
||||
"funding": {
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/Borewit"
|
||||
}
|
||||
},
|
||||
"node_modules/safe-buffer": {
|
||||
"version": "5.2.1",
|
||||
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
|
||||
"integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==",
|
||||
"funding": [
|
||||
{
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/feross"
|
||||
},
|
||||
{
|
||||
"type": "patreon",
|
||||
"url": "https://www.patreon.com/feross"
|
||||
},
|
||||
{
|
||||
"type": "consulting",
|
||||
"url": "https://feross.org/support"
|
||||
}
|
||||
],
|
||||
"optional": true
|
||||
},
|
||||
"node_modules/string_decoder": {
|
||||
"version": "1.3.0",
|
||||
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz",
|
||||
"integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==",
|
||||
"optional": true,
|
||||
"dependencies": {
|
||||
"safe-buffer": "~5.2.0"
|
||||
}
|
||||
},
|
||||
"node_modules/strtok3": {
|
||||
"version": "6.2.4",
|
||||
"resolved": "https://registry.npmjs.org/strtok3/-/strtok3-6.2.4.tgz",
|
||||
"integrity": "sha512-GO8IcFF9GmFDvqduIspUBwCzCbqzegyVKIsSymcMgiZKeCfrN9SowtUoi8+b59WZMAjIzVZic/Ft97+pynR3Iw==",
|
||||
"optional": true,
|
||||
"dependencies": {
|
||||
"@tokenizer/token": "^0.3.0",
|
||||
"peek-readable": "^4.0.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
},
|
||||
"funding": {
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/Borewit"
|
||||
}
|
||||
},
|
||||
"node_modules/token-types": {
|
||||
"version": "4.1.1",
|
||||
"resolved": "https://registry.npmjs.org/token-types/-/token-types-4.1.1.tgz",
|
||||
"integrity": "sha512-hD+QyuUAyI2spzsI0B7gf/jJ2ggR4RjkAo37j3StuePhApJUwcWDjnHDOFdIWYSwNR28H14hpwm4EI+V1Ted1w==",
|
||||
"optional": true,
|
||||
"dependencies": {
|
||||
"@tokenizer/token": "^0.3.0",
|
||||
"ieee754": "^1.2.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
},
|
||||
"funding": {
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/Borewit"
|
||||
}
|
||||
},
|
||||
"node_modules/util-deprecate": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
|
||||
"integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=",
|
||||
"optional": true
|
||||
}
|
||||
},
|
||||
"dependencies": {
|
||||
"@tokenizer/token": {
|
||||
"version": "0.3.0",
|
||||
"resolved": "https://registry.npmjs.org/@tokenizer/token/-/token-0.3.0.tgz",
|
||||
"integrity": "sha512-OvjF+z51L3ov0OyAU0duzsYuvO01PH7x4t6DJx+guahgTnBHkhJdG7soQeTSFLWN3efnHyibZ4Z8l2EuWwJN3A==",
|
||||
"optional": true
|
||||
},
|
||||
"file-type": {
|
||||
"version": "16.5.3",
|
||||
"resolved": "https://registry.npmjs.org/file-type/-/file-type-16.5.3.tgz",
|
||||
"integrity": "sha512-uVsl7iFhHSOY4bEONLlTK47iAHtNsFHWP5YE4xJfZ4rnX7S1Q3wce09XgqSC7E/xh8Ncv/be1lNoyprlUH/x6A==",
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"readable-web-to-node-stream": "^3.0.0",
|
||||
"strtok3": "^6.2.4",
|
||||
"token-types": "^4.1.1"
|
||||
}
|
||||
},
|
||||
"ieee754": {
|
||||
"version": "1.2.1",
|
||||
"resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz",
|
||||
"integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==",
|
||||
"optional": true
|
||||
},
|
||||
"inherits": {
|
||||
"version": "2.0.4",
|
||||
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
|
||||
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
|
||||
"optional": true
|
||||
},
|
||||
"peek-readable": {
|
||||
"version": "4.0.1",
|
||||
"resolved": "https://registry.npmjs.org/peek-readable/-/peek-readable-4.0.1.tgz",
|
||||
"integrity": "sha512-7qmhptnR0WMSpxT5rMHG9bW/mYSR1uqaPFj2MHvT+y/aOUu6msJijpKt5SkTDKySwg65OWG2JwTMBlgcbwMHrQ==",
|
||||
"optional": true
|
||||
},
|
||||
"readable-stream": {
|
||||
"version": "3.6.0",
|
||||
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz",
|
||||
"integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==",
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"inherits": "^2.0.3",
|
||||
"string_decoder": "^1.1.1",
|
||||
"util-deprecate": "^1.0.1"
|
||||
}
|
||||
},
|
||||
"readable-web-to-node-stream": {
|
||||
"version": "3.0.2",
|
||||
"resolved": "https://registry.npmjs.org/readable-web-to-node-stream/-/readable-web-to-node-stream-3.0.2.tgz",
|
||||
"integrity": "sha512-ePeK6cc1EcKLEhJFt/AebMCLL+GgSKhuygrZ/GLaKZYEecIgIECf4UaUuaByiGtzckwR4ain9VzUh95T1exYGw==",
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"readable-stream": "^3.6.0"
|
||||
}
|
||||
},
|
||||
"safe-buffer": {
|
||||
"version": "5.2.1",
|
||||
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
|
||||
"integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==",
|
||||
"optional": true
|
||||
},
|
||||
"string_decoder": {
|
||||
"version": "1.3.0",
|
||||
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz",
|
||||
"integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==",
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"safe-buffer": "~5.2.0"
|
||||
}
|
||||
},
|
||||
"strtok3": {
|
||||
"version": "6.2.4",
|
||||
"resolved": "https://registry.npmjs.org/strtok3/-/strtok3-6.2.4.tgz",
|
||||
"integrity": "sha512-GO8IcFF9GmFDvqduIspUBwCzCbqzegyVKIsSymcMgiZKeCfrN9SowtUoi8+b59WZMAjIzVZic/Ft97+pynR3Iw==",
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"@tokenizer/token": "^0.3.0",
|
||||
"peek-readable": "^4.0.1"
|
||||
}
|
||||
},
|
||||
"token-types": {
|
||||
"version": "4.1.1",
|
||||
"resolved": "https://registry.npmjs.org/token-types/-/token-types-4.1.1.tgz",
|
||||
"integrity": "sha512-hD+QyuUAyI2spzsI0B7gf/jJ2ggR4RjkAo37j3StuePhApJUwcWDjnHDOFdIWYSwNR28H14hpwm4EI+V1Ted1w==",
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"@tokenizer/token": "^0.3.0",
|
||||
"ieee754": "^1.2.1"
|
||||
}
|
||||
},
|
||||
"util-deprecate": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
|
||||
"integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=",
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,11 +1,14 @@
|
|||
{
|
||||
"name": "astronomical-theater",
|
||||
"version": "v2.0.5",
|
||||
"version": "v2.1.0",
|
||||
"author": "Matthias",
|
||||
"license": "CC0-1.0",
|
||||
"type": "module",
|
||||
"main": "main.js",
|
||||
"scripts": {
|
||||
"start": "node main.js"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"file-type": "^16.5.3"
|
||||
}
|
||||
}
|
||||
|
|
Binary file not shown.
After Width: | Height: | Size: 3.9 KiB |
Loading…
Reference in New Issue