@@ -69,6 +69,21 @@ func (f *FrankenPHPModule) Provision(ctx caddy.Context) error {
69
69
return fmt .Errorf (`expected ctx.App("frankenphp") to return *FrankenPHPApp, got nil` )
70
70
}
71
71
72
+ for i , wc := range f .Workers {
73
+
74
+ // make the file path absolute from the public directory
75
+ // this can only be done if the root is definied inside php_server
76
+ if ! filepath .IsAbs (wc .FileName ) && f .Root != "" {
77
+ wc .FileName = filepath .Join (f .Root , wc .FileName )
78
+ }
79
+
80
+ // Inherit environment variables from the parent php_server directive
81
+ if f .Env != nil {
82
+ wc .inheritEnv (f .Env )
83
+ }
84
+ f .Workers [i ] = wc
85
+ }
86
+
72
87
workers , err := fapp .addModuleWorkers (f .Workers ... )
73
88
if err != nil {
74
89
return err
@@ -161,12 +176,11 @@ func (f *FrankenPHPModule) ServeHTTP(w http.ResponseWriter, r *http.Request, _ c
161
176
}
162
177
}
163
178
164
- fullScriptPath , _ := fastabs .FastAbs (documentRoot + "/" + r .URL .Path )
165
-
166
179
workerName := ""
167
180
for _ , w := range f .Workers {
168
- if p , _ := fastabs . FastAbs ( w . FileName ); p == fullScriptPath {
181
+ if w . matchesPath ( r , documentRoot ) {
169
182
workerName = w .Name
183
+ break
170
184
}
171
185
}
172
186
@@ -230,12 +244,11 @@ func (f *FrankenPHPModule) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
230
244
f .ResolveRootSymlink = & v
231
245
232
246
case "worker" :
233
- for d . NextBlock ( 1 ) {
234
- }
235
- for d . NextArg () {
247
+ wc , err := parseWorkerConfig ( d )
248
+ if err != nil {
249
+ return err
236
250
}
237
- // Skip "worker" blocks in the first pass
238
- continue
251
+ f .Workers = append (f .Workers , wc )
239
252
240
253
default :
241
254
allowedDirectives := "root, split, env, resolve_root_symlink, worker"
@@ -244,43 +257,13 @@ func (f *FrankenPHPModule) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
244
257
}
245
258
}
246
259
247
- // Second pass: Parse only "worker" blocks
248
- d .Reset ()
249
- for d .Next () {
250
- for d .NextBlock (0 ) {
251
- if d .Val () == "worker" {
252
- wc , err := parseWorkerConfig (d )
253
- if err != nil {
254
- return err
255
- }
256
-
257
- // Inherit environment variables from the parent php_server directive
258
- if ! filepath .IsAbs (wc .FileName ) && f .Root != "" {
259
- wc .FileName = filepath .Join (f .Root , wc .FileName )
260
- }
261
-
262
- if f .Env != nil {
263
- if wc .Env == nil {
264
- wc .Env = make (map [string ]string )
265
- }
266
- for k , v := range f .Env {
267
- // Only set if not already defined in the worker
268
- if _ , exists := wc .Env [k ]; ! exists {
269
- wc .Env [k ] = v
270
- }
271
- }
272
- }
273
-
274
- // Check if a worker with this filename already exists in this module
275
- for _ , existingWorker := range f .Workers {
276
- if existingWorker .FileName == wc .FileName {
277
- return fmt .Errorf (`workers in a single "php_server" block must not have duplicate filenames: %q` , wc .FileName )
278
- }
279
- }
280
-
281
- f .Workers = append (f .Workers , wc )
282
- }
260
+ // Check if a worker with this filename already exists in this module
261
+ fileNames := make (map [string ]struct {}, len (f .Workers ))
262
+ for _ , w := range f .Workers {
263
+ if _ , ok := fileNames [w .FileName ]; ok {
264
+ return fmt .Errorf (`workers in a single "php_server" block must not have duplicate filenames: %q` , w .FileName )
283
265
}
266
+ fileNames [w .FileName ] = struct {}{}
284
267
}
285
268
286
269
return nil
@@ -418,6 +401,13 @@ func parsePhpServer(h httpcaddyfile.Helper) ([]httpcaddyfile.ConfigValue, error)
418
401
// unmarshaler can read it from the start
419
402
dispenser .Reset ()
420
403
404
+ // the rest of the config is specified by the user
405
+ // using the php directive syntax
406
+ dispenser .Next () // consume the directive name
407
+ if err := phpsrv .UnmarshalCaddyfile (dispenser ); err != nil {
408
+ return nil , err
409
+ }
410
+
421
411
if frankenphp .EmbeddedAppPath != "" {
422
412
if phpsrv .Root == "" {
423
413
phpsrv .Root = filepath .Join (frankenphp .EmbeddedAppPath , defaultDocumentRoot )
@@ -433,6 +423,9 @@ func parsePhpServer(h httpcaddyfile.Helper) ([]httpcaddyfile.ConfigValue, error)
433
423
// set up a route list that we'll append to
434
424
routes := caddyhttp.RouteList {}
435
425
426
+ // prepend routes from the 'worker match *' directives
427
+ routes = prependWorkerRoutes (routes , h , phpsrv , fsrv , disableFsrv )
428
+
436
429
// set the list of allowed path segments on which to split
437
430
phpsrv .SplitPath = extensions
438
431
@@ -521,15 +514,6 @@ func parsePhpServer(h httpcaddyfile.Helper) ([]httpcaddyfile.ConfigValue, error)
521
514
"path" : h .JSON (pathList ),
522
515
}
523
516
524
- // the rest of the config is specified by the user
525
- // using the php directive syntax
526
- dispenser .Next () // consume the directive name
527
- err = phpsrv .UnmarshalCaddyfile (dispenser )
528
-
529
- if err != nil {
530
- return nil , err
531
- }
532
-
533
517
// create the PHP route which is
534
518
// conditional on matching PHP files
535
519
phpRoute := caddyhttp.Route {
@@ -576,3 +560,52 @@ func parsePhpServer(h httpcaddyfile.Helper) ([]httpcaddyfile.ConfigValue, error)
576
560
},
577
561
}, nil
578
562
}
563
+
564
+ // workers can also match a path without being in the public directory
565
+ // in this case we need to prepend the worker routes to the existing routes
566
+ func prependWorkerRoutes (routes caddyhttp.RouteList , h httpcaddyfile.Helper , f FrankenPHPModule , fsrv caddy.Module , disableFsrv bool ) caddyhttp.RouteList {
567
+ allWorkerMatches := caddyhttp.MatchPath {}
568
+ for _ , w := range f .Workers {
569
+ for _ , path := range w .MatchPath {
570
+ allWorkerMatches = append (allWorkerMatches , path )
571
+ }
572
+ }
573
+
574
+ if len (allWorkerMatches ) == 0 {
575
+ return routes
576
+ }
577
+
578
+ // if there are match patterns, we need to check for files beforehand
579
+ if ! disableFsrv {
580
+ routes = append (routes , caddyhttp.Route {
581
+ MatcherSetsRaw : []caddy.ModuleMap {
582
+ caddy.ModuleMap {
583
+ "file" : h .JSON (fileserver.MatchFile {
584
+ TryFiles : []string {"{http.request.uri.path}" },
585
+ Root : f .Root ,
586
+ }),
587
+ "not" : h .JSON (caddyhttp.MatchNot {
588
+ MatcherSetsRaw : []caddy.ModuleMap {
589
+ {"path" : h .JSON (caddyhttp.MatchPath {"*.php" })},
590
+ },
591
+ }),
592
+ },
593
+ },
594
+ HandlersRaw : []json.RawMessage {
595
+ caddyconfig .JSONModuleObject (fsrv , "handler" , "file_server" , nil ),
596
+ },
597
+ })
598
+ }
599
+
600
+ // forward matching routes to the PHP handler
601
+ routes = append (routes , caddyhttp.Route {
602
+ MatcherSetsRaw : []caddy.ModuleMap {
603
+ caddy.ModuleMap {"path" : h .JSON (allWorkerMatches )},
604
+ },
605
+ HandlersRaw : []json.RawMessage {
606
+ caddyconfig .JSONModuleObject (f , "handler" , "php" , nil ),
607
+ },
608
+ })
609
+
610
+ return routes
611
+ }
0 commit comments