Skip to content

Commit

Permalink
perf: cache document root resolution when possible
Browse files Browse the repository at this point in the history
  • Loading branch information
dunglas committed Aug 26, 2024
1 parent 4a85555 commit db12b4e
Show file tree
Hide file tree
Showing 2 changed files with 58 additions and 5 deletions.
53 changes: 48 additions & 5 deletions caddy/caddy.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,11 @@ package caddy
import (
"encoding/json"
"errors"
"fmt"
"net/http"
"path/filepath"
"strconv"
"strings"

"github.com/caddyserver/caddy/v2"
"github.com/caddyserver/caddy/v2/caddyconfig"
Expand Down Expand Up @@ -212,8 +214,10 @@ type FrankenPHPModule struct {
// Env sets an extra environment variable to the given value. Can be specified more than once for multiple environment variables.
Env map[string]string `json:"env,omitempty"`

preparedEnv frankenphp.PreparedEnv
logger *zap.Logger
resolvedDocumentRoot string
preparedEnv frankenphp.PreparedEnv
preparedEnvNeedsReplacement bool
logger *zap.Logger
}

// CaddyModule returns the Caddy module information.
Expand Down Expand Up @@ -251,30 +255,69 @@ func (f *FrankenPHPModule) Provision(ctx caddy.Context) error {
f.ResolveRootSymlink = &rrs
}

if !needReplacement(f.Root) {
root, err := filepath.Abs(f.Root)
if err != nil {
return fmt.Errorf("unable to make the root path absolute: %w", err)
}
f.resolvedDocumentRoot = root

if *f.ResolveRootSymlink {
root, err := filepath.EvalSymlinks(root)
if err != nil {
return fmt.Errorf("unable to resolve root symlink: %w", err)
}

f.resolvedDocumentRoot = root
}
}

if f.preparedEnv == nil {
f.preparedEnv = frankenphp.PrepareEnv(f.Env)

for e := range f.preparedEnv {
if needReplacement(e) {
f.preparedEnvNeedsReplacement = true

break
}
}
}

return nil
}

// needReplacement checks if a string contains placeholdes.
func needReplacement(s string) bool {
return strings.Contains(s, "{") || strings.Contains(s, "}")
}

// ServeHTTP implements caddyhttp.MiddlewareHandler.
// TODO: Expose TLS versions as env vars, as Apache's mod_ssl: https://github.com/caddyserver/caddy/blob/master/modules/caddyhttp/reverseproxy/fastcgi/fastcgi.go#L298
func (f FrankenPHPModule) ServeHTTP(w http.ResponseWriter, r *http.Request, _ caddyhttp.Handler) error {
origReq := r.Context().Value(caddyhttp.OriginalRequestCtxKey).(http.Request)
repl := r.Context().Value(caddy.ReplacerCtxKey).(*caddy.Replacer)

documentRoot := repl.ReplaceKnown(f.Root, "")
var documentRootOption frankenphp.RequestOption
if f.resolvedDocumentRoot == "" {
documentRootOption = frankenphp.WithRequestDocumentRoot(repl.ReplaceKnown(f.Root, ""), *f.ResolveRootSymlink)
} else {
documentRootOption = frankenphp.WithRequestResolvedDocumentRoot(f.resolvedDocumentRoot)
}

env := make(map[string]string, len(f.preparedEnv)+1)
env["REQUEST_URI\x00"] = origReq.URL.RequestURI()
for k, v := range f.preparedEnv {
env[k] = repl.ReplaceKnown(v, "")
if f.preparedEnvNeedsReplacement {
env[k] = repl.ReplaceKnown(v, "")
} else {
env[k] = v
}
}

fr, err := frankenphp.NewRequestWithContext(
r,
frankenphp.WithRequestDocumentRoot(documentRoot, *f.ResolveRootSymlink),
documentRootOption,
frankenphp.WithRequestSplitPath(f.SplitPath),
frankenphp.WithRequestPreparedEnv(env),
)
Expand Down
10 changes: 10 additions & 0 deletions request_options.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,16 @@ func WithRequestDocumentRoot(documentRoot string, resolveSymlink bool) RequestOp
}
}

// WithRequestResolvedDocumentRoot is similar to WithRequestDocumentRoot
// but doesn't does any checks or resolving on the path to improve performance.
func WithRequestResolvedDocumentRoot(documentRoot string) RequestOption {
return func(o *FrankenPHPContext) error {
o.documentRoot = documentRoot

return nil
}
}

// The path in the URL will be split into two, with the first piece ending
// with the value of SplitPath. The first piece will be assumed as the
// actual resource (CGI script) name, and the second piece will be set to
Expand Down

0 comments on commit db12b4e

Please sign in to comment.