Merge branch 'main' into 95-send-spots-to-xota

# Conflicts:
#	README.md
This commit is contained in:
Ian Renton
2026-06-20 12:23:06 +01:00
11 changed files with 79 additions and 23 deletions

View File

@@ -310,44 +310,80 @@ server {
# SSE endpoints # SSE endpoints
location ~ ^/api/v2/(spots|alerts)/stream { location ~ ^/api/v2/(spots|alerts)/stream {
proxy_pass http://127.0.0.1:8080;
# Allow keep-alive
proxy_http_version 1.1; proxy_http_version 1.1;
proxy_set_header Connection ""; proxy_set_header Connection "";
proxy_pass http://127.0.0.1:8080;
# Set correct content type for SSE API calls
add_header Content-Type text/event-stream always;
# Set remove buffering, remove caching, add suitable timeouts for SSE API calls
proxy_buffering off; proxy_buffering off;
proxy_cache off; proxy_cache off;
proxy_read_timeout 24h; proxy_read_timeout 24h;
proxy_connect_timeout 10s; proxy_connect_timeout 10s;
proxy_send_timeout 24h; proxy_send_timeout 24h;
proxy_set_header X-Accel-Buffering no; proxy_set_header X-Accel-Buffering no;
add_header Cache-Control no-store always;
# Allow cross-origin requests to API
proxy_hide_header Access-Control-Allow-Origin; proxy_hide_header Access-Control-Allow-Origin;
add_header Access-Control-Allow-Origin * always; add_header Access-Control-Allow-Origin * always;
add_header Cache-Control no-store always;
add_header Content-Type text/event-stream always; # Pass on IP address and host information to Spothole, in case logging this information is required
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_set_header X-Forwarded-Proto $scheme;
} }
# Other API endpoints # Other API endpoints
location /api/ { location /api/ {
proxy_pass http://127.0.0.1:8080;
# Allow keep-alive
proxy_http_version 1.1; proxy_http_version 1.1;
proxy_set_header Connection ""; proxy_set_header Connection "";
proxy_pass http://127.0.0.1:8080;
# Set up buffering, remove caching, add suitable timeouts for API calls
proxy_buffering on; proxy_buffering on;
proxy_cache off; proxy_cache off;
proxy_read_timeout 30s; proxy_read_timeout 30s;
proxy_connect_timeout 10s; proxy_connect_timeout 10s;
add_header Cache-Control no-store always;
# Allow cross-origin requests to API
proxy_hide_header Access-Control-Allow-Origin; proxy_hide_header Access-Control-Allow-Origin;
add_header Access-Control-Allow-Origin * always; add_header Access-Control-Allow-Origin * always;
add_header Cache-Control no-store always;
# Pass on IP address and host information to Spothole, in case logging this information is required
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_set_header X-Forwarded-Proto $scheme;
} }
# Static assets # Static assets
location / { location / {
proxy_pass http://127.0.0.1:8080;
# Allow keep-alive
proxy_http_version 1.1; proxy_http_version 1.1;
proxy_set_header Connection ""; proxy_set_header Connection "";
proxy_pass http://127.0.0.1:8080;
# Set up buffering and caching, add suitable timeouts for static asset requests
proxy_buffering on; proxy_buffering on;
proxy_read_timeout 30s; proxy_read_timeout 30s;
proxy_connect_timeout 10s; proxy_connect_timeout 10s;
add_header Cache-Control "public, max-age=3600, must-revalidate" always; add_header Cache-Control "public, max-age=3600, must-revalidate" always;
# Pass on IP address and host information to Spothole, in case logging this information is required
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_set_header X-Forwarded-Proto $scheme;
} }
} }
``` ```

View File

