diff --git a/package.json b/package.json index 9da491159a..8a5e3dcc11 100644 --- a/package.json +++ b/package.json @@ -71,6 +71,7 @@ "mime": "^4.1.0", "nanoid": "^5.1.7", "next": "16.2.6", + "ip-address": "^10.2.0", "node-cache": "5.1.2", "node-gyp": "12.2.0", "node-schedule": "2.1.1", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 167cc4d377..0f33b8a92a 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -110,6 +110,9 @@ importers: humanize-duration: specifier: ^3.33.2 version: 3.33.2 + ip-address: + specifier: ^10.2.0 + version: 10.2.0 js-yaml: specifier: ^4.1.1 version: 4.1.1 @@ -4868,6 +4871,10 @@ packages: resolution: {integrity: sha512-XXADHxXmvT9+CRxhXg56LJovE+bmWnEWB78LB83VZTprKTmaC5QfruXocxzTZ2Kl0DNwKuBdlIhjL8LeY8Sf8Q==} engines: {node: '>= 12'} + ip-address@10.2.0: + resolution: {integrity: sha512-/+S6j4E9AHvW9SWMSEY9Xfy66O5PWvVEJ08O0y5JGyEKQpojb0K0GKpz/v5HJ/G0vi3D2sjGK78119oXZeE0qA==} + engines: {node: '>= 12'} + ip-address@9.0.5: resolution: {integrity: sha512-zHtQzGojZXTwZTHQqra+ETKd4Sn3vgi7uBmlPoXVWZqYvuKmtI0l/VZTjqGmJY9x88GGOaZ9+G9ES8hC4T4X8g==} engines: {node: '>= 12'} @@ -13283,6 +13290,8 @@ snapshots: ip-address@10.1.0: {} + ip-address@10.2.0: {} + ip-address@9.0.5: dependencies: jsbn: 1.1.0 diff --git a/server/index.ts b/server/index.ts index 37b41fd60d..38d1f1e14b 100644 --- a/server/index.ts +++ b/server/index.ts @@ -267,19 +267,27 @@ app const port = Number(process.env.PORT) || 5055; const host = process.env.HOST; + let httpServer; if (host) { - server.listen(port, host, () => { + httpServer = server.listen(port, host, () => { logger.info(`Server ready on ${host} port ${port}`, { label: 'Server', }); }); } else { - server.listen(port, () => { + httpServer = server.listen(port, () => { logger.info(`Server ready on port ${port}`, { label: 'Server', }); }); } + httpServer.on('error', (err) => { + logger.error('Failed to start server', { + label: 'Server', + message: err.message, + }); + process.exit(1); + }); }) .catch((err) => { logger.error(err.stack); diff --git a/src/pages/_app.tsx b/src/pages/_app.tsx index 833ecad66b..4159fa5268 100644 --- a/src/pages/_app.tsx +++ b/src/pages/_app.tsx @@ -11,6 +11,7 @@ import type { User } from '@app/hooks/useUser'; import { Permission, useUser } from '@app/hooks/useUser'; import '@app/styles/globals.css'; import { polyfillIntl } from '@app/utils/polyfillIntl'; +import { getHostAndPort } from '@app/utils/urlHelper'; import '@fontsource-variable/inter'; import { MediaServerType } from '@server/constants/server'; import type { PublicSettingsResponse } from '@server/interfaces/api/settingsInterfaces'; @@ -266,9 +267,7 @@ CoreApp.getInitialProps = async (initialProps) => { if (ctx.res) { // Check if app is initialized and redirect if necessary const response = await axios.get( - `http://${process.env.HOST || 'localhost'}:${ - process.env.PORT || 5055 - }/api/v1/settings/public` + `http://${getHostAndPort()}/api/v1/settings/public` ); currentSettings = response.data; @@ -286,9 +285,7 @@ CoreApp.getInitialProps = async (initialProps) => { try { // Attempt to get the user by running a request to the local api const response = await axios.get( - `http://${process.env.HOST || 'localhost'}:${ - process.env.PORT || 5055 - }/api/v1/auth/me`, + `http://${getHostAndPort()}/api/v1/auth/me`, { headers: ctx.req && ctx.req.headers.cookie diff --git a/src/pages/collection/[collectionId]/index.tsx b/src/pages/collection/[collectionId]/index.tsx index e555e41e59..ff8bbbd898 100644 --- a/src/pages/collection/[collectionId]/index.tsx +++ b/src/pages/collection/[collectionId]/index.tsx @@ -1,4 +1,5 @@ import CollectionDetails from '@app/components/CollectionDetails'; +import { getHostAndPort } from '@app/utils/urlHelper'; import type { Collection } from '@server/models/Collection'; import axios from 'axios'; import type { GetServerSideProps, NextPage } from 'next'; @@ -15,9 +16,7 @@ export const getServerSideProps: GetServerSideProps< CollectionPageProps > = async (ctx) => { const response = await axios.get( - `http://${process.env.HOST || 'localhost'}:${ - process.env.PORT || 5055 - }/api/v1/collection/${ctx.query.collectionId}`, + `http://${getHostAndPort()}/api/v1/collection/${ctx.query.collectionId}`, { headers: ctx.req?.headers?.cookie ? { cookie: ctx.req.headers.cookie } diff --git a/src/pages/movie/[movieId]/index.tsx b/src/pages/movie/[movieId]/index.tsx index d9788a2023..24fd3a826f 100644 --- a/src/pages/movie/[movieId]/index.tsx +++ b/src/pages/movie/[movieId]/index.tsx @@ -1,4 +1,5 @@ import MovieDetails from '@app/components/MovieDetails'; +import { getHostAndPort } from '@app/utils/urlHelper'; import type { MovieDetails as MovieDetailsType } from '@server/models/Movie'; import axios from 'axios'; import type { GetServerSideProps, NextPage } from 'next'; @@ -15,9 +16,7 @@ export const getServerSideProps: GetServerSideProps = async ( ctx ) => { const response = await axios.get( - `http://${process.env.HOST || 'localhost'}:${ - process.env.PORT || 5055 - }/api/v1/movie/${ctx.query.movieId}`, + `http://${getHostAndPort()}/api/v1/movie/${ctx.query.movieId}`, { headers: ctx.req?.headers?.cookie ? { cookie: ctx.req.headers.cookie } diff --git a/src/pages/tv/[tvId]/index.tsx b/src/pages/tv/[tvId]/index.tsx index 9659d82ca8..599a7985e0 100644 --- a/src/pages/tv/[tvId]/index.tsx +++ b/src/pages/tv/[tvId]/index.tsx @@ -1,4 +1,5 @@ import TvDetails from '@app/components/TvDetails'; +import { getHostAndPort } from '@app/utils/urlHelper'; import type { TvDetails as TvDetailsType } from '@server/models/Tv'; import axios from 'axios'; import type { GetServerSideProps, NextPage } from 'next'; @@ -15,9 +16,7 @@ export const getServerSideProps: GetServerSideProps = async ( ctx ) => { const response = await axios.get( - `http://${process.env.HOST || 'localhost'}:${ - process.env.PORT || 5055 - }/api/v1/tv/${ctx.query.tvId}`, + `http://${getHostAndPort()}/api/v1/tv/${ctx.query.tvId}`, { headers: ctx.req?.headers?.cookie ? { cookie: ctx.req.headers.cookie } diff --git a/src/utils/urlHelper.ts b/src/utils/urlHelper.ts new file mode 100644 index 0000000000..c79550a905 --- /dev/null +++ b/src/utils/urlHelper.ts @@ -0,0 +1,12 @@ +import { Address6 } from 'ip-address'; + +export function getHostAndPort(): string { + let host = process.env.HOST || 'localhost'; + if (Address6.isValid(host)) { + // If host is an IPv6 literal it needs to be placed in square brackets + host = `[${host}]`; + } + + const port = Number(process.env.PORT) || 5055; + return `${host}:${port}`; +}