mirror of
https://github.com/unraid/api.git
synced 2026-01-12 03:30:08 -06:00
110 lines
3.4 KiB
JavaScript
110 lines
3.4 KiB
JavaScript
/*
|
|
* Copyright 2005-2019, Lime Technology
|
|
* Copyright 2018-2019, Alexis Tyler
|
|
*
|
|
* This program is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU General Public License version 2,
|
|
* as published by the Free Software Foundation.
|
|
*
|
|
* The above copyright notice and this permission notice shall be included in
|
|
* all copies or substantial portions of the Software.
|
|
*/
|
|
|
|
/**
|
|
* The Graphql server.
|
|
*/
|
|
module.exports = function ($injector, fs, net, express, config, log, getEndpoints, stoppable) {
|
|
const app = express();
|
|
const port = config.get('graphql-api-port');
|
|
let server;
|
|
|
|
const ApolloServer = $injector.resolve('apollo-server-express').ApolloServer;
|
|
const graphql = $injector.resolvePath(__dirname + '/graphql');
|
|
|
|
// Mount graph endpoint
|
|
const graphApp = new ApolloServer(graphql);
|
|
graphApp.applyMiddleware({ app });
|
|
|
|
// List all endpoints at start of server
|
|
app.get('/', (req, res, next) => {
|
|
return res.send(getEndpoints(app));
|
|
});
|
|
|
|
// Handle errors by logging them and returning a 500.
|
|
app.use(function (err, req, res, next) {
|
|
log.error(err);
|
|
if (err.stack) {
|
|
err.stackTrace = err.stack;
|
|
}
|
|
res.status(error.status || 500).send(err);
|
|
});
|
|
|
|
// Return an object with start and stop methods.
|
|
return {
|
|
start() {
|
|
server = stoppable(app.listen(port, () => {
|
|
// Downgrade process user to owner of this file
|
|
return fs.stat(__filename, (err, stats) => {
|
|
if (err) {
|
|
throw err;
|
|
}
|
|
|
|
return process.setuid(stats.uid);
|
|
});
|
|
}));
|
|
|
|
// Port is a UNIX socket file
|
|
if (isNaN(parseInt(port, 10))) {
|
|
server.on('listening', () => {
|
|
// In production this will let pm2 know we're ready
|
|
if (process.send) {
|
|
process.send('ready');
|
|
}
|
|
|
|
// Set permissions
|
|
return fs.chmodSync(port, 777);
|
|
});
|
|
|
|
// Double-check EADDRINUSE
|
|
server.on('error', error => {
|
|
if (error.code !== 'EADDRINUSE') {
|
|
throw error;
|
|
}
|
|
|
|
net.connect({
|
|
path: port
|
|
}, () => {
|
|
// Really in use: re-throw
|
|
throw error;
|
|
}).on('error', error => {
|
|
if (error.code !== 'ECONNREFUSED') {
|
|
throw error;
|
|
}
|
|
|
|
// Not in use: delete it and re-listen
|
|
fs.unlinkSync(port);
|
|
server.listen(port);
|
|
});
|
|
});
|
|
}
|
|
|
|
return server;
|
|
},
|
|
stop() {
|
|
// Stop the server from accepting new connections and close existing connections
|
|
return server.close(err => {
|
|
if (err) {
|
|
log.error(err);
|
|
// Exit with error (code 1)
|
|
// eslint-disable-next-line
|
|
process.exit(1);
|
|
}
|
|
|
|
log.info('Server shutting down..');
|
|
|
|
// Gracefully exit
|
|
process.exitCode = 0;
|
|
});
|
|
}
|
|
};
|
|
}; |