@@ -119,8 +119,9 @@ class WebServer:
app = tornado.web.Application(api_routes + v1_compat_routes + ui_routes + misc_routes, app = tornado.web.Application(api_routes + v1_compat_routes + ui_routes + misc_routes,
template_path=os.path.join(_HERE, "../templates"), template_path=os.path.join(_HERE, "../templates"),
log_function=request_log,
debug=False) debug=False)
app.listen(self._port) app.listen(self._port, xheaders=True)
logging.info("Web server running on port " + str(WEB_SERVER_PORT)) logging.info("Web server running on port " + str(WEB_SERVER_PORT))
await self._shutdown_event.wait() await self._shutdown_event.wait()
@@ -173,3 +174,22 @@ class WebServer:
# Probably got deleted already on another thread # Probably got deleted already on another thread
pass pass
pass pass
def request_log(handler):
"""Custom log function to provide more data about requests."""
if handler.get_status() < 500:
log_method = logging.info
else:
log_method = logging.warning
request = handler.request
client_ip = request.remote_ip
referrer = request.headers.get("Referer", "-")
user_agent = request.headers.get("User-Agent", "-")
log_method(
f'{client_ip} - "{request.method} {request.uri}" '
f'{handler.get_status()} {request.request_time():.2f}ms | '
f'Ref: {referrer} | UA: {user_agent}'
)

View File

@@ -13,7 +13,7 @@
href="/apidocs">API documentation</a>. The API delivers spots in a consistent format regardless of the data href="/apidocs">API documentation</a>. The API delivers spots in a consistent format regardless of the data
source, freeing developers from needing to know how each individual data source presents its data.</p> source, freeing developers from needing to know how each individual data source presents its data.</p>
<p>Spothole itself is also open source, Public Domain licenced code that anyone can take and modify. <a <p>Spothole itself is also open source, Public Domain licenced code that anyone can take and modify. <a
href="https://git.ianrenton.com/ian/metaspot/">The source code is here</a>.</p> href="https://git.ianrenton.com/ian/spothole/">The source code is here</a>.</p>
<p>The software was written by <a href="https://ianrenton.com">Ian Renton, MØTRT</a> and other contributors. Full <p>The software was written by <a href="https://ianrenton.com">Ian Renton, MØTRT</a> and other contributors. Full
details are available in the <a href="https://git.ianrenton.com/ian/spothole/src/branch/main/README.md">README details are available in the <a href="https://git.ianrenton.com/ian/spothole/src/branch/main/README.md">README
file</a>.</p> file</a>.</p>

View File

@@ -76,7 +76,7 @@
</div> </div>
<script src="/js/add-spot.js?v=1781901371"></script> <script src="/js/add-spot.js?v=1781954233"></script>
<script>$(document).ready(function () { <script>$(document).ready(function () {
$("#nav-link-add-spot").addClass("active"); $("#nav-link-add-spot").addClass("active");
}); <!-- highlight active page in nav --></script> }); <!-- highlight active page in nav --></script>

View File

@@ -75,7 +75,7 @@
</div> </div>
<script src="/js/alerts.js?v=1781901371"></script> <script src="/js/alerts.js?v=1781954233"></script>
<script>$(document).ready(function () { <script>$(document).ready(function () {
$("#nav-link-alerts").addClass("active"); $("#nav-link-alerts").addClass("active");
}); <!-- highlight active page in nav --></script> }); <!-- highlight active page in nav --></script>

View File

@@ -77,8 +77,8 @@
<script> <script>
let spotProvidersEnabledByDefault = {% raw json_encode(web_ui_options["spot-providers-enabled-by-default"]) %}; let spotProvidersEnabledByDefault = {% raw json_encode(web_ui_options["spot-providers-enabled-by-default"]) %};
</script> </script>
<script src="/js/spotsbandsandmap.js?v=1781901371"></script> <script src="/js/spotsbandsandmap.js?v=1781954233"></script>
<script src="/js/bands.js?v=1781901371"></script> <script src="/js/bands.js?v=1781954233"></script>
<script>$(document).ready(function () { <script>$(document).ready(function () {
$("#nav-link-bands").addClass("active"); $("#nav-link-bands").addClass("active");
}); <!-- highlight active page in nav --></script> }); <!-- highlight active page in nav --></script>

View File

