Skip to content

Commit aee2352

Browse files
committed
enhance: improve sandbox configuration handling and include directive processing #1430
1 parent 8522ba7 commit aee2352

File tree

2 files changed

+97
-39
lines changed

2 files changed

+97
-39
lines changed

internal/nginx/sandbox.go

Lines changed: 49 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -161,77 +161,93 @@ func generateSandboxConfig(namespace *NamespaceInfo, siteFiles, streamFiles []st
161161
func replaceIncludeDirectives(mainConf string, sandboxDir string, siteIncludeLines, streamIncludeLines []string) string {
162162
lines := strings.Split(mainConf, "\n")
163163
var result []string
164-
insideHTTP := false
165-
insideStream := false
164+
httpDepth := 0
165+
streamDepth := 0
166166
httpIncludesAdded := false
167167
streamIncludesAdded := false
168168

169+
includeRx := regexp.MustCompile(`(?i)^\s*include\s+([^;#]+);`)
170+
httpOpenRx := regexp.MustCompile(`(?i)^\s*http\s*\{`)
171+
streamOpenRx := regexp.MustCompile(`(?i)^\s*stream\s*\{`)
172+
169173
for _, line := range lines {
170174
trimmed := strings.TrimSpace(line)
171175

172-
// Track http and stream blocks
173-
if strings.HasPrefix(trimmed, "http") && strings.Contains(trimmed, "{") {
174-
insideHTTP = true
176+
// Skip processing for comment-only lines
177+
if strings.HasPrefix(trimmed, "#") {
175178
result = append(result, line)
176179
continue
177180
}
178-
if strings.HasPrefix(trimmed, "stream") && strings.Contains(trimmed, "{") {
179-
insideStream = true
181+
182+
// Detect opening of http/stream blocks
183+
if httpOpenRx.MatchString(line) {
184+
httpDepth = 1
185+
httpIncludesAdded = false
186+
result = append(result, line)
187+
continue
188+
}
189+
if streamOpenRx.MatchString(line) {
190+
streamDepth = 1
191+
streamIncludesAdded = false
180192
result = append(result, line)
181193
continue
182194
}
183195

184-
// Handle include directives
185-
if strings.Contains(trimmed, "include") {
186-
isSitesEnabled := strings.Contains(trimmed, "sites-enabled")
187-
isStreamsEnabled := strings.Contains(trimmed, "streams-enabled")
196+
// Handle include directives (non-comment)
197+
if includeRx.MatchString(line) {
198+
isSitesEnabled := strings.Contains(line, "sites-enabled")
199+
isStreamsEnabled := strings.Contains(line, "streams-enabled")
188200

189201
// If it's sites-enabled or streams-enabled, replace it
190202
if isSitesEnabled || isStreamsEnabled {
191203
// Add our sandbox-specific includes at the first occurrence
192-
if insideHTTP && isSitesEnabled && !httpIncludesAdded {
204+
if httpDepth > 0 && isSitesEnabled && !httpIncludesAdded {
193205
result = append(result, " # Sandbox-specific includes (generated for isolated testing)")
194206
result = append(result, siteIncludeLines...)
195207
httpIncludesAdded = true
196208
}
197-
if insideStream && isStreamsEnabled && !streamIncludesAdded {
209+
if streamDepth > 0 && isStreamsEnabled && !streamIncludesAdded {
198210
result = append(result, " # Sandbox-specific includes (generated for isolated testing)")
199211
result = append(result, streamIncludeLines...)
200212
streamIncludesAdded = true
201213
}
202-
continue // Skip the original include line
214+
// Skip the original include line
215+
continue
203216
}
204217

205-
// Rewrite includes to sandbox paths
218+
// Rewrite other includes to sandbox paths
206219
normalized := rewriteIncludeLineToSandbox(line, sandboxDir)
207220
if normalized != "" {
208221
result = append(result, normalized)
209222
}
210223
continue
211224
}
212225

213-
// Detect end of http/stream block
214-
if strings.Contains(line, "}") {
215-
if insideHTTP {
216-
// Add includes before closing http block if not added yet
217-
if !httpIncludesAdded {
218-
result = append(result, " # Sandbox-specific includes (generated for isolated testing)")
219-
result = append(result, siteIncludeLines...)
220-
httpIncludesAdded = true
221-
}
222-
insideHTTP = false
226+
// Before appending this line, check if it closes http/stream top-level block.
227+
openCount := strings.Count(line, "{")
228+
closeCount := strings.Count(line, "}")
229+
230+
// If current httpDepth will reach zero after this line, inject includes BEFORE the closing brace line.
231+
if httpDepth > 0 {
232+
newDepth := httpDepth + openCount - closeCount
233+
if newDepth == 0 && !httpIncludesAdded {
234+
result = append(result, " # Sandbox-specific includes (generated for isolated testing)")
235+
result = append(result, siteIncludeLines...)
236+
httpIncludesAdded = true
223237
}
224-
if insideStream {
225-
// Add includes before closing stream block if not added yet
226-
if !streamIncludesAdded {
227-
result = append(result, " # Sandbox-specific includes (generated for isolated testing)")
228-
result = append(result, streamIncludeLines...)
229-
streamIncludesAdded = true
230-
}
231-
insideStream = false
238+
httpDepth = newDepth
239+
}
240+
if streamDepth > 0 {
241+
newDepth := streamDepth + openCount - closeCount
242+
if newDepth == 0 && !streamIncludesAdded {
243+
result = append(result, " # Sandbox-specific includes (generated for isolated testing)")
244+
result = append(result, streamIncludeLines...)
245+
streamIncludesAdded = true
232246
}
247+
streamDepth = newDepth
233248
}
234249

250+
// Append current line
235251
result = append(result, line)
236252
}
237253

internal/nginx/sandbox_test.go

Lines changed: 48 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,18 +16,18 @@ func TestNormalizeIncludeLineRelativeTo(t *testing.T) {
1616
sandboxDir := "/tmp/sbx"
1717

1818
tests := []struct {
19-
name string
20-
in string
19+
name string
20+
in string
2121
wantPrefix string
2222
}{
2323
{
24-
name: "relative simple file",
25-
in: " include mime.types;",
24+
name: "relative simple file",
25+
in: " include mime.types;",
2626
wantPrefix: " include ",
2727
},
2828
{
29-
name: "relative path with subdir",
30-
in: "include ../common/snippets/*.conf;",
29+
name: "relative path with subdir",
30+
in: "include ../common/snippets/*.conf;",
3131
wantPrefix: "include ",
3232
},
3333
}
@@ -69,6 +69,11 @@ events {
6969
}
7070
7171
http {
72+
server {
73+
location / {
74+
return 200;
75+
}
76+
}
7277
include mime.types;
7378
include /etc/nginx/conf.d/*.conf;
7479
include /etc/nginx/sites-enabled/*;
@@ -83,6 +88,43 @@ stream {
8388

8489
out := replaceIncludeDirectives(mainConf, "/tmp/sbx", siteLines, streamLines)
8590

91+
// ensure site includes inserted before closing http brace (inside block)
92+
lines := strings.Split(out, "\n")
93+
httpStart := -1
94+
httpClose := -1
95+
inHttp := false
96+
depth := 0
97+
for i, l := range lines {
98+
if strings.Contains(l, "http {") && httpStart == -1 {
99+
httpStart = i
100+
inHttp = true
101+
depth = 1
102+
continue
103+
}
104+
if inHttp {
105+
depth += strings.Count(l, "{")
106+
depth -= strings.Count(l, "}")
107+
if depth == 0 {
108+
httpClose = i
109+
inHttp = false
110+
break
111+
}
112+
}
113+
}
114+
if httpStart == -1 || httpClose == -1 {
115+
t.Fatal("failed to locate http block bounds")
116+
}
117+
incIdx := -1
118+
for i := httpStart; i <= httpClose; i++ {
119+
if strings.Contains(lines[i], "/tmp/sbx/sites-enabled/a.conf;") {
120+
incIdx = i
121+
break
122+
}
123+
}
124+
if incIdx == -1 || incIdx >= httpClose {
125+
t.Fatalf("sandbox site include should be inside http block before closing brace, got index=%d close=%d", incIdx, httpClose)
126+
}
127+
86128
if strings.Contains(out, "/etc/nginx/sites-enabled/*") {
87129
t.Fatal("sites-enabled wildcard should be replaced by sandbox files")
88130
}

0 commit comments

Comments
 (0)