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

add option to listen via unix socket #96

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,8 @@ You must fill this out for the webserver to work properly. Below explains the co
"domain": "*.example.com", // Domain server will use. Will error if domain not used in request. Place "*" as the subdomain to enable wildcard subdomains for the webserver.
"puploadKeyGenLength": 64, // Amount of characters server should use for pupload files
"public": false, // Disables auth and does not render a password field for /upload
"socket": "", // socket path to listen eg. /tmp/shares.sock
"socketOnly": true, // do not listen via ip if socket is set (ignore options secure, port)
"maxUploadSize": 50, // max upload size for non-admins using regular key in MB
"markdown": true, // enables markdown rendering (upload whole .md file for render)
"port": 80, // port to listen on
Expand Down Expand Up @@ -86,6 +88,7 @@ If you're configuring this webserver to run through an Nginx reverse proxy, make
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_cache_bypass $http_upgrade;
```
This is generally some things you want to add to your config, and is what's actually required for ShareS to work properly. This is because ShareS returns uploads like `[http/https]://[requested url]/[filename]` and since you're running ShareS through a reverse proxy, unless you're passing along the *original* headers, ShareS is most likely just going to send you something like `http://[server's real ip address]/[filename]`
Expand Down
2 changes: 2 additions & 0 deletions src/config.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
"domain": "example.com",
"puploadKeyGenLength": 64,
"public": false,
"socket": "",
"socketOnly": true,
"maxUploadSize": 50,
"markdown": true,
"port": 80,
Expand Down
79 changes: 47 additions & 32 deletions src/server/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ class ShareXAPI {
this.c = c;
this.monitorChannel = null;
this.checkMonth();
this.c.discordToken && this.c.discordToken !== undefined && this.c.discrdToken !== null
this.c.discordToken && this.c.discordToken !== undefined && this.c.discordToken !== null
? this.runDiscordBot()
: this.log.verbose('No Discord Token provided...\nContinuing without Discord connection...');
this.app = app;
Expand All @@ -60,16 +60,16 @@ class ShareXAPI {

/* Don't allow access if not accessed with configured domain */
this.app.use((req, res, next) => {
if(this.c.domain === '*') {
if (this.c.domain === '*') {
next();
} else if(req.headers.host !== this.c.domain.toLowerCase() && !this.c.domain.includes('*')) {
} else if (req.headers.host !== this.c.domain.toLowerCase() && !this.c.domain.includes('*')) {
res.statusCode = 401;
res.write('Error 401: Unauthorized Domain');
return res.end();
} else if(this.c.domain.includes('*')) {
let reqParts = req.headers.host.toLowerCase().split('.');
let domainParts = this.c.domain.toLowerCase().split('.')
if(reqParts[1] === domainParts[1] && reqParts[2] === domainParts[2]) {
} else if (this.c.domain.includes('*')) {
const reqParts = req.headers.host.toLowerCase().split('.');
const domainParts = this.c.domain.toLowerCase().split('.');
if (reqParts[1] === domainParts[1] && reqParts[2] === domainParts[2]) {
next();
} else {
res.statusCode = 401;
Expand Down Expand Up @@ -114,7 +114,7 @@ class ShareXAPI {
this.app.use((req, res, next) => {
if (req.method === 'GET') {
const userIP = req.headers['x-forwarded-for'] || req.connection.remoteAddress || req.socket.remoteAddress || req.connection.socket.remoteAddress;
let file = req.path;
const file = req.path;
// Not ignoring these files causes bloat in the db
const ignored = ['/favicon.ico', '/assets/css/styles.min.css', '/highlight.pack.js', '/highlightjs-line-numbers.min.js', '/paste.css', '/atom-one-dark.css'];
let exists = this.db.get('files').find({ path: file }).value();
Expand Down Expand Up @@ -172,7 +172,7 @@ class ShareXAPI {
});
// All files in /uploads/ are publicly accessible via http
this.app.use(express.static(`${__dirname}/uploads/`, {
extensions: this.c.admin.allowed.includes("*") ? null : this.c.admin.allowed,
extensions: this.c.admin.allowed.includes('*') ? null : this.c.admin.allowed,
}));
this.app.use(express.static(`${__dirname}/views/`, {
extensions: ['css'],
Expand Down Expand Up @@ -234,32 +234,47 @@ class ShareXAPI {
* @returns {void}
*/
async startServer() {
if (this.c.secure) {
/** if the secure option is set to true in config,
* it will boot in https so long as it detects
* key.pem and cert.pem in the src directory
*/
if (fs.existsSync(`${__dirname}/../key.pem`) && fs.existsSync(`${__dirname}/../cert.pem`)) {
const privateKey = fs.readFileSync(`${__dirname}/../key.pem`);
const certificate = fs.readFileSync(`${__dirname}/../cert.pem`);
https.createServer({
key: privateKey,
cert: certificate,
}, this.app).listen(this.c.securePort, '0.0.0.0');
if (!this.c.socketOnly || !this.c.socket) {
if (this.c.secure) {
/** if the secure option is set to true in config,
* it will boot in https so long as it detects
* key.pem and cert.pem in the src directory
*/
if (fs.existsSync(`${__dirname}/../key.pem`) && fs.existsSync(`${__dirname}/../cert.pem`)) {
const privateKey = fs.readFileSync(`${__dirname}/../key.pem`);
const certificate = fs.readFileSync(`${__dirname}/../cert.pem`);
https.createServer({
key: privateKey,
cert: certificate,
}, this.app).listen(this.c.securePort, '0.0.0.0');
} else {
// CF Flexible SSL
/** if no key & cert pem files are detected,
* it will still run in secure mode (returning urls with https)
* so that it's compatible with CF flexible SSL
* and SSL configurations via a reverse proxy */
this.app.listen(this.c.securePort, '0.0.0.0', () => {
this.log.warning('Server using flexible SSL secure setting\nTo run a full SSL setting, ensure key.pem and cert.pem are in the /src folder');
});
}
this.log.success(`Secure server listening on port ${this.c.securePort}`);
} else {
// CF Flexible SSL
/** if no key & cert pem files are detected,
* it will still run in secure mode (returning urls with https)
* so that it's compatible with CF flexible SSL
* and SSL configurations via a reverse proxy */
this.app.listen(this.c.securePort, '0.0.0.0', () => {
this.log.warning('Server using flexible SSL secure setting\nTo run a full SSL setting, ensure key.pem and cert.pem are in the /src folder');
this.app.listen(this.c.port, '0.0.0.0', () => {
this.log.success(`Server listening on port ${this.c.port}`);
});
}
this.log.success(`Secure server listening on port ${this.c.securePort}`);
} else {
this.app.listen(this.c.port, '0.0.0.0', () => {
this.log.success(`Server listening on port ${this.c.port}`);
}
if (this.c.socket) {
const socket = this.c.socket.toString();
// https://stackoverflow.com/a/21385803
fs.stat(socket, (err) => {
if (!err) { fs.unlinkSync(socket); }
this.app.listen(/** @type string */socket, () => {
if (fs.chmodSync) {
fs.chmodSync(socket, '777');
}
this.log.success(`Server listening on socket ${socket}`);
});
});
}
}
Expand Down