Skip to content

Commit f739c9e

Browse files
committed
add option to listen via unix socket
add `X-Forwarded-For` in nginx note (fix error in app.js:86) fix: eslint problem in app.js fix: TannerReynolds#90
1 parent e708060 commit f739c9e

File tree

3 files changed

+52
-32
lines changed

3 files changed

+52
-32
lines changed

README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,8 @@ You must fill this out for the webserver to work properly. Below explains the co
4747
"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.
4848
"puploadKeyGenLength": 64, // Amount of characters server should use for pupload files
4949
"public": false, // Disables auth and does not render a password field for /upload
50+
"socket": "", // socket path to listen eg. /tmp/shares.sock
51+
"socketOnly": true, // do not listen via ip if socket is set (ignore options secure, port)
5052
"maxUploadSize": 50, // max upload size for non-admins using regular key in MB
5153
"markdown": true, // enables markdown rendering (upload whole .md file for render)
5254
"port": 80, // port to listen on
@@ -86,6 +88,7 @@ If you're configuring this webserver to run through an Nginx reverse proxy, make
8688
proxy_set_header Upgrade $http_upgrade;
8789
proxy_set_header Connection 'upgrade';
8890
proxy_set_header Host $host;
91+
proxy_set_header X-Forwarded-For $remote_addr;
8992
proxy_cache_bypass $http_upgrade;
9093
```
9194
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]`

src/config.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
"domain": "example.com",
44
"puploadKeyGenLength": 64,
55
"public": false,
6+
"socket": "",
7+
"socketOnly": true,
68
"maxUploadSize": 50,
79
"markdown": true,
810
"port": 80,

src/server/app.js

Lines changed: 47 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ class ShareXAPI {
4545
this.c = c;
4646
this.monitorChannel = null;
4747
this.checkMonth();
48-
this.c.discordToken && this.c.discordToken !== undefined && this.c.discrdToken !== null
48+
this.c.discordToken && this.c.discordToken !== undefined && this.c.discordToken !== null
4949
? this.runDiscordBot()
5050
: this.log.verbose('No Discord Token provided...\nContinuing without Discord connection...');
5151
this.app = app;
@@ -60,16 +60,16 @@ class ShareXAPI {
6060

6161
/* Don't allow access if not accessed with configured domain */
6262
this.app.use((req, res, next) => {
63-
if(this.c.domain === '*') {
63+
if (this.c.domain === '*') {
6464
next();
65-
} else if(req.headers.host !== this.c.domain.toLowerCase() && !this.c.domain.includes('*')) {
65+
} else if (req.headers.host !== this.c.domain.toLowerCase() && !this.c.domain.includes('*')) {
6666
res.statusCode = 401;
6767
res.write('Error 401: Unauthorized Domain');
6868
return res.end();
69-
} else if(this.c.domain.includes('*')) {
70-
let reqParts = req.headers.host.toLowerCase().split('.');
71-
let domainParts = this.c.domain.toLowerCase().split('.')
72-
if(reqParts[1] === domainParts[1] && reqParts[2] === domainParts[2]) {
69+
} else if (this.c.domain.includes('*')) {
70+
const reqParts = req.headers.host.toLowerCase().split('.');
71+
const domainParts = this.c.domain.toLowerCase().split('.');
72+
if (reqParts[1] === domainParts[1] && reqParts[2] === domainParts[2]) {
7373
next();
7474
} else {
7575
res.statusCode = 401;
@@ -114,7 +114,7 @@ class ShareXAPI {
114114
this.app.use((req, res, next) => {
115115
if (req.method === 'GET') {
116116
const userIP = req.headers['x-forwarded-for'] || req.connection.remoteAddress || req.socket.remoteAddress || req.connection.socket.remoteAddress;
117-
let file = req.path;
117+
const file = req.path;
118118
// Not ignoring these files causes bloat in the db
119119
const ignored = ['/favicon.ico', '/assets/css/styles.min.css', '/highlight.pack.js', '/highlightjs-line-numbers.min.js', '/paste.css', '/atom-one-dark.css'];
120120
let exists = this.db.get('files').find({ path: file }).value();
@@ -172,7 +172,7 @@ class ShareXAPI {
172172
});
173173
// All files in /uploads/ are publicly accessible via http
174174
this.app.use(express.static(`${__dirname}/uploads/`, {
175-
extensions: this.c.admin.allowed.includes("*") ? null : this.c.admin.allowed,
175+
extensions: this.c.admin.allowed.includes('*') ? null : this.c.admin.allowed,
176176
}));
177177
this.app.use(express.static(`${__dirname}/views/`, {
178178
extensions: ['css'],
@@ -234,32 +234,47 @@ class ShareXAPI {
234234
* @returns {void}
235235
*/
236236
async startServer() {
237-
if (this.c.secure) {
238-
/** if the secure option is set to true in config,
239-
* it will boot in https so long as it detects
240-
* key.pem and cert.pem in the src directory
241-
*/
242-
if (fs.existsSync(`${__dirname}/../key.pem`) && fs.existsSync(`${__dirname}/../cert.pem`)) {
243-
const privateKey = fs.readFileSync(`${__dirname}/../key.pem`);
244-
const certificate = fs.readFileSync(`${__dirname}/../cert.pem`);
245-
https.createServer({
246-
key: privateKey,
247-
cert: certificate,
248-
}, this.app).listen(this.c.securePort, '0.0.0.0');
237+
if (!this.c.socketOnly || !this.c.socket) {
238+
if (this.c.secure) {
239+
/** if the secure option is set to true in config,
240+
* it will boot in https so long as it detects
241+
* key.pem and cert.pem in the src directory
242+
*/
243+
if (fs.existsSync(`${__dirname}/../key.pem`) && fs.existsSync(`${__dirname}/../cert.pem`)) {
244+
const privateKey = fs.readFileSync(`${__dirname}/../key.pem`);
245+
const certificate = fs.readFileSync(`${__dirname}/../cert.pem`);
246+
https.createServer({
247+
key: privateKey,
248+
cert: certificate,
249+
}, this.app).listen(this.c.securePort, '0.0.0.0');
250+
} else {
251+
// CF Flexible SSL
252+
/** if no key & cert pem files are detected,
253+
* it will still run in secure mode (returning urls with https)
254+
* so that it's compatible with CF flexible SSL
255+
* and SSL configurations via a reverse proxy */
256+
this.app.listen(this.c.securePort, '0.0.0.0', () => {
257+
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');
258+
});
259+
}
260+
this.log.success(`Secure server listening on port ${this.c.securePort}`);
249261
} else {
250-
// CF Flexible SSL
251-
/** if no key & cert pem files are detected,
252-
* it will still run in secure mode (returning urls with https)
253-
* so that it's compatible with CF flexible SSL
254-
* and SSL configurations via a reverse proxy */
255-
this.app.listen(this.c.securePort, '0.0.0.0', () => {
256-
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');
262+
this.app.listen(this.c.port, '0.0.0.0', () => {
263+
this.log.success(`Server listening on port ${this.c.port}`);
257264
});
258265
}
259-
this.log.success(`Secure server listening on port ${this.c.securePort}`);
260-
} else {
261-
this.app.listen(this.c.port, '0.0.0.0', () => {
262-
this.log.success(`Server listening on port ${this.c.port}`);
266+
}
267+
if (this.c.socket) {
268+
const socket = this.c.socket.toString();
269+
// https://stackoverflow.com/a/21385803
270+
fs.stat(socket, (err) => {
271+
if (!err) { fs.unlinkSync(socket); }
272+
this.app.listen(/** @type string */socket, () => {
273+
if (fs.chmodSync) {
274+
fs.chmodSync(socket, '777');
275+
}
276+
this.log.success(`Server listening on socket ${socket}`);
277+
});
263278
});
264279
}
265280
}

0 commit comments

Comments
 (0)