@@ -1,6 +1,6 @@
{% extends "skeleton.html" %} {% extends "skeleton.html" %}
{% block head_extra %} {% block head_extra %}
<link rel="stylesheet" href="/css/style.css?v=1781901371" type="text/css"> <link rel="stylesheet" href="/css/style.css?v=1781954233" type="text/css">
<link href="/vendor/css/bootstrap-5.3.8.min.css" rel="stylesheet"> <link href="/vendor/css/bootstrap-5.3.8.min.css" rel="stylesheet">
<link href="/vendor/css/fontawesome-6.7.2.min.css" rel="stylesheet"> <link href="/vendor/css/fontawesome-6.7.2.min.css" rel="stylesheet">
<link href="/vendor/css/solid-6.7.2.min.css" rel="stylesheet"> <link href="/vendor/css/solid-6.7.2.min.css" rel="stylesheet">
@@ -10,10 +10,10 @@
<script src="/vendor/js/bootstrap-5.3.8.bundle.min.js"></script> <script src="/vendor/js/bootstrap-5.3.8.bundle.min.js"></script>
<script src="/vendor/js/tinycolor2-1.6.0.min.js"></script> <script src="/vendor/js/tinycolor2-1.6.0.min.js"></script>
<script src="/js/utils.js?v=1781901371"></script> <script src="/js/utils.js?v=1781954233"></script>
<script src="/js/ui-ham.js?v=1781901371"></script> <script src="/js/ui-ham.js?v=1781954233"></script>
<script src="/js/geo.js?v=1781901371"></script> <script src="/js/geo.js?v=1781954233"></script>
<script src="/js/common.js?v=1781901371"></script> <script src="/js/common.js?v=1781954233"></script>
{% end %} {% end %}
{% block body %} {% block body %}
<div class="container"> <div class="container">

View File

@@ -284,7 +284,7 @@
</div> </div>
<script src="/vendor/js/chart-4.4.9.umd.min.js"></script> <script src="/vendor/js/chart-4.4.9.umd.min.js"></script>
<script src="/js/conditions.js?v=1781901371"></script> <script src="/js/conditions.js?v=1781954233"></script>
<script>$(document).ready(function () { <script>$(document).ready(function () {
$("#nav-link-conditions").addClass("active"); $("#nav-link-conditions").addClass("active");
}); <!-- highlight active page in nav --></script> }); <!-- highlight active page in nav --></script>

View File

@@ -95,8 +95,8 @@
<script> <script>
let spotProvidersEnabledByDefault = {% raw json_encode(web_ui_options["spot-providers-enabled-by-default"]) %}; let spotProvidersEnabledByDefault = {% raw json_encode(web_ui_options["spot-providers-enabled-by-default"]) %};
</script> </script>
<script src="/js/spotsbandsandmap.js?v=1781901371"></script> <script src="/js/spotsbandsandmap.js?v=1781954233"></script>
<script src="/js/map.js?v=1781901371"></script> <script src="/js/map.js?v=1781954233"></script>
<script>$(document).ready(function () { <script>$(document).ready(function () {
$("#nav-link-map").addClass("active"); $("#nav-link-map").addClass("active");
}); <!-- highlight active page in nav --></script> }); <!-- highlight active page in nav --></script>

View File

@@ -116,8 +116,8 @@
<script> <script>
let spotProvidersEnabledByDefault = {% raw json_encode(web_ui_options["spot-providers-enabled-by-default"]) %}; let spotProvidersEnabledByDefault = {% raw json_encode(web_ui_options["spot-providers-enabled-by-default"]) %};
</script> </script>
<script src="/js/spotsbandsandmap.js?v=1781901371"></script> <script src="/js/spotsbandsandmap.js?v=1781954233"></script>
<script src="/js/spots.js?v=1781901371"></script> <script src="/js/spots.js?v=1781954233"></script>
<script>$(document).ready(function () { <script>$(document).ready(function () {
$("#nav-link-spots").addClass("active"); $("#nav-link-spots").addClass("active");
}); <!-- highlight active page in nav --></script> }); <!-- highlight active page in nav --></script>

View File

@@ -59,7 +59,7 @@
</div> </div>
</div> </div>
<script src="/js/status.js?v=1781901371"></script> <script src="/js/status.js?v=1781954233"></script>
<script> <script>
$(document).ready(function () { $(document).ready(function () {
$("#nav-link-status").addClass("active"); $("#nav-link-status").addClass("active");