Fix Bot commited on
Commit
f48bf36
·
1 Parent(s): 819218e

fix: split OpenCode nginx into two locations — /api/ off, / on

Browse files

nginx 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.

Files changed (1) hide show
  1. 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 text/html;
148
  }
149
 
150
- # ── OpenCode chat UI + REST API + SSE streaming ───────────────────
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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 the backend from gzip-compressing responses — compressed SSE
158
- # cannot be decompressed incrementally by the browser.
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 initialises and
174
- # clears any stale URL that does not match the current public origin.
 
175
  #
176
  # The upstream CSP hash covers only the theme-preload script, so we
177
- # must strip it and emit a permissive replacement that still blocks
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 text/html;
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