vartiste-extras
Version:
Server to serve vartiste-extras files
189 lines (160 loc) • 6.38 kB
JavaScript
#!/usr/bin/env node
const express = require('express')
const { createProxyMiddleware } = require('http-proxy-middleware');
const app = express()
const https = require('https')
const cors = require('cors')
const selfsigned = require('selfsigned');
const fs = require('fs')
const fsPromises = require('fs/promises')
const path = require('path')
const os = require('os')
const chalk = require('chalk')
const servePath = fs.existsSync('extras') ? "extras" : "."
console.warn(chalk.yellow(`
***WARNING:*** By running this server you are exposing all files and directories
in \`${servePath}\`.
`))
console.warn(`
THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
`)
const yargonaut = require('yargonaut')
.style('green')
.helpStyle('blue')
.errorsStyle('red')
.style('green', 'ngrok')
const yargs = require('yargs');
const argv = yargs
.command('ngrok', 'Start server using ngrok tunnel. The extras will be available over the internet via https. This will work with most mobile VR headsets without additional configuration on the PC.')
.command('http', 'Start the server using a plain http server. This will work for local PCVR headsets and VARTISTE running locally, or mobile VR headsets using desktop PC streaming. However, to access it from remote PCs or mobile VR browsers, you\'ll need to proxy the data through an https server')
.command('https', 'Start the server using an https server. You will need to supply a valid SSL certificate. Note that this will not work with a self-signed certificate on most browsers unless the certificate has been installed as a trusted certificate to the operating system.', (yargs) => {
yargs.demandOption('ssl-key')
yargs.demandOption('ssl-cert')
})
.command('proxy', 'Start the server using a self-signed certificate AND a proxy for vartiste.xyz. You will need to use the provided URL to access VARTISTE in order for the extras to be available. This will likely only be available to devices on your local network, depending on your firewall setup.')
.demandCommand(1, 1, chalk.red("You must specify at least one command to run the server.") + ` The quickest way to get up and running is to use the ${chalk.green("ngrok")} command option`, "")
.group(['port'], chalk.blue('General Options:'))
.option('port', {
description: "Port to run the local server on",
default: 8081,
type: 'number'
})
.group(['ngrok-token'], chalk.blue('ngrok Options:'))
.option('ngrok-token', {
description: "Authentication token from ngrok.com for custom domains.",
type: 'string'
})
.group(['ssl-key', 'ssl-cert'], chalk.blue('https Options:'))
.option('ssl-key', {
description: 'Path to the private key file for the SSL certificate',
type: 'path'
})
.option('ssl-cert', {
description: 'Path to the SSL certificate file',
type: 'path'
})
.help()
.strict()
.alias('help', 'h').argv;
var port = argv.port
var mode = argv._[0]
const [
MODE_NGROK,
MODE_HTTP,
MODE_HTTPS,
MODE_PROXY,
] = [
"ngrok",
"http",
"https",
"proxy"
];
const localUrl = `${mode === MODE_HTTP ? "http" : "https"}://${os.hostname()}:${port}`
const ngrok = require('ngrok');
process.on('SIGINT', () => process.exit(1));
if (mode === MODE_PROXY)
{
app.use('/vartiste', createProxyMiddleware({
target: 'https://vartiste.xyz',
changeOrigin: true,
pathRewrite: {
'^/vartiste': '/', // rewrite path
},
}));
app.get('/', (req, res) => res.redirect('/vartiste/index.html?extrasURL=/'))
}
app.use(cors({
origin: '*'
}));
app.use(express.static(servePath))
app.get('/index.json', async (req, res) => {
let index = {}
let dirs = await fsPromises.readdir(servePath, {withFileTypes: true})
for (let file of dirs)
{
if (!file.isDirectory()) continue;
index[file.name] = await fsPromises.readdir(path.join(servePath, file.name))
}
res.send(index)
})
function showStartedMessage(url) {
console.info(chalk.green(`
You should be able to add ${url} as an Extras URL in VARTISTE using the Extras Shelf.
${chalk.blue("Project / Settings -> Load -> Load Extras -> Add Extras Source")}
`))
}
var listener = app;
if (mode === MODE_HTTPS)
{
listener = https.createServer({
key: fs.readFileSync(argv.sslKey),
cert: fs.readFileSync(argv.sslCert),
}, app);
}
else if (mode === MODE_PROXY)
{
var pems = selfsigned.generate([{ name: 'commonName', value: 'selfsigned-extras.vartiste.xyz' }], { days: 365 });
listener = https.createServer({
key: pems.private,
cert: pems.cert,
}, app);
}
listener.listen(port, () => {
console.log(`Serving VARTISTE extras from ${servePath} on port ${port}`)
if (mode === MODE_NGROK)
{
let authtoken = argv['ngrok-token'];
ngrok.connect(port, {authtoken}).then((url) => {
showStartedMessage(url)
if (!authtoken) {
console.warn(chalk.yellow(`
WARNING: you are using ngrok without an --ngrok-token option. This means the URL
will change every time you run the server. Make sure to remove the URL from
VARTISTE when you are done with it.
`) + `
You can register a permanent custom domain by signing up for a paid plan from
ngrok.com and using the provided auth token with the --ngrok-token option.
`)
}
});
}
else if (mode === MODE_PROXY)
{
console.info(chalk.green(`
VARTISTE Proxy is up and running. To use VARTISTE with this extras server, go to
${localUrl} on your browser for your VR headset in order to access VARTISTE.
NOTE: You will need to accept the security warning that comes up when you try to
access it. This is because it is using a "self-signed" ssl certificate. If you
want an option without this message, consider the ngrok or https command options.
`))
}
else
{
showStartedMessage(localUrl)
}
})