mirror of
https://github.com/jiojciojsioe3/a3cjroijsiojiorj.git
synced 2024-11-21 18:31:50 +08:00
Add base directory support
- Base directory can be changed in config.py from the default / to, for example, /taiko-web/ - See tools/nginx_subdir.conf for an example nginx configuration with a base directory - Custom error pages can be used, they can be set in config.py
This commit is contained in:
parent
ba1a6ab306
commit
fd32ecb004
1
.gitignore
vendored
1
.gitignore
vendored
@ -53,3 +53,4 @@ config.py
|
||||
public/assets/song_skins
|
||||
.venv
|
||||
public/src/js/plugin
|
||||
.hidden
|
||||
|
92
app.py
92
app.py
@ -15,7 +15,7 @@ import os
|
||||
import time
|
||||
|
||||
from functools import wraps
|
||||
from flask import Flask, g, jsonify, render_template, request, abort, redirect, session, flash, make_response
|
||||
from flask import Flask, g, jsonify, render_template, request, abort, redirect, session, flash, make_response, send_from_directory
|
||||
from flask_caching import Cache
|
||||
from flask_session import Session
|
||||
from flask_wtf.csrf import CSRFProtect, generate_csrf, CSRFError
|
||||
@ -33,6 +33,7 @@ def take_config(name, required=False):
|
||||
|
||||
app = Flask(__name__)
|
||||
client = MongoClient(host=take_config('MONGO', required=True)['host'])
|
||||
basedir = take_config('BASEDIR') or '/'
|
||||
|
||||
app.secret_key = take_config('SECRET_KEY') or 'change-me'
|
||||
app.config['SESSION_TYPE'] = 'redis'
|
||||
@ -79,8 +80,8 @@ def generate_hash(id, form):
|
||||
raise HashException('Invalid response from %s (status code %s)' % (resp.url, resp.status_code))
|
||||
md5.update(resp.content)
|
||||
else:
|
||||
if url.startswith("/"):
|
||||
url = url[1:]
|
||||
if url.startswith(basedir):
|
||||
url = url[len(basedir):]
|
||||
path = os.path.normpath(os.path.join("public", url))
|
||||
if not os.path.isfile(path):
|
||||
raise HashException("File not found: %s" % (os.path.abspath(path)))
|
||||
@ -129,6 +130,7 @@ def before_request_func():
|
||||
|
||||
def get_config(credentials=False):
|
||||
config_out = {
|
||||
'basedir': basedir,
|
||||
'songs_baseurl': take_config('SONGS_BASEURL', required=True),
|
||||
'assets_baseurl': take_config('ASSETS_BASEURL', required=True),
|
||||
'email': take_config('EMAIL'),
|
||||
@ -138,6 +140,10 @@ def get_config(credentials=False):
|
||||
'preview_type': take_config('PREVIEW_TYPE') or 'mp3',
|
||||
'multiplayer_url': take_config('MULTIPLAYER_URL')
|
||||
}
|
||||
relative_urls = ['songs_baseurl', 'assets_baseurl']
|
||||
for name in relative_urls:
|
||||
if not config_out[name].startswith("/") and not config_out[name].startswith("http://") and not config_out[name].startswith("https://"):
|
||||
config_out[name] = basedir + config_out[name]
|
||||
if credentials:
|
||||
google_credentials = take_config('GOOGLE_CREDENTIALS')
|
||||
min_level = google_credentials['min_level'] or 0
|
||||
@ -200,24 +206,24 @@ def is_hex(input):
|
||||
return False
|
||||
|
||||
|
||||
@app.route('/')
|
||||
@app.route(basedir)
|
||||
def route_index():
|
||||
version = get_version()
|
||||
return render_template('index.html', version=version, config=get_config())
|
||||
|
||||
|
||||
@app.route('/api/csrftoken')
|
||||
@app.route(basedir + 'api/csrftoken')
|
||||
def route_csrftoken():
|
||||
return jsonify({'status': 'ok', 'token': generate_csrf()})
|
||||
|
||||
|
||||
@app.route('/admin')
|
||||
@app.route(basedir + 'admin')
|
||||
@admin_required(level=50)
|
||||
def route_admin():
|
||||
return redirect('/admin/songs')
|
||||
return redirect(basedir + 'admin/songs')
|
||||
|
||||
|
||||
@app.route('/admin/songs')
|
||||
@app.route(basedir + 'admin/songs')
|
||||
@admin_required(level=50)
|
||||
def route_admin_songs():
|
||||
songs = sorted(list(db.songs.find({})), key=lambda x: x['id'])
|
||||
@ -226,7 +232,7 @@ def route_admin_songs():
|
||||
return render_template('admin_songs.html', songs=songs, admin=user, categories=list(categories), config=get_config())
|
||||
|
||||
|
||||
@app.route('/admin/songs/<int:id>')
|
||||
@app.route(basedir + 'admin/songs/<int:id>')
|
||||
@admin_required(level=50)
|
||||
def route_admin_songs_id(id):
|
||||
song = db.songs.find_one({'id': id})
|
||||
@ -242,7 +248,7 @@ def route_admin_songs_id(id):
|
||||
song=song, categories=categories, song_skins=song_skins, makers=makers, admin=user, config=get_config())
|
||||
|
||||
|
||||
@app.route('/admin/songs/new')
|
||||
@app.route(basedir + 'admin/songs/new')
|
||||
@admin_required(level=100)
|
||||
def route_admin_songs_new():
|
||||
categories = list(db.categories.find({}))
|
||||
@ -254,7 +260,7 @@ def route_admin_songs_new():
|
||||
return render_template('admin_song_new.html', categories=categories, song_skins=song_skins, makers=makers, config=get_config(), id=seq_new)
|
||||
|
||||
|
||||
@app.route('/admin/songs/new', methods=['POST'])
|
||||
@app.route(basedir + 'admin/songs/new', methods=['POST'])
|
||||
@admin_required(level=100)
|
||||
def route_admin_songs_new_post():
|
||||
output = {'title_lang': {}, 'subtitle_lang': {}, 'courses': {}}
|
||||
@ -303,10 +309,10 @@ def route_admin_songs_new_post():
|
||||
|
||||
db.seq.update_one({'name': 'songs'}, {'$set': {'value': seq_new}}, upsert=True)
|
||||
|
||||
return redirect('/admin/songs/%s' % str(seq_new))
|
||||
return redirect(basedir + 'admin/songs/%s' % str(seq_new))
|
||||
|
||||
|
||||
@app.route('/admin/songs/<int:id>', methods=['POST'])
|
||||
@app.route(basedir + 'admin/songs/<int:id>', methods=['POST'])
|
||||
@admin_required(level=50)
|
||||
def route_admin_songs_id_post(id):
|
||||
song = db.songs.find_one({'id': id})
|
||||
@ -356,10 +362,10 @@ def route_admin_songs_id_post(id):
|
||||
if not hash_error:
|
||||
flash('Changes saved.')
|
||||
|
||||
return redirect('/admin/songs/%s' % id)
|
||||
return redirect(basedir + 'admin/songs/%s' % id)
|
||||
|
||||
|
||||
@app.route('/admin/songs/<int:id>/delete', methods=['POST'])
|
||||
@app.route(basedir + 'admin/songs/<int:id>/delete', methods=['POST'])
|
||||
@admin_required(level=100)
|
||||
def route_admin_songs_id_delete(id):
|
||||
song = db.songs.find_one({'id': id})
|
||||
@ -368,10 +374,10 @@ def route_admin_songs_id_delete(id):
|
||||
|
||||
db.songs.delete_one({'id': id})
|
||||
flash('Song deleted.')
|
||||
return redirect('/admin/songs')
|
||||
return redirect(basedir + 'admin/songs')
|
||||
|
||||
|
||||
@app.route('/admin/users')
|
||||
@app.route(basedir + 'admin/users')
|
||||
@admin_required(level=50)
|
||||
def route_admin_users():
|
||||
user = db.users.find_one({'username': session.get('username')})
|
||||
@ -379,7 +385,7 @@ def route_admin_users():
|
||||
return render_template('admin_users.html', config=get_config(), max_level=max_level, username='', level='')
|
||||
|
||||
|
||||
@app.route('/admin/users', methods=['POST'])
|
||||
@app.route(basedir + 'admin/users', methods=['POST'])
|
||||
@admin_required(level=50)
|
||||
def route_admin_users_post():
|
||||
admin_name = session.get('username')
|
||||
@ -411,7 +417,7 @@ def route_admin_users_post():
|
||||
return render_template('admin_users.html', config=get_config(), max_level=max_level, username=username, level=level)
|
||||
|
||||
|
||||
@app.route('/api/preview')
|
||||
@app.route(basedir + 'api/preview')
|
||||
@app.cache.cached(timeout=15, query_string=True)
|
||||
def route_api_preview():
|
||||
song_id = request.args.get('id', None)
|
||||
@ -432,7 +438,7 @@ def route_api_preview():
|
||||
return redirect(get_config()['songs_baseurl'] + '%s/preview.mp3' % song_id)
|
||||
|
||||
|
||||
@app.route('/api/songs')
|
||||
@app.route(basedir + 'api/songs')
|
||||
@app.cache.cached(timeout=15)
|
||||
def route_api_songs():
|
||||
songs = list(db.songs.find({'enabled': True}, {'_id': False, 'enabled': False}))
|
||||
@ -460,20 +466,20 @@ def route_api_songs():
|
||||
|
||||
return jsonify(songs)
|
||||
|
||||
@app.route('/api/categories')
|
||||
@app.route(basedir + 'api/categories')
|
||||
@app.cache.cached(timeout=15)
|
||||
def route_api_categories():
|
||||
categories = list(db.categories.find({},{'_id': False}))
|
||||
return jsonify(categories)
|
||||
|
||||
@app.route('/api/config')
|
||||
@app.route(basedir + 'api/config')
|
||||
@app.cache.cached(timeout=15)
|
||||
def route_api_config():
|
||||
config = get_config(credentials=True)
|
||||
return jsonify(config)
|
||||
|
||||
|
||||
@app.route('/api/register', methods=['POST'])
|
||||
@app.route(basedir + 'api/register', methods=['POST'])
|
||||
def route_api_register():
|
||||
data = request.get_json()
|
||||
if not schema.validate(data, schema.register):
|
||||
@ -514,7 +520,7 @@ def route_api_register():
|
||||
return jsonify({'status': 'ok', 'username': username, 'display_name': username, 'don': don})
|
||||
|
||||
|
||||
@app.route('/api/login', methods=['POST'])
|
||||
@app.route(basedir + 'api/login', methods=['POST'])
|
||||
def route_api_login():
|
||||
data = request.get_json()
|
||||
if not schema.validate(data, schema.login):
|
||||
@ -541,14 +547,14 @@ def route_api_login():
|
||||
return jsonify({'status': 'ok', 'username': result['username'], 'display_name': result['display_name'], 'don': don})
|
||||
|
||||
|
||||
@app.route('/api/logout', methods=['POST'])
|
||||
@app.route(basedir + 'api/logout', methods=['POST'])
|
||||
@login_required
|
||||
def route_api_logout():
|
||||
session.clear()
|
||||
return jsonify({'status': 'ok'})
|
||||
|
||||
|
||||
@app.route('/api/account/display_name', methods=['POST'])
|
||||
@app.route(basedir + 'api/account/display_name', methods=['POST'])
|
||||
@login_required
|
||||
def route_api_account_display_name():
|
||||
data = request.get_json()
|
||||
@ -568,7 +574,7 @@ def route_api_account_display_name():
|
||||
return jsonify({'status': 'ok', 'display_name': display_name})
|
||||
|
||||
|
||||
@app.route('/api/account/don', methods=['POST'])
|
||||
@app.route(basedir + 'api/account/don', methods=['POST'])
|
||||
@login_required
|
||||
def route_api_account_don():
|
||||
data = request.get_json()
|
||||
@ -593,7 +599,7 @@ def route_api_account_don():
|
||||
return jsonify({'status': 'ok', 'don': {'body_fill': don_body_fill, 'face_fill': don_face_fill}})
|
||||
|
||||
|
||||
@app.route('/api/account/password', methods=['POST'])
|
||||
@app.route(basedir + 'api/account/password', methods=['POST'])
|
||||
@login_required
|
||||
def route_api_account_password():
|
||||
data = request.get_json()
|
||||
@ -621,7 +627,7 @@ def route_api_account_password():
|
||||
return jsonify({'status': 'ok'})
|
||||
|
||||
|
||||
@app.route('/api/account/remove', methods=['POST'])
|
||||
@app.route(basedir + 'api/account/remove', methods=['POST'])
|
||||
@login_required
|
||||
def route_api_account_remove():
|
||||
data = request.get_json()
|
||||
@ -640,7 +646,7 @@ def route_api_account_remove():
|
||||
return jsonify({'status': 'ok'})
|
||||
|
||||
|
||||
@app.route('/api/scores/save', methods=['POST'])
|
||||
@app.route(basedir + 'api/scores/save', methods=['POST'])
|
||||
@login_required
|
||||
def route_api_scores_save():
|
||||
data = request.get_json()
|
||||
@ -663,7 +669,7 @@ def route_api_scores_save():
|
||||
return jsonify({'status': 'ok'})
|
||||
|
||||
|
||||
@app.route('/api/scores/get')
|
||||
@app.route(basedir + 'api/scores/get')
|
||||
@login_required
|
||||
def route_api_scores_get():
|
||||
username = session.get('username')
|
||||
@ -680,7 +686,7 @@ def route_api_scores_get():
|
||||
return jsonify({'status': 'ok', 'scores': scores, 'username': user['username'], 'display_name': user['display_name'], 'don': don})
|
||||
|
||||
|
||||
@app.route('/privacy')
|
||||
@app.route(basedir + 'privacy')
|
||||
def route_api_privacy():
|
||||
last_modified = time.strftime('%d %B %Y', time.gmtime(os.path.getmtime('templates/privacy.txt')))
|
||||
integration = take_config('GOOGLE_CREDENTIALS')['gdrive_enabled'] if take_config('GOOGLE_CREDENTIALS') else False
|
||||
@ -706,10 +712,26 @@ def make_preview(song_id, song_type, song_ext, preview):
|
||||
|
||||
return prev_path
|
||||
|
||||
error_pages = take_config('ERROR_PAGES') or {}
|
||||
|
||||
def create_error_page(code, url):
|
||||
if url.startswith("http://") or url.startswith("https://"):
|
||||
resp = requests.get(url)
|
||||
if resp.status_code == 200:
|
||||
app.register_error_handler(code, lambda e: (resp.content, code))
|
||||
else:
|
||||
if url.startswith(basedir):
|
||||
url = url[len(basedir):]
|
||||
path = os.path.normpath(os.path.join("public", url))
|
||||
if os.path.isfile(path):
|
||||
app.register_error_handler(code, lambda e: (send_from_directory(".", path), code))
|
||||
|
||||
for code in error_pages:
|
||||
if error_pages[code]:
|
||||
create_error_page(code, error_pages[code])
|
||||
|
||||
if __name__ == '__main__':
|
||||
import argparse
|
||||
from flask import send_from_directory
|
||||
|
||||
parser = argparse.ArgumentParser(description='Run the taiko-web development server.')
|
||||
parser.add_argument('port', type=int, metavar='PORT', nargs='?', default=34801, help='Port to listen on.')
|
||||
@ -717,11 +739,11 @@ if __name__ == '__main__':
|
||||
parser.add_argument('-d', '--debug', action='store_true', help='Enable debug mode.')
|
||||
args = parser.parse_args()
|
||||
|
||||
@app.route('/src/<path:path>')
|
||||
@app.route(basedir + 'src/<path:path>')
|
||||
def send_src(path):
|
||||
return send_from_directory('public/src', path)
|
||||
|
||||
@app.route('/assets/<path:path>')
|
||||
@app.route(basedir + 'assets/<path:path>')
|
||||
def send_assets(path):
|
||||
return send_from_directory('public/assets', path)
|
||||
|
||||
|
@ -1,3 +1,6 @@
|
||||
# The base URL for Taiko Web, with trailing slash.
|
||||
BASEDIR = '/'
|
||||
|
||||
# The full URL base asset URL, with trailing slash.
|
||||
ASSETS_BASEURL = '/assets/'
|
||||
|
||||
@ -7,6 +10,11 @@ SONGS_BASEURL = '/songs/'
|
||||
# Multiplayer websocket URL. Defaults to /p2 if blank.
|
||||
MULTIPLAYER_URL = ''
|
||||
|
||||
# Send static files for custom error pages
|
||||
ERROR_PAGES = {
|
||||
404: ''
|
||||
}
|
||||
|
||||
# The email address to display in the "About Simulator" menu.
|
||||
EMAIL = None
|
||||
|
||||
|
@ -300,7 +300,7 @@ class CustomSongs{
|
||||
this.loading(true)
|
||||
var importSongs = new ImportSongs(true)
|
||||
if(!gpicker){
|
||||
var gpickerPromise = loader.loadScript("/src/js/gpicker.js").then(() => {
|
||||
var gpickerPromise = loader.loadScript("src/js/gpicker.js").then(() => {
|
||||
gpicker = new Gpicker()
|
||||
})
|
||||
}else{
|
||||
|
@ -13,11 +13,11 @@ class Loader{
|
||||
|
||||
var promises = []
|
||||
|
||||
promises.push(this.ajax("/src/views/loader.html").then(page => {
|
||||
promises.push(this.ajax("src/views/loader.html").then(page => {
|
||||
this.screen.innerHTML = page
|
||||
}))
|
||||
|
||||
promises.push(this.ajax("/api/config").then(conf => {
|
||||
promises.push(this.ajax("api/config").then(conf => {
|
||||
gameConfig = JSON.parse(conf)
|
||||
}))
|
||||
|
||||
@ -39,7 +39,7 @@ class Loader{
|
||||
assets.js.push("lib/oggmented-wasm.js")
|
||||
}
|
||||
assets.js.forEach(name => {
|
||||
this.addPromise(this.loadScript("/src/js/" + name), "/src/js/" + name)
|
||||
this.addPromise(this.loadScript("src/js/" + name), "src/js/" + name)
|
||||
})
|
||||
|
||||
var pageVersion = versionLink.href
|
||||
@ -59,7 +59,7 @@ class Loader{
|
||||
assets.css.forEach(name => {
|
||||
var stylesheet = document.createElement("link")
|
||||
stylesheet.rel = "stylesheet"
|
||||
stylesheet.href = "/src/css/" + name + this.queryString
|
||||
stylesheet.href = "src/css/" + name + this.queryString
|
||||
document.head.appendChild(stylesheet)
|
||||
})
|
||||
var checkStyles = () => {
|
||||
@ -124,13 +124,13 @@ class Loader{
|
||||
|
||||
assets.views.forEach(name => {
|
||||
var id = this.getFilename(name)
|
||||
var url = "/src/views/" + name + this.queryString
|
||||
var url = "src/views/" + name + this.queryString
|
||||
this.addPromise(this.ajax(url).then(page => {
|
||||
assets.pages[id] = page
|
||||
}), url)
|
||||
})
|
||||
|
||||
this.addPromise(this.ajax("/api/categories").then(cats => {
|
||||
this.addPromise(this.ajax("api/categories").then(cats => {
|
||||
assets.categories = JSON.parse(cats)
|
||||
assets.categories.forEach(cat => {
|
||||
if(cat.song_skin){
|
||||
@ -150,7 +150,7 @@ class Loader{
|
||||
infoFill: "#656565"
|
||||
}
|
||||
})
|
||||
}), "/api/categories")
|
||||
}), "api/categories")
|
||||
|
||||
var url = gameConfig.assets_baseurl + "img/vectors.json" + this.queryString
|
||||
this.addPromise(this.ajax(url).then(response => {
|
||||
@ -159,7 +159,7 @@ class Loader{
|
||||
|
||||
this.afterJSCount =
|
||||
[
|
||||
"/api/songs",
|
||||
"api/songs",
|
||||
"blurPerformance",
|
||||
"categories"
|
||||
].length +
|
||||
@ -178,7 +178,7 @@ class Loader{
|
||||
style.appendChild(document.createTextNode(css.join("\n")))
|
||||
document.head.appendChild(style)
|
||||
|
||||
this.addPromise(this.ajax("/api/songs").then(songs => {
|
||||
this.addPromise(this.ajax("api/songs").then(songs => {
|
||||
songs = JSON.parse(songs)
|
||||
songs.forEach(song => {
|
||||
var directory = gameConfig.songs_baseurl + song.id + "/"
|
||||
@ -203,7 +203,7 @@ class Loader{
|
||||
})
|
||||
assets.songsDefault = songs
|
||||
assets.songs = assets.songsDefault
|
||||
}), "/api/songs")
|
||||
}), "api/songs")
|
||||
|
||||
var categoryPromises = []
|
||||
assets.categories //load category backgrounds to DOM
|
||||
@ -276,7 +276,7 @@ class Loader{
|
||||
}), "blurPerformance")
|
||||
|
||||
if(gameConfig.accounts){
|
||||
this.addPromise(this.ajax("/api/scores/get").then(response => {
|
||||
this.addPromise(this.ajax("api/scores/get").then(response => {
|
||||
response = JSON.parse(response)
|
||||
if(response.status === "ok"){
|
||||
account.loggedIn = true
|
||||
@ -286,7 +286,7 @@ class Loader{
|
||||
scoreStorage.load(response.scores)
|
||||
pageEvents.send("login", account.username)
|
||||
}
|
||||
}), "/api/scores/get")
|
||||
}), "api/scores/get")
|
||||
}
|
||||
|
||||
settings = new Settings()
|
||||
|
@ -32,7 +32,7 @@ class P2Connection{
|
||||
if(this.closed && !this.disabled){
|
||||
this.closed = false
|
||||
var wsProtocol = location.protocol == "https:" ? "wss:" : "ws:"
|
||||
this.socket = new WebSocket(gameConfig.multiplayer_url ? gameConfig.multiplayer_url : wsProtocol + "//" + location.host + "/p2")
|
||||
this.socket = new WebSocket(gameConfig.multiplayer_url ? gameConfig.multiplayer_url : wsProtocol + "//" + location.host + location.pathname + "p2")
|
||||
pageEvents.race(this.socket, "open", "close").then(response => {
|
||||
if(response.type === "open"){
|
||||
return this.openEvent()
|
||||
|
@ -7,13 +7,13 @@
|
||||
<meta name="viewport" content="width=device-width, user-scalable=no">
|
||||
|
||||
<link href="https://fonts.googleapis.com/css2?family=Noto+Sans+JP:wght@400;700&display=swap" rel="stylesheet">
|
||||
<link href="/src/css/admin.css" rel="stylesheet">
|
||||
<link href="{{config.basedir}}src/css/admin.css" rel="stylesheet">
|
||||
</head>
|
||||
<body>
|
||||
<header>
|
||||
<div class="nav">
|
||||
<a href="/admin/songs">Songs</a>
|
||||
<a href="/admin/users">Users</a>
|
||||
<a href="{{config.basedir}}admin/songs">Songs</a>
|
||||
<a href="{{config.basedir}}admin/users">Users</a>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
|
@ -1,14 +1,14 @@
|
||||
{% extends 'admin.html' %}
|
||||
{% block content %}
|
||||
{% if admin.user_level >= 100 %}
|
||||
<a href="/admin/songs/new" class="side-button">New song</a>
|
||||
<a href="{{config.basedir}}admin/songs/new" class="side-button">New song</a>
|
||||
{% endif %}
|
||||
<h1>Songs</h1>
|
||||
{% for message in get_flashed_messages() %}
|
||||
<div class="message">{{ message }}</div>
|
||||
{% endfor %}
|
||||
{% for song in songs %}
|
||||
<a href="/admin/songs/{{ song.id }}" class="song-link">
|
||||
<a href="{{config.basedir}}admin/songs/{{ song.id }}" class="song-link">
|
||||
<div class="song">
|
||||
{% if song.title_lang.en and song.title_lang.en != song.title %}
|
||||
<p><span class="song-id">{{ song.id }}.</span>
|
||||
|
@ -11,12 +11,12 @@
|
||||
<meta name="robots" content="noimageindex">
|
||||
<meta name="color-scheme" content="only light">
|
||||
|
||||
<link rel="stylesheet" href="/src/css/loader.css?{{version.commit_short}}">
|
||||
<link rel="stylesheet" href="src/css/loader.css?{{version.commit_short}}">
|
||||
|
||||
<script src="/src/js/assets.js?{{version.commit_short}}"></script>
|
||||
<script src="/src/js/strings.js?{{version.commit_short}}"></script>
|
||||
<script src="/src/js/pageevents.js?{{version.commit_short}}"></script>
|
||||
<script src="/src/js/loader.js?{{version.commit_short}}"></script>
|
||||
<script src="src/js/assets.js?{{version.commit_short}}"></script>
|
||||
<script src="src/js/strings.js?{{version.commit_short}}"></script>
|
||||
<script src="src/js/pageevents.js?{{version.commit_short}}"></script>
|
||||
<script src="src/js/loader.js?{{version.commit_short}}"></script>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
@ -29,8 +29,8 @@
|
||||
<a href="{{version.url}}" target="_blank" rel="noopener" id="version-link" class="stroke-sub" alt="taiko-web (unknown version)">taiko-web (unknown version)</a>
|
||||
{% endif %}
|
||||
</div>
|
||||
<script src="/src/js/browsersupport.js?{{version.commit_short}}"></script>
|
||||
<script src="/src/js/main.js?{{version.commit_short}}"></script>
|
||||
<script src="src/js/browsersupport.js?{{version.commit_short}}"></script>
|
||||
<script src="src/js/main.js?{{version.commit_short}}"></script>
|
||||
<noscript>
|
||||
<div data-nosnippet id="unsupportedBrowser">
|
||||
<div id="unsupportedWarn">!</div>
|
||||
|
28
tools/nginx_subdir.conf
Normal file
28
tools/nginx_subdir.conf
Normal file
@ -0,0 +1,28 @@
|
||||
server {
|
||||
listen 80;
|
||||
#server_name taiko.example.com;
|
||||
|
||||
location /taiko-web/ {
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header Host $server_name;
|
||||
proxy_pass http://127.0.0.1:34801;
|
||||
}
|
||||
|
||||
location ~ ^/taiko-web/(assets|songs|src)/ {
|
||||
rewrite ^/taiko-web/(.*) /$1 break;
|
||||
root /srv/taiko-web/public;
|
||||
location ~ ^/taiko-web/songs/([0-9]+)/preview\.mp3$ {
|
||||
set $id $1;
|
||||
rewrite ^/taiko-web/(.*) /$1 break;
|
||||
try_files $uri /taiko-web/api/preview?id=$id;
|
||||
}
|
||||
}
|
||||
|
||||
location /taiko-web/p2 {
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header Connection "Upgrade";
|
||||
proxy_pass http://127.0.0.1:34802;
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user