fixed broken ipv6 on linux, and weird implementation in general
| @@ -28,7 +28,6 @@ import multer from 'multer'; | |||
| 28 | import responseTime from 'response-time'; | 28 | import responseTime from 'response-time'; |
| 29 | import helmet from 'helmet'; | 29 | import helmet from 'helmet'; |
| 30 | import bodyParser from 'body-parser'; | 30 | import bodyParser from 'body-parser'; |
| 31 | import { getMatch, IPMatch, IPSubnetwork, IPRange, matches } from 'ip-matching'; | ||
| 32 | 31 | ||
| 33 | // net related library imports | 32 | // net related library imports |
| 34 | import fetch from 'node-fetch'; | 33 | import fetch from 'node-fetch'; |
| @@ -70,6 +69,7 @@ import { | |||
| 70 | removeColorFormatting, | 69 | removeColorFormatting, |
| 71 | getSeparator, | 70 | getSeparator, |
| 72 | stringToBool, | 71 | stringToBool, |
| 72 | urlHostnameToIPv6, | ||
| 73 | } from './src/util.js'; | 73 | } from './src/util.js'; |
| 74 | import { UPLOADS_DIRECTORY } from './src/constants.js'; | 74 | import { UPLOADS_DIRECTORY } from './src/constants.js'; |
| 75 | import { ensureThumbnailCache } from './src/endpoints/thumbnails.js'; | 75 | import { ensureThumbnailCache } from './src/endpoints/thumbnails.js'; |
| @@ -388,14 +388,14 @@ async function getHasIP() { | |||
| 388 | let hasIPv4 = false; | 388 | let hasIPv4 = false; |
| 389 | let hasIPv4Local = false; | 389 | let hasIPv4Local = false; |
| 390 | const interfaces = os.networkInterfaces(); | 390 | const interfaces = os.networkInterfaces(); |
| 391 | const linkLocalV6 = getMatch('fe80::/10'); | ||
| 392 | 391 | ||
| 393 | for (const iface of Object.values(interfaces)) { | 392 | for (const iface of Object.values(interfaces)) { |
| 394 | if (iface === undefined) { | 393 | if (iface === undefined) { |
| 395 | continue; | 394 | continue; |
| 396 | } | 395 | } |
| 397 | for (const info of iface) { | 396 | for (const info of iface) { |
| 398 | if (info.family === 'IPv6' && !linkLocalV6.matches(info.address)) { | 397 | //! change this if you ever add configurable addresses to bind to |
| 398 | if (info.family === 'IPv6') { | ||
| 399 | hasIPv6 = true; | 399 | hasIPv6 = true; |
| 400 | if (info.internal === true) { | 400 | if (info.internal === true) { |
| 401 | hasIPv6Local = true; | 401 | hasIPv6Local = true; |
| @@ -878,7 +878,7 @@ function handleServerListenFail(v6Failed, v4Failed, useIPv6, useIPv4) { | |||
| 878 | * @returns {Promise<void>} A promise that resolves when the server is listening | 878 | * @returns {Promise<void>} A promise that resolves when the server is listening |
| 879 | * @throws {Error} If the server fails to start | 879 | * @throws {Error} If the server fails to start |
| 880 | */ | 880 | */ |
| 881 | function createHttpsServer(url) { | 881 | function createHttpsServer(url, ipVersion) { |
| 882 | return new Promise((resolve, reject) => { | 882 | return new Promise((resolve, reject) => { |
| 883 | const server = https.createServer( | 883 | const server = https.createServer( |
| 884 | { | 884 | { |
| @@ -887,7 +887,15 @@ function createHttpsServer(url) { | |||
| 887 | }, app); | 887 | }, app); |
| 888 | server.on('error', reject); | 888 | server.on('error', reject); |
| 889 | server.on('listening', resolve); | 889 | server.on('listening', resolve); |
| 890 | server.listen(Number(url.port || 443), url.hostname); | 890 | |
| 891 | let host = url.hostname | ||
| 892 | if (ipVersion === 6) host = urlHostnameToIPv6(url.hostname); | ||
| 893 | server.listen({ | ||
| 894 | host: host, | ||
| 895 | port: Number(url.port || 443), | ||
| 896 | // see https://nodejs.org/api/net.html#serverlisten for why ipv6Only is used | ||
| 897 | ipv6Only: true, | ||
| 898 | }); | ||
| 891 | }); | 899 | }); |
| 892 | } | 900 | } |
| 893 | 901 | ||
| @@ -897,12 +905,20 @@ function createHttpsServer(url) { | |||
| 897 | * @returns {Promise<void>} A promise that resolves when the server is listening | 905 | * @returns {Promise<void>} A promise that resolves when the server is listening |
| 898 | * @throws {Error} If the server fails to start | 906 | * @throws {Error} If the server fails to start |
| 899 | */ | 907 | */ |
| 900 | function createHttpServer(url) { | 908 | function createHttpServer(url, ipVersion) { |
| 901 | return new Promise((resolve, reject) => { | 909 | return new Promise((resolve, reject) => { |
| 902 | const server = http.createServer(app); | 910 | const server = http.createServer(app); |
| 903 | server.on('error', reject); | 911 | server.on('error', reject); |
| 904 | server.on('listening', resolve); | 912 | server.on('listening', resolve); |
| 905 | server.listen(Number(url.port || 80), url.hostname); | 913 | |
| 914 | let host = url.hostname | ||
| 915 | if (ipVersion === 6) host = urlHostnameToIPv6(url.hostname); | ||
| 916 | server.listen({ | ||
| 917 | host: host, | ||
| 918 | port: Number(url.port || 80), | ||
| 919 | // see https://nodejs.org/api/net.html#serverlisten for why ipv6Only is used | ||
| 920 | ipv6Only: true, | ||
| 921 | }); | ||
| 906 | }); | 922 | }); |
| 907 | } | 923 | } |
| 908 | 924 | ||
| @@ -914,7 +930,7 @@ async function startHTTPorHTTPS(useIPv6, useIPv4) { | |||
| 914 | 930 | ||
| 915 | if (useIPv6) { | 931 | if (useIPv6) { |
| 916 | try { | 932 | try { |
| 917 | await createFunc(tavernUrlV6); | 933 | await createFunc(tavernUrlV6, 6); |
| 918 | } catch (error) { | 934 | } catch (error) { |
| 919 | console.error('non-fatal error: failed to start server on IPv6'); | 935 | console.error('non-fatal error: failed to start server on IPv6'); |
| 920 | console.error(error); | 936 | console.error(error); |
| @@ -925,7 +941,7 @@ async function startHTTPorHTTPS(useIPv6, useIPv4) { | |||
| 925 | 941 | ||
| 926 | if (useIPv4) { | 942 | if (useIPv4) { |
| 927 | try { | 943 | try { |
| 928 | await createFunc(tavernUrl); | 944 | await createFunc(tavernUrl, 4); |
| 929 | } catch (error) { | 945 | } catch (error) { |
| 930 | console.error('non-fatal error: failed to start server on IPv4'); | 946 | console.error('non-fatal error: failed to start server on IPv4'); |
| 931 | console.error(error); | 947 | console.error(error); |