mirror of
https://github.com/stashapp/stash.git
synced 2025-12-06 08:26:00 +01:00
Support subpaths when serving stash through a reverse proxy (#1719)
* Support subpaths when serving stash through a reverse proxy * Add README documentation Co-authored-by: WithoutPants <53250216+WithoutPants@users.noreply.github.com>
This commit is contained in:
parent
f3c8407c40
commit
a4ed9515c7
9 changed files with 44 additions and 9 deletions
|
|
@ -68,6 +68,10 @@ This command would need customizing for your environment. [This link](https://s
|
||||||
|
|
||||||
Once you have a certificate and key file name them `stash.crt` and `stash.key` and place them in the same directory as the `config.yml` file, or the `~/.stash` directory. Stash detects these and starts up using HTTPS rather than HTTP.
|
Once you have a certificate and key file name them `stash.crt` and `stash.key` and place them in the same directory as the `config.yml` file, or the `~/.stash` directory. Stash detects these and starts up using HTTPS rather than HTTP.
|
||||||
|
|
||||||
|
## Basepath rewriting
|
||||||
|
|
||||||
|
The basepath defaults to `/`. When running stash via a reverse proxy in a subpath, the basepath can be changed by having the reverse proxy pass `X-Forwarded-Prefix` (and optionally `X-Forwarded-Port`) headers. When detects these headers, it alters the basepath URL of the UI.
|
||||||
|
|
||||||
# Customization
|
# Customization
|
||||||
|
|
||||||
## Themes and CSS Customization
|
## Themes and CSS Customization
|
||||||
|
|
|
||||||
|
|
@ -258,7 +258,15 @@ func Start() {
|
||||||
|
|
||||||
if ext == ".html" || ext == "" {
|
if ext == ".html" || ext == "" {
|
||||||
data, _ := uiBox.Find("index.html")
|
data, _ := uiBox.Find("index.html")
|
||||||
_, _ = w.Write(data)
|
|
||||||
|
prefix := ""
|
||||||
|
if r.Header.Get("X-Forwarded-Prefix") != "" {
|
||||||
|
prefix = strings.TrimRight(r.Header.Get("X-Forwarded-Prefix"), "/")
|
||||||
|
}
|
||||||
|
|
||||||
|
baseURLIndex := strings.Replace(string(data), "%BASE_URL%", prefix+"/", 2)
|
||||||
|
baseURLIndex = strings.Replace(baseURLIndex, "base href=\"/\"", fmt.Sprintf("base href=\"%s\"", prefix+"/"), 2)
|
||||||
|
_, _ = w.Write([]byte(baseURLIndex))
|
||||||
} else {
|
} else {
|
||||||
isStatic, _ := path.Match("/static/*/*", r.URL.Path)
|
isStatic, _ := path.Match("/static/*/*", r.URL.Path)
|
||||||
if isStatic {
|
if isStatic {
|
||||||
|
|
@ -372,11 +380,22 @@ func BaseURLMiddleware(next http.Handler) http.Handler {
|
||||||
} else {
|
} else {
|
||||||
scheme = "http"
|
scheme = "http"
|
||||||
}
|
}
|
||||||
baseURL := scheme + "://" + r.Host
|
prefix := ""
|
||||||
|
if r.Header.Get("X-Forwarded-Prefix") != "" {
|
||||||
|
prefix = strings.TrimRight(r.Header.Get("X-Forwarded-Prefix"), "/")
|
||||||
|
}
|
||||||
|
|
||||||
|
port := ""
|
||||||
|
forwardedPort := r.Header.Get("X-Forwarded-Port")
|
||||||
|
if forwardedPort != "" && forwardedPort != "80" && forwardedPort != "8080" {
|
||||||
|
port = ":" + forwardedPort
|
||||||
|
}
|
||||||
|
|
||||||
|
baseURL := scheme + "://" + r.Host + port + prefix
|
||||||
|
|
||||||
externalHost := config.GetInstance().GetExternalHost()
|
externalHost := config.GetInstance().GetExternalHost()
|
||||||
if externalHost != "" {
|
if externalHost != "" {
|
||||||
baseURL = externalHost
|
baseURL = externalHost + prefix
|
||||||
}
|
}
|
||||||
|
|
||||||
r = r.WithContext(context.WithValue(ctx, BaseURLCtxKey, baseURL))
|
r = r.WithContext(context.WithValue(ctx, BaseURLCtxKey, baseURL))
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@
|
||||||
"name": "stash",
|
"name": "stash",
|
||||||
"version": "0.1.0",
|
"version": "0.1.0",
|
||||||
"private": true,
|
"private": true,
|
||||||
|
"homepage": "./",
|
||||||
"sideEffects": false,
|
"sideEffects": false,
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"start": "react-scripts start",
|
"start": "react-scripts start",
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
|
<base href="/">
|
||||||
<meta charset="utf-8" />
|
<meta charset="utf-8" />
|
||||||
<link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico" />
|
<link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico" />
|
||||||
<meta
|
<meta
|
||||||
|
|
@ -23,6 +24,7 @@
|
||||||
Learn how to configure a non-root public URL by running `npm run build`.
|
Learn how to configure a non-root public URL by running `npm run build`.
|
||||||
-->
|
-->
|
||||||
<title>Stash</title>
|
<title>Stash</title>
|
||||||
|
<script>window.STASH_BASE_URL = "%BASE_URL%"</script>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<noscript>You need to enable JavaScript to run this app.</noscript>
|
<noscript>You need to enable JavaScript to run this app.</noscript>
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
#### 💥 Note: Please check your logs after migrating to this release. A log warning will be generated on startup if duplicate image checksums exist in your system. Search for the images using the logged checksums, and remove the unwanted ones.
|
#### 💥 Note: Please check your logs after migrating to this release. A log warning will be generated on startup if duplicate image checksums exist in your system. Search for the images using the logged checksums, and remove the unwanted ones.
|
||||||
|
|
||||||
### ✨ New Features
|
### ✨ New Features
|
||||||
|
* Support subpaths when serving stash via reverse proxy. ([#1719](https://github.com/stashapp/stash/pull/1719))
|
||||||
* Added options to generate webp and static preview files for markers. ([#1604](https://github.com/stashapp/stash/pull/1604))
|
* Added options to generate webp and static preview files for markers. ([#1604](https://github.com/stashapp/stash/pull/1604))
|
||||||
* Added sort by option for gallery rating. ([#1720](https://github.com/stashapp/stash/pull/1720))
|
* Added sort by option for gallery rating. ([#1720](https://github.com/stashapp/stash/pull/1720))
|
||||||
* Added support for querying scene scrapers using keywords. ([#1712](https://github.com/stashapp/stash/pull/1712))
|
* Added support for querying scene scrapers using keywords. ([#1712](https://github.com/stashapp/stash/pull/1712))
|
||||||
|
|
|
||||||
|
|
@ -343,7 +343,7 @@ export class ScenePlayerImpl extends React.Component<
|
||||||
<div id="jwplayer-container" className={className}>
|
<div id="jwplayer-container" className={className}>
|
||||||
<ReactJWPlayer
|
<ReactJWPlayer
|
||||||
playerId={JWUtils.playerID}
|
playerId={JWUtils.playerID}
|
||||||
playerScript="/jwplayer/jwplayer.js"
|
playerScript="jwplayer/jwplayer.js"
|
||||||
customProps={this.state.config}
|
customProps={this.state.config}
|
||||||
onReady={this.onReady}
|
onReady={this.onReady}
|
||||||
onSeeked={this.onSeeked}
|
onSeeked={this.onSeeked}
|
||||||
|
|
|
||||||
|
|
@ -81,8 +81,14 @@ const typePolicies: TypePolicies = {
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const getBaseURL = () => {
|
||||||
|
const baseURL = window.STASH_BASE_URL;
|
||||||
|
if (baseURL === "%BASE_URL%") return "/";
|
||||||
|
return baseURL;
|
||||||
|
};
|
||||||
|
|
||||||
export const getPlatformURL = (ws?: boolean) => {
|
export const getPlatformURL = (ws?: boolean) => {
|
||||||
const platformUrl = new URL(window.location.origin);
|
const platformUrl = new URL(window.location.origin + getBaseURL());
|
||||||
|
|
||||||
if (!process.env.NODE_ENV || process.env.NODE_ENV === "development") {
|
if (!process.env.NODE_ENV || process.env.NODE_ENV === "development") {
|
||||||
platformUrl.port = process.env.REACT_APP_PLATFORM_PORT ?? "9999";
|
platformUrl.port = process.env.REACT_APP_PLATFORM_PORT ?? "9999";
|
||||||
|
|
@ -107,8 +113,8 @@ export const createClient = () => {
|
||||||
wsPlatformUrl.protocol = "wss:";
|
wsPlatformUrl.protocol = "wss:";
|
||||||
}
|
}
|
||||||
|
|
||||||
const url = `${platformUrl.toString().slice(0, -1)}/graphql`;
|
const url = `${platformUrl.toString()}graphql`;
|
||||||
const wsUrl = `${wsPlatformUrl.toString().slice(0, -1)}/graphql`;
|
const wsUrl = `${wsPlatformUrl.toString()}graphql`;
|
||||||
|
|
||||||
const httpLink = createUploadLink({
|
const httpLink = createUploadLink({
|
||||||
uri: url,
|
uri: url,
|
||||||
|
|
|
||||||
2
ui/v2.5/src/globals.d.ts
vendored
2
ui/v2.5/src/globals.d.ts
vendored
|
|
@ -1,3 +1,5 @@
|
||||||
|
// eslint-disable-next-line no-var
|
||||||
|
declare var STASH_BASE_URL: string;
|
||||||
declare module "*.md";
|
declare module "*.md";
|
||||||
declare module "string.prototype.replaceall";
|
declare module "string.prototype.replaceall";
|
||||||
declare module "mousetrap-pause";
|
declare module "mousetrap-pause";
|
||||||
|
|
|
||||||
|
|
@ -4,14 +4,14 @@ import ReactDOM from "react-dom";
|
||||||
import { BrowserRouter } from "react-router-dom";
|
import { BrowserRouter } from "react-router-dom";
|
||||||
import { App } from "./App";
|
import { App } from "./App";
|
||||||
import { getClient } from "./core/StashService";
|
import { getClient } from "./core/StashService";
|
||||||
import { getPlatformURL } from "./core/createClient";
|
import { getPlatformURL, getBaseURL } from "./core/createClient";
|
||||||
import "./index.scss";
|
import "./index.scss";
|
||||||
import * as serviceWorker from "./serviceWorker";
|
import * as serviceWorker from "./serviceWorker";
|
||||||
|
|
||||||
ReactDOM.render(
|
ReactDOM.render(
|
||||||
<>
|
<>
|
||||||
<link rel="stylesheet" type="text/css" href={`${getPlatformURL()}css`} />
|
<link rel="stylesheet" type="text/css" href={`${getPlatformURL()}css`} />
|
||||||
<BrowserRouter>
|
<BrowserRouter basename={getBaseURL()}>
|
||||||
<ApolloProvider client={getClient()}>
|
<ApolloProvider client={getClient()}>
|
||||||
<App />
|
<App />
|
||||||
</ApolloProvider>
|
</ApolloProvider>
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue