diff --git a/client/assets/fonts.css b/client/assets/fonts.css index 46e007aa..f3c586e3 100644 --- a/client/assets/fonts.css +++ b/client/assets/fonts.css @@ -2,14 +2,14 @@ font-family: 'Material Icons'; font-style: normal; font-weight: 400; - src: url(/fonts/MaterialIcons.woff2) format('woff2'); + src: url(~static/fonts/MaterialIcons.woff2) format('woff2'); } @font-face { font-family: 'Material Icons Outlined'; font-style: normal; font-weight: 400; - src: url(/fonts/MaterialIconsOutlined.woff2) format('woff2'); + src: url(~static/fonts/MaterialIconsOutlined.woff2) format('woff2'); } .material-icons { @@ -54,7 +54,7 @@ font-style: normal; font-weight: 400; font-display: swap; - src: url(/fonts/GentiumBookBasic.woff2) format('woff2'); + src: url(~static/fonts/GentiumBookBasic.woff2) format('woff2'); unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF; } @@ -64,7 +64,7 @@ font-style: normal; font-weight: 400; font-display: swap; - src: url(/fonts/GentiumBookBasic.woff2) format('woff2'); + src: url(~static/fonts/GentiumBookBasic.woff2) format('woff2'); unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; } @@ -74,7 +74,7 @@ font-style: normal; font-weight: 300; font-display: swap; - src: url(/fonts/Source_Sans_Pro/SourceSansPro-Light.ttf) format('truetype'); + src: url(~static/fonts/Source_Sans_Pro/SourceSansPro-Light.ttf) format('truetype'); unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F; } @@ -84,7 +84,7 @@ font-style: normal; font-weight: 300; font-display: swap; - src: url(/fonts/Source_Sans_Pro/SourceSansPro-Light.ttf) format('truetype'); + src: url(~static/fonts/Source_Sans_Pro/SourceSansPro-Light.ttf) format('truetype'); unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; } @@ -94,7 +94,7 @@ font-style: normal; font-weight: 300; font-display: swap; - src: url(/fonts/Source_Sans_Pro/SourceSansPro-Light.ttf) format('truetype'); + src: url(~static/fonts/Source_Sans_Pro/SourceSansPro-Light.ttf) format('truetype'); unicode-range: U+1F00-1FFF; } @@ -104,7 +104,7 @@ font-style: normal; font-weight: 300; font-display: swap; - src: url(/fonts/Source_Sans_Pro/SourceSansPro-Light.ttf) format('truetype'); + src: url(~static/fonts/Source_Sans_Pro/SourceSansPro-Light.ttf) format('truetype'); unicode-range: U+0370-03FF; } @@ -114,7 +114,7 @@ font-style: normal; font-weight: 300; font-display: swap; - src: url(/fonts/Source_Sans_Pro/SourceSansPro-Light.ttf) format('truetype'); + src: url(~static/fonts/Source_Sans_Pro/SourceSansPro-Light.ttf) format('truetype'); unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+1EA0-1EF9, U+20AB; } @@ -124,7 +124,7 @@ font-style: normal; font-weight: 300; font-display: swap; - src: url(/fonts/Source_Sans_Pro/SourceSansPro-Light.ttf) format('truetype'); + src: url(~static/fonts/Source_Sans_Pro/SourceSansPro-Light.ttf) format('truetype'); unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF; } @@ -134,7 +134,7 @@ font-style: normal; font-weight: 300; font-display: swap; - src: url(/fonts/Source_Sans_Pro/SourceSansPro-Light.ttf) format('truetype'); + src: url(~static/fonts/Source_Sans_Pro/SourceSansPro-Light.ttf) format('truetype'); unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; } @@ -144,7 +144,7 @@ font-style: normal; font-weight: 400; font-display: swap; - src: url(/fonts/Source_Sans_Pro/SourceSansPro-Regular.ttf) format('ttf'); + src: url(~static/fonts/Source_Sans_Pro/SourceSansPro-Regular.ttf) format('ttf'); unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F; } @@ -154,7 +154,7 @@ font-style: normal; font-weight: 400; font-display: swap; - src: url(/fonts/Source_Sans_Pro/SourceSansPro-Regular.ttf) format('truetype'); + src: url(~static/fonts/Source_Sans_Pro/SourceSansPro-Regular.ttf) format('truetype'); unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; } @@ -164,7 +164,7 @@ font-style: normal; font-weight: 400; font-display: swap; - src: url(/fonts/Source_Sans_Pro/SourceSansPro-Regular.ttf) format('truetype'); + src: url(~static/fonts/Source_Sans_Pro/SourceSansPro-Regular.ttf) format('truetype'); unicode-range: U+1F00-1FFF; } @@ -174,7 +174,7 @@ font-style: normal; font-weight: 400; font-display: swap; - src: url(/fonts/Source_Sans_Pro/SourceSansPro-Regular.ttf) format('truetype'); + src: url(~static/fonts/Source_Sans_Pro/SourceSansPro-Regular.ttf) format('truetype'); unicode-range: U+0370-03FF; } @@ -184,7 +184,7 @@ font-style: normal; font-weight: 400; font-display: swap; - src: url(/fonts/Source_Sans_Pro/SourceSansPro-Regular.ttf) format('truetype'); + src: url(~static/fonts/Source_Sans_Pro/SourceSansPro-Regular.ttf) format('truetype'); unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+1EA0-1EF9, U+20AB; } @@ -194,7 +194,7 @@ font-style: normal; font-weight: 400; font-display: swap; - src: url(/fonts/Source_Sans_Pro/SourceSansPro-Regular.ttf) format('truetype'); + src: url(~static/fonts/Source_Sans_Pro/SourceSansPro-Regular.ttf) format('truetype'); unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF; } @@ -204,7 +204,7 @@ font-style: normal; font-weight: 400; font-display: swap; - src: url(/fonts/Source_Sans_Pro/SourceSansPro-Regular.ttf) format('truetype'); + src: url(~static/fonts/Source_Sans_Pro/SourceSansPro-Regular.ttf) format('truetype'); unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; } @@ -214,7 +214,7 @@ font-style: normal; font-weight: 600; font-display: swap; - src: url(/fonts/Source_Sans_Pro/SourceSansPro-SemiBold.ttf) format('truetype'); + src: url(~static/fonts/Source_Sans_Pro/SourceSansPro-SemiBold.ttf) format('truetype'); unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F; } @@ -224,7 +224,7 @@ font-style: normal; font-weight: 600; font-display: swap; - src: url(/fonts/Source_Sans_Pro/SourceSansPro-SemiBold.ttf) format('truetype'); + src: url(~static/fonts/Source_Sans_Pro/SourceSansPro-SemiBold.ttf) format('truetype'); unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; } @@ -234,7 +234,7 @@ font-style: normal; font-weight: 600; font-display: swap; - src: url(/fonts/Source_Sans_Pro/SourceSansPro-SemiBold.ttf) format('truetype'); + src: url(~static/fonts/Source_Sans_Pro/SourceSansPro-SemiBold.ttf) format('truetype'); unicode-range: U+1F00-1FFF; } @@ -244,7 +244,7 @@ font-style: normal; font-weight: 600; font-display: swap; - src: url(/fonts/Source_Sans_Pro/SourceSansPro-SemiBold.ttf) format('truetype'); + src: url(~static/fonts/Source_Sans_Pro/SourceSansPro-SemiBold.ttf) format('truetype'); unicode-range: U+0370-03FF; } @@ -254,7 +254,7 @@ font-style: normal; font-weight: 600; font-display: swap; - src: url(/fonts/Source_Sans_Pro/SourceSansPro-SemiBold.ttf) format('truetype'); + src: url(~static/fonts/Source_Sans_Pro/SourceSansPro-SemiBold.ttf) format('truetype'); unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+1EA0-1EF9, U+20AB; } @@ -264,7 +264,7 @@ font-style: normal; font-weight: 600; font-display: swap; - src: url(/fonts/Source_Sans_Pro/SourceSansPro-SemiBold.ttf) format('truetype'); + src: url(~static/fonts/Source_Sans_Pro/SourceSansPro-SemiBold.ttf) format('truetype'); unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF; } @@ -274,7 +274,7 @@ font-style: normal; font-weight: 600; font-display: swap; - src: url(/fonts/Source_Sans_Pro/SourceSansPro-SemiBold.ttf) format('truetype'); + src: url(~static/fonts/Source_Sans_Pro/SourceSansPro-SemiBold.ttf) format('truetype'); unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; } @@ -284,7 +284,7 @@ font-style: normal; font-weight: 400; font-display: swap; - src: url(/fonts/Ubuntu_Mono/UbuntuMono-Regular.ttf) format('truetype'); + src: url(~static/fonts/Ubuntu_Mono/UbuntuMono-Regular.ttf) format('truetype'); unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F; } @@ -294,7 +294,7 @@ font-style: normal; font-weight: 400; font-display: swap; - src: url(/fonts/Ubuntu_Mono/UbuntuMono-Regular.ttf) format('truetype'); + src: url(~static/fonts/Ubuntu_Mono/UbuntuMono-Regular.ttf) format('truetype'); unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; } @@ -304,7 +304,7 @@ font-style: normal; font-weight: 400; font-display: swap; - src: url(/fonts/Ubuntu_Mono/UbuntuMono-Regular.ttf) format('truetype'); + src: url(~static/fonts/Ubuntu_Mono/UbuntuMono-Regular.ttf) format('truetype'); unicode-range: U+1F00-1FFF; } @@ -314,7 +314,7 @@ font-style: normal; font-weight: 400; font-display: swap; - src: url(/fonts/Ubuntu_Mono/UbuntuMono-Regular.ttf) format('truetype'); + src: url(~static/fonts/Ubuntu_Mono/UbuntuMono-Regular.ttf) format('truetype'); unicode-range: U+0370-03FF; } @@ -324,7 +324,7 @@ font-style: normal; font-weight: 400; font-display: swap; - src: url(/fonts/Ubuntu_Mono/UbuntuMono-Regular.ttf) format('truetype'); + src: url(~static/fonts/Ubuntu_Mono/UbuntuMono-Regular.ttf) format('truetype'); unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF; } @@ -334,6 +334,6 @@ font-style: normal; font-weight: 400; font-display: swap; - src: url(/fonts/Ubuntu_Mono/UbuntuMono-Regular.ttf) format('truetype'); + src: url(~static/fonts/Ubuntu_Mono/UbuntuMono-Regular.ttf) format('truetype'); unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; } \ No newline at end of file diff --git a/client/components/app/Appbar.vue b/client/components/app/Appbar.vue index 842d559f..8f30c5d9 100644 --- a/client/components/app/Appbar.vue +++ b/client/components/app/Appbar.vue @@ -3,7 +3,7 @@
- + @@ -216,7 +216,7 @@ export default { }, batchAutoMatchClick() { this.$store.commit('globals/setShowBatchQuickMatchModal', true) - }, + } }, mounted() { this.$eventBus.$on('bookshelf-total-entities', this.setBookshelfTotalEntities) diff --git a/client/components/cards/LazyBookCard.vue b/client/components/cards/LazyBookCard.vue index a368707d..c18c3117 100644 --- a/client/components/cards/LazyBookCard.vue +++ b/client/components/cards/LazyBookCard.vue @@ -182,7 +182,7 @@ export default { return this.mediaType === 'podcast' }, placeholderUrl() { - return '/book_placeholder.jpg' + return `${this.$config.routerBasePath}/book_placeholder.jpg` }, bookCoverSrc() { return this.store.getters['globals/getLibraryItemCoverSrc'](this._libraryItem, this.placeholderUrl) diff --git a/client/components/covers/AuthorImage.vue b/client/components/covers/AuthorImage.vue index 58363e87..c3cafaea 100644 --- a/client/components/covers/AuthorImage.vue +++ b/client/components/covers/AuthorImage.vue @@ -58,7 +58,7 @@ export default { if (!this.imagePath) return null if (process.env.NODE_ENV !== 'production') { // Testing - return `http://localhost:3333/api/authors/${this.authorId}/image?token=${this.userToken}&ts=${this.updatedAt}` + return `http://localhost:3333${this.$config.routerBasePath}/api/authors/${this.authorId}/image?token=${this.userToken}&ts=${this.updatedAt}` } return `/api/authors/${this.authorId}/image?token=${this.userToken}&ts=${this.updatedAt}` } diff --git a/client/components/covers/BookCover.vue b/client/components/covers/BookCover.vue index 838611ea..0d421955 100644 --- a/client/components/covers/BookCover.vue +++ b/client/components/covers/BookCover.vue @@ -94,7 +94,7 @@ export default { return this.author }, placeholderUrl() { - return '/book_placeholder.jpg' + return `${this.$config.routerBasePath}/book_placeholder.jpg` }, fullCoverUrl() { if (!this.libraryItem) return null diff --git a/client/components/covers/HoverBookCover.vue b/client/components/covers/HoverBookCover.vue deleted file mode 100644 index 7171061e..00000000 --- a/client/components/covers/HoverBookCover.vue +++ /dev/null @@ -1,41 +0,0 @@ - - - \ No newline at end of file diff --git a/client/components/modals/player/QueueItemRow.vue b/client/components/modals/player/QueueItemRow.vue index f9378dc7..fcb2c788 100644 --- a/client/components/modals/player/QueueItemRow.vue +++ b/client/components/modals/player/QueueItemRow.vue @@ -55,7 +55,7 @@ export default { return this.item.coverPath }, coverUrl() { - if (!this.coverPath) return '/book_placeholder.jpg' + if (!this.coverPath) return `${this.$config.routerBasePath}/book_placeholder.jpg` return this.$store.getters['globals/getLibraryItemCoverSrcById'](this.libraryItemId) }, bookCoverAspectRatio() { diff --git a/client/components/modals/rssfeed/ViewModal.vue b/client/components/modals/rssfeed/ViewModal.vue index aa018e82..95234114 100644 --- a/client/components/modals/rssfeed/ViewModal.vue +++ b/client/components/modals/rssfeed/ViewModal.vue @@ -117,7 +117,7 @@ export default { serverAddress: window.origin, slug: this.newFeedSlug } - if (this.$isDev) payload.serverAddress = 'http://localhost:3333' + if (this.$isDev) payload.serverAddress = `http://localhost:3333${this.$config.routerBasePath}` console.log('Payload', payload) this.$axios diff --git a/client/components/tables/LibraryFilesTable.vue b/client/components/tables/LibraryFilesTable.vue index 00d0ed0b..05998f85 100644 --- a/client/components/tables/LibraryFilesTable.vue +++ b/client/components/tables/LibraryFilesTable.vue @@ -34,7 +34,7 @@
- download + download diff --git a/client/components/tables/TracksTable.vue b/client/components/tables/TracksTable.vue index 89f366fd..d0f93ff4 100644 --- a/client/components/tables/TracksTable.vue +++ b/client/components/tables/TracksTable.vue @@ -38,7 +38,7 @@ {{ $secondsToTimestamp(track.duration) }} - download + download diff --git a/client/nuxt.config.js b/client/nuxt.config.js index c5f9436f..ede30503 100644 --- a/client/nuxt.config.js +++ b/client/nuxt.config.js @@ -6,13 +6,14 @@ module.exports = { target: 'static', dev: process.env.NODE_ENV !== 'production', env: { - serverUrl: process.env.NODE_ENV === 'production' ? '' : 'http://localhost:3333', + serverUrl: process.env.NODE_ENV === 'production' ? process.env.ROUTER_BASE_PATH : 'http://localhost:3333', chromecastReceiver: 'FD1F76C5' }, telemetry: false, publicRuntimeConfig: { - version: pkg.version + version: pkg.version, + routerBasePath: process.env.ROUTER_BASE_PATH || '' }, // Global page headers: https://go.nuxtjs.dev/config-head @@ -28,15 +29,17 @@ module.exports = { ], script: [ { - src: '/libs/sortable.js' + src: (process.env.ROUTER_BASE_PATH || '') + '/libs/sortable.js' } ], link: [ - { rel: 'icon', type: 'image/x-icon', href: '/favicon.ico' } + { rel: 'icon', type: 'image/x-icon', href: (process.env.ROUTER_BASE_PATH || '') + '/favicon.ico' } ] }, - router: {}, + router: { + base: process.env.ROUTER_BASE_PATH || '' + }, // Global CSS: https://go.nuxtjs.dev/config-css css: [ @@ -73,8 +76,7 @@ module.exports = { proxy: { '/dev/': { target: 'http://localhost:3333', pathRewrite: { '^/dev/': '' } }, '/ebook/': { target: process.env.NODE_ENV !== 'production' ? 'http://localhost:3333' : '/' }, - '/s/': { target: process.env.NODE_ENV !== 'production' ? 'http://localhost:3333' : '/' }, - '/metadata/': { target: process.env.NODE_ENV !== 'production' ? 'http://localhost:3333' : '/' } + '/s/': { target: process.env.NODE_ENV !== 'production' ? 'http://localhost:3333' + process.env : '/' }, }, io: { @@ -89,7 +91,7 @@ module.exports = { // Axios module configuration: https://go.nuxtjs.dev/config-axios axios: { - baseURL: process.env.serverUrl || '' + baseURL: process.env.ROUTER_BASE_PATH || '' }, // nuxt/pwa https://pwa.nuxtjs.org @@ -109,15 +111,15 @@ module.exports = { background_color: '#373838', icons: [ { - src: '/icon.svg', + src: (process.env.ROUTER_BASE_PATH || '') + '/icon.svg', sizes: "64x64" }, { - src: '/icon.svg', + src: (process.env.ROUTER_BASE_PATH || '') + '/icon.svg', sizes: "192x192" }, { - src: '/icon.svg', + src: (process.env.ROUTER_BASE_PATH || '') + '/icon.svg', sizes: "512x512" } ] diff --git a/client/pages/audiobook/_id/chapters.vue b/client/pages/audiobook/_id/chapters.vue index f97c83f9..f3067e2b 100644 --- a/client/pages/audiobook/_id/chapters.vue +++ b/client/pages/audiobook/_id/chapters.vue @@ -304,7 +304,7 @@ export default { const audioEl = this.audioEl || document.createElement('audio') var src = audioTrack.contentUrl + `?token=${this.userToken}` if (this.$isDev) { - src = `http://localhost:3333${src}` + src = `http://localhost:3333${this.$config.routerBasePath}${src}` } console.log('src', src) diff --git a/client/plugins/axios.js b/client/plugins/axios.js index 88468b2a..e839e382 100644 --- a/client/plugins/axios.js +++ b/client/plugins/axios.js @@ -1,4 +1,4 @@ -export default function ({ $axios, store }) { +export default function ({ $axios, store, $config }) { $axios.onRequest(config => { if (!config.url) { console.error('Axios request invalid config', config) diff --git a/client/plugins/init.client.js b/client/plugins/init.client.js index 75841d64..a208f387 100644 --- a/client/plugins/init.client.js +++ b/client/plugins/init.client.js @@ -143,8 +143,10 @@ export { encode, decode } -export default ({ app }, inject) => { +export default ({ app, store }, inject) => { app.$decode = decode app.$encode = encode inject('isDev', process.env.NODE_ENV !== 'production') + + store.commit('setRouterBasePath', app.$config.routerBasePath) } \ No newline at end of file diff --git a/client/store/globals.js b/client/store/globals.js index 8b1c3d5e..96970629 100644 --- a/client/store/globals.js +++ b/client/store/globals.js @@ -32,7 +32,8 @@ export const state = () => ({ }) export const getters = { - getLibraryItemCoverSrc: (state, getters, rootState, rootGetters) => (libraryItem, placeholder = '/book_placeholder.jpg') => { + getLibraryItemCoverSrc: (state, getters, rootState, rootGetters) => (libraryItem, placeholder = null) => { + if (!placeholder) placeholder = `${rootState.routerBasePath}/book_placeholder.jpg` if (!libraryItem) return placeholder var media = libraryItem.media if (!media || !media.coverPath || media.coverPath === placeholder) return placeholder @@ -45,18 +46,19 @@ export const getters = { const libraryItemId = libraryItem.libraryItemId || libraryItem.id // Workaround for /users/:id page showing media progress covers if (process.env.NODE_ENV !== 'production') { // Testing - return `http://localhost:3333/api/items/${libraryItemId}/cover?token=${userToken}&ts=${lastUpdate}` + return `http://localhost:3333${rootState.routerBasePath}/api/items/${libraryItemId}/cover?token=${userToken}&ts=${lastUpdate}` } - return `/api/items/${libraryItemId}/cover?token=${userToken}&ts=${lastUpdate}` + return `${rootState.routerBasePath}/api/items/${libraryItemId}/cover?token=${userToken}&ts=${lastUpdate}` }, - getLibraryItemCoverSrcById: (state, getters, rootState, rootGetters) => (libraryItemId, placeholder = '/book_placeholder.jpg') => { + getLibraryItemCoverSrcById: (state, getters, rootState, rootGetters) => (libraryItemId, placeholder = null) => { + if (!placeholder) placeholder = `${rootState.routerBasePath}/book_placeholder.jpg` if (!libraryItemId) return placeholder var userToken = rootGetters['user/getToken'] if (process.env.NODE_ENV !== 'production') { // Testing - return `http://localhost:3333/api/items/${libraryItemId}/cover?token=${userToken}` + return `http://localhost:3333${rootState.routerBasePath}/api/items/${libraryItemId}/cover?token=${userToken}` } - return `/api/items/${libraryItemId}/cover?token=${userToken}` + return `${rootState.routerBasePath}/api/items/${libraryItemId}/cover?token=${userToken}` } } diff --git a/client/store/index.js b/client/store/index.js index 96e3129a..f55d6077 100644 --- a/client/store/index.js +++ b/client/store/index.js @@ -25,7 +25,8 @@ export const state = () => ({ bookshelfBookIds: [], openModal: null, innerModalOpen: false, - lastBookshelfScrollData: {} + lastBookshelfScrollData: {}, + routerBasePath: '/' }) export const getters = { @@ -119,6 +120,9 @@ export const actions = { } export const mutations = { + setRouterBasePath(state, rbp) { + state.routerBasePath = rbp + }, setSource(state, source) { state.Source = source }, diff --git a/index.js b/index.js index c15a9e0b..19a24d82 100644 --- a/index.js +++ b/index.js @@ -11,6 +11,7 @@ if (isDev) { process.env.FFMPEG_PATH = devEnv.FFmpegPath process.env.FFPROBE_PATH = devEnv.FFProbePath process.env.SOURCE = 'local' + process.env.ROUTER_BASE_PATH = devEnv.RouterBasePath || '' } const PORT = process.env.PORT || 80 @@ -20,8 +21,9 @@ const METADATA_PATH = process.env.METADATA_PATH || '/metadata' const UID = process.env.AUDIOBOOKSHELF_UID || 99 const GID = process.env.AUDIOBOOKSHELF_GID || 100 const SOURCE = process.env.SOURCE || 'docker' +const ROUTER_BASE_PATH = process.env.ROUTER_BASE_PATH || '' console.log('Config', CONFIG_PATH, METADATA_PATH) -const Server = new server(SOURCE, PORT, HOST, UID, GID, CONFIG_PATH, METADATA_PATH) +const Server = new server(SOURCE, PORT, HOST, UID, GID, CONFIG_PATH, METADATA_PATH, ROUTER_BASE_PATH) Server.start() diff --git a/prod.js b/prod.js index de7a6417..57417033 100644 --- a/prod.js +++ b/prod.js @@ -26,8 +26,9 @@ const METADATA_PATH = inputMetadata || process.env.METADATA_PATH || Path.resolve const UID = 99 const GID = 100 const SOURCE = options.source || 'debian' +const ROUTER_BASE_PATH = process.env.ROUTER_BASE_PATH || '' console.log(process.env.NODE_ENV, 'Config', CONFIG_PATH, METADATA_PATH) -const Server = new server(SOURCE, PORT, HOST, UID, GID, CONFIG_PATH, METADATA_PATH) +const Server = new server(SOURCE, PORT, HOST, UID, GID, CONFIG_PATH, METADATA_PATH, ROUTER_BASE_PATH) Server.start() diff --git a/server/Server.js b/server/Server.js index 44038d55..71213960 100644 --- a/server/Server.js +++ b/server/Server.js @@ -36,7 +36,7 @@ const RssFeedManager = require('./managers/RssFeedManager') const CronManager = require('./managers/CronManager') class Server { - constructor(SOURCE, PORT, HOST, UID, GID, CONFIG_PATH, METADATA_PATH) { + constructor(SOURCE, PORT, HOST, UID, GID, CONFIG_PATH, METADATA_PATH, ROUTER_BASE_PATH) { this.Port = PORT this.Host = HOST global.Source = SOURCE @@ -44,6 +44,7 @@ class Server { global.Gid = isNaN(GID) ? 0 : Number(GID) global.ConfigPath = Path.normalize(CONFIG_PATH) global.MetadataPath = Path.normalize(METADATA_PATH) + global.RouterBasePath = ROUTER_BASE_PATH // Fix backslash if not on Windows if (process.platform !== 'win32') { @@ -170,29 +171,32 @@ class Server { await this.init() const app = express() + const router = express.Router() + app.use(global.RouterBasePath, router) + this.server = http.createServer(app) - app.use(this.auth.cors) - app.use(fileUpload()) - app.use(express.urlencoded({ extended: true, limit: "5mb" })); - app.use(express.json({ limit: "5mb" })) + router.use(this.auth.cors) + router.use(fileUpload()) + router.use(express.urlencoded({ extended: true, limit: "5mb" })); + router.use(express.json({ limit: "5mb" })) // Static path to generated nuxt const distPath = Path.join(global.appRoot, '/client/dist') - app.use(express.static(distPath)) + router.use(express.static(distPath)) // Metadata folder static path - app.use('/metadata', this.authMiddleware.bind(this), express.static(global.MetadataPath)) + router.use('/metadata', this.authMiddleware.bind(this), express.static(global.MetadataPath)) // Static folder - app.use(express.static(Path.join(global.appRoot, 'static'))) + router.use(express.static(Path.join(global.appRoot, 'static'))) - app.use('/api', this.authMiddleware.bind(this), this.apiRouter.router) - app.use('/hls', this.authMiddleware.bind(this), this.hlsRouter.router) - app.use('/s', this.authMiddleware.bind(this), this.staticRouter.router) + router.use('/api', this.authMiddleware.bind(this), this.apiRouter.router) + router.use('/hls', this.authMiddleware.bind(this), this.hlsRouter.router) + router.use('/s', this.authMiddleware.bind(this), this.staticRouter.router) // EBook static file routes - app.get('/ebook/:library/:folder/*', (req, res) => { + router.get('/ebook/:library/:folder/*', (req, res) => { var library = this.db.libraries.find(lib => lib.id === req.params.library) if (!library) return res.sendStatus(404) var folder = library.folders.find(fol => fol.id === req.params.folder) @@ -204,14 +208,14 @@ class Server { }) // RSS Feed temp route - app.get('/feed/:id', (req, res) => { + router.get('/feed/:id', (req, res) => { Logger.info(`[Server] Requesting rss feed ${req.params.id}`) this.rssFeedManager.getFeed(req, res) }) - app.get('/feed/:id/cover', (req, res) => { + router.get('/feed/:id/cover', (req, res) => { this.rssFeedManager.getFeedCover(req, res) }) - app.get('/feed/:id/item/:episodeId/*', (req, res) => { + router.get('/feed/:id/item/:episodeId/*', (req, res) => { Logger.debug(`[Server] Requesting rss feed episode ${req.params.id}/${req.params.episodeId}`) this.rssFeedManager.getFeedItem(req, res) }) @@ -234,18 +238,18 @@ class Server { '/config/users/:id/sessions', '/collection/:id' ] - dyanimicRoutes.forEach((route) => app.get(route, (req, res) => res.sendFile(Path.join(distPath, 'index.html')))) + dyanimicRoutes.forEach((route) => router.get(route, (req, res) => res.sendFile(Path.join(distPath, 'index.html')))) - app.post('/login', this.getLoginRateLimiter(), (req, res) => this.auth.login(req, res, this.rssFeedManager.feedsArray)) - app.post('/logout', this.authMiddleware.bind(this), this.logout.bind(this)) - app.post('/init', (req, res) => { + router.post('/login', this.getLoginRateLimiter(), (req, res) => this.auth.login(req, res, this.rssFeedManager.feedsArray)) + router.post('/logout', this.authMiddleware.bind(this), this.logout.bind(this)) + router.post('/init', (req, res) => { if (this.db.hasRootUser) { Logger.error(`[Server] attempt to init server when server already has a root user`) return res.sendStatus(500) } this.initializeServer(req, res) }) - app.get('/status', (req, res) => { + router.get('/status', (req, res) => { // status check for client to see if server has been initialized // server has been initialized if a root user exists const payload = { @@ -257,7 +261,7 @@ class Server { } res.json(payload) }) - app.get('/ping', (req, res) => { + router.get('/ping', (req, res) => { Logger.info('Received ping') res.json({ success: true }) }) diff --git a/server/objects/files/AudioTrack.js b/server/objects/files/AudioTrack.js index 4fa6ff8d..dc7b75b6 100644 --- a/server/objects/files/AudioTrack.js +++ b/server/objects/files/AudioTrack.js @@ -29,7 +29,7 @@ class AudioTrack { this.startOffset = startOffset this.duration = audioFile.duration this.title = audioFile.metadata.filename || '' - this.contentUrl = Path.join(`/s/item/${itemId}`, encodeUriPath(audioFile.metadata.relPath)) + this.contentUrl = Path.join(`${global.RouterBasePath}/s/item/${itemId}`, encodeUriPath(audioFile.metadata.relPath)) this.mimeType = audioFile.mimeType this.metadata = audioFile.metadata.clone() } diff --git a/server/objects/files/VideoTrack.js b/server/objects/files/VideoTrack.js index f9241ad7..7c4128f5 100644 --- a/server/objects/files/VideoTrack.js +++ b/server/objects/files/VideoTrack.js @@ -26,7 +26,7 @@ class VideoTrack { this.index = videoFile.index this.duration = videoFile.duration this.title = videoFile.metadata.filename || '' - this.contentUrl = Path.join(`/s/item/${itemId}`, encodeUriPath(videoFile.metadata.relPath)) + this.contentUrl = Path.join(`${global.RouterBasePath}/s/item/${itemId}`, encodeUriPath(videoFile.metadata.relPath)) this.mimeType = videoFile.mimeType this.metadata = videoFile.metadata.clone() }