@@ -69,6 +69,21 @@ func (f *FrankenPHPModule) Provision(ctx caddy.Context) error {
6969 return fmt .Errorf (`expected ctx.App("frankenphp") to return *FrankenPHPApp, got nil` )
7070 }
7171
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+
7287 workers , err := fapp .addModuleWorkers (f .Workers ... )
7388 if err != nil {
7489 return err
@@ -161,12 +176,11 @@ func (f *FrankenPHPModule) ServeHTTP(w http.ResponseWriter, r *http.Request, _ c
161176 }
162177 }
163178
164- fullScriptPath , _ := fastabs .FastAbs (documentRoot + "/" + r .URL .Path )
165-
166179 workerName := ""
167180 for _ , w := range f .Workers {
168- if p , _ := fastabs . FastAbs ( w . FileName ); p == fullScriptPath {
181+ if w . matchesPath ( r , documentRoot ) {
169182 workerName = w .Name
183+ break
170184 }
171185 }
172186
@@ -230,12 +244,11 @@ func (f *FrankenPHPModule) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
230244 f .ResolveRootSymlink = & v
231245
232246 case "worker" :
233- for d . NextBlock ( 1 ) {
234- }
235- for d . NextArg () {
247+ wc , err := parseWorkerConfig ( d )
248+ if err != nil {
249+ return err
236250 }
237- // Skip "worker" blocks in the first pass
238- continue
251+ f .Workers = append (f .Workers , wc )
239252
240253 default :
241254 allowedDirectives := "root, split, env, resolve_root_symlink, worker"
@@ -244,43 +257,13 @@ func (f *FrankenPHPModule) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
244257 }
245258 }
246259
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 )
283265 }
266+ fileNames [w .FileName ] = struct {}{}
284267 }
285268
286269 return nil
@@ -418,6 +401,13 @@ func parsePhpServer(h httpcaddyfile.Helper) ([]httpcaddyfile.ConfigValue, error)
418401 // unmarshaler can read it from the start
419402 dispenser .Reset ()
420403
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+
421411 if frankenphp .EmbeddedAppPath != "" {
422412 if phpsrv .Root == "" {
423413 phpsrv .Root = filepath .Join (frankenphp .EmbeddedAppPath , defaultDocumentRoot )
@@ -433,6 +423,9 @@ func parsePhpServer(h httpcaddyfile.Helper) ([]httpcaddyfile.ConfigValue, error)
433423 // set up a route list that we'll append to
434424 routes := caddyhttp.RouteList {}
435425
426+ // prepend routes from the 'worker match *' directives
427+ routes = prependWorkerRoutes (routes , h , phpsrv , fsrv , disableFsrv )
428+
436429 // set the list of allowed path segments on which to split
437430 phpsrv .SplitPath = extensions
438431
@@ -521,15 +514,6 @@ func parsePhpServer(h httpcaddyfile.Helper) ([]httpcaddyfile.ConfigValue, error)
521514 "path" : h .JSON (pathList ),
522515 }
523516
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-
533517 // create the PHP route which is
534518 // conditional on matching PHP files
535519 phpRoute := caddyhttp.Route {
@@ -576,3 +560,52 @@ func parsePhpServer(h httpcaddyfile.Helper) ([]httpcaddyfile.ConfigValue, error)
576560 },
577561 }, nil
578562}
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