Spaces:
Paused
Paused
Fix Bot commited on
Commit ·
f48bf36
1
Parent(s): 819218e
fix: split OpenCode nginx into two locations — /api/ off, / on
Browse filesnginx 1.22 (Alpine) rejects variables in proxy_buffering directive
('it must be on or off'). Replace the map-based approach with two
explicit location blocks:
location /api/ — proxy_buffering off (SSE + JSON API, streams immediately)
location / — proxy_buffering on (SPA HTML, needed for sub_filter)
Also remove 'sub_filter_types text/html' from both terminal and OpenCode
locations — text/html is sub_filter's default and listing it explicitly
triggers a 'duplicate MIME type' nginx warning.
- entrypoint.sh +25 -21
entrypoint.sh
CHANGED
|
@@ -74,14 +74,6 @@ map $http_upgrade $connection_upgrade {
|
|
| 74 |
websocket upgrade;
|
| 75 |
default "";
|
| 76 |
}
|
| 77 |
-
|
| 78 |
-
# Proxy buffering:
|
| 79 |
-
# SSE requests (Accept: text/event-stream) → off (stream tokens immediately)
|
| 80 |
-
# Everything else (HTML, JSON, assets) → on (needed for sub_filter HTML injection)
|
| 81 |
-
map $http_accept $oc_proxy_buffering {
|
| 82 |
-
"~*text/event-stream" "off";
|
| 83 |
-
default "on";
|
| 84 |
-
}
|
| 85 |
MAPEOF
|
| 86 |
|
| 87 |
cat > /etc/nginx/conf.d/opencode.conf << 'NGINXEOF'
|
|
@@ -144,25 +136,37 @@ document.addEventListener("DOMContentLoaded", function () {
|
|
| 144 |
});
|
| 145 |
</script>';
|
| 146 |
sub_filter_once on;
|
| 147 |
-
sub_filter_types
|
| 148 |
}
|
| 149 |
|
| 150 |
-
# ── OpenCode
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 151 |
location / {
|
| 152 |
proxy_pass http://127.0.0.1:8080;
|
| 153 |
proxy_http_version 1.1;
|
| 154 |
proxy_set_header Upgrade $http_upgrade;
|
| 155 |
proxy_set_header Connection $connection_upgrade;
|
| 156 |
proxy_set_header Host $host;
|
| 157 |
-
# Prevent
|
| 158 |
-
#
|
| 159 |
proxy_set_header Accept-Encoding "";
|
| 160 |
proxy_read_timeout 86400;
|
| 161 |
proxy_cache off;
|
| 162 |
-
|
| 163 |
-
# SSE requests get proxy_buffering=off (immediate streaming).
|
| 164 |
-
# HTML/JSON requests get proxy_buffering=on (required for sub_filter below).
|
| 165 |
-
proxy_buffering $oc_proxy_buffering;
|
| 166 |
|
| 167 |
# ── Server-URL localStorage fix ───────────────────────────────
|
| 168 |
# Root cause of "New Session doesn't work" / "AI never responds":
|
|
@@ -170,12 +174,12 @@ document.addEventListener("DOMContentLoaded", function () {
|
|
| 170 |
# "opencode.settings.dat:defaultServerUrl". If a previous visit stored
|
| 171 |
# a wrong URL (e.g. http://localhost:4096 from an older config), every
|
| 172 |
# API call fails silently in the browser — curl tests pass because they
|
| 173 |
-
# bypass localStorage. This script runs BEFORE the SPA
|
| 174 |
-
# clears any stale URL that
|
|
|
|
| 175 |
#
|
| 176 |
# The upstream CSP hash covers only the theme-preload script, so we
|
| 177 |
-
#
|
| 178 |
-
# dangerous sources while allowing our injected inline fix.
|
| 179 |
proxy_hide_header Content-Security-Policy;
|
| 180 |
add_header Content-Security-Policy
|
| 181 |
"default-src 'self'; script-src 'self' 'unsafe-inline' 'wasm-unsafe-eval'; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:; font-src 'self' data:; media-src 'self' data:; connect-src * data:;"
|
|
@@ -184,7 +188,7 @@ document.addEventListener("DOMContentLoaded", function () {
|
|
| 184 |
sub_filter '</head>'
|
| 185 |
'<script>!function(){try{var k="opencode.settings.dat:defaultServerUrl",s=localStorage.getItem(k);if(s&&s!==location.origin)localStorage.removeItem(k);}catch(e){}}();</script></head>';
|
| 186 |
sub_filter_once on;
|
| 187 |
-
sub_filter_types
|
| 188 |
}
|
| 189 |
}
|
| 190 |
NGINXEOF
|
|
|
|
| 74 |
websocket upgrade;
|
| 75 |
default "";
|
| 76 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 77 |
MAPEOF
|
| 78 |
|
| 79 |
cat > /etc/nginx/conf.d/opencode.conf << 'NGINXEOF'
|
|
|
|
| 136 |
});
|
| 137 |
</script>';
|
| 138 |
sub_filter_once on;
|
| 139 |
+
# (no sub_filter_types needed — text/html is processed by default)
|
| 140 |
}
|
| 141 |
|
| 142 |
+
# ── OpenCode API + SSE: buffering OFF so events stream immediately ─
|
| 143 |
+
# nginx 1.22 does not allow variables in proxy_buffering, so SSE and
|
| 144 |
+
# HTML must be split across two location blocks.
|
| 145 |
+
# This block catches all /api/* requests (JSON responses + SSE streams).
|
| 146 |
+
location /api/ {
|
| 147 |
+
proxy_pass http://127.0.0.1:8080;
|
| 148 |
+
proxy_http_version 1.1;
|
| 149 |
+
proxy_set_header Host $host;
|
| 150 |
+
proxy_set_header Connection "";
|
| 151 |
+
proxy_set_header Accept-Encoding "";
|
| 152 |
+
proxy_read_timeout 86400;
|
| 153 |
+
proxy_buffering off;
|
| 154 |
+
proxy_cache off;
|
| 155 |
+
}
|
| 156 |
+
|
| 157 |
+
# ── OpenCode SPA (HTML + assets): buffering ON for sub_filter ─────
|
| 158 |
location / {
|
| 159 |
proxy_pass http://127.0.0.1:8080;
|
| 160 |
proxy_http_version 1.1;
|
| 161 |
proxy_set_header Upgrade $http_upgrade;
|
| 162 |
proxy_set_header Connection $connection_upgrade;
|
| 163 |
proxy_set_header Host $host;
|
| 164 |
+
# Prevent gzip compression — compressed SSE cannot be decompressed
|
| 165 |
+
# incrementally by the browser.
|
| 166 |
proxy_set_header Accept-Encoding "";
|
| 167 |
proxy_read_timeout 86400;
|
| 168 |
proxy_cache off;
|
| 169 |
+
# proxy_buffering is on by default — required for sub_filter below.
|
|
|
|
|
|
|
|
|
|
| 170 |
|
| 171 |
# ── Server-URL localStorage fix ───────────────────────────────
|
| 172 |
# Root cause of "New Session doesn't work" / "AI never responds":
|
|
|
|
| 174 |
# "opencode.settings.dat:defaultServerUrl". If a previous visit stored
|
| 175 |
# a wrong URL (e.g. http://localhost:4096 from an older config), every
|
| 176 |
# API call fails silently in the browser — curl tests pass because they
|
| 177 |
+
# bypass localStorage entirely. This script runs BEFORE the SPA
|
| 178 |
+
# initialises and clears any stale URL that doesn't match the current
|
| 179 |
+
# public origin, so the SPA falls back to location.origin (correct).
|
| 180 |
#
|
| 181 |
# The upstream CSP hash covers only the theme-preload script, so we
|
| 182 |
+
# strip it and emit an equivalent policy that also allows our fix.
|
|
|
|
| 183 |
proxy_hide_header Content-Security-Policy;
|
| 184 |
add_header Content-Security-Policy
|
| 185 |
"default-src 'self'; script-src 'self' 'unsafe-inline' 'wasm-unsafe-eval'; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:; font-src 'self' data:; media-src 'self' data:; connect-src * data:;"
|
|
|
|
| 188 |
sub_filter '</head>'
|
| 189 |
'<script>!function(){try{var k="opencode.settings.dat:defaultServerUrl",s=localStorage.getItem(k);if(s&&s!==location.origin)localStorage.removeItem(k);}catch(e){}}();</script></head>';
|
| 190 |
sub_filter_once on;
|
| 191 |
+
# (no sub_filter_types needed — text/html is processed by default)
|
| 192 |
}
|
| 193 |
}
|
| 194 |
NGINXEOF
|