mirror of
https://github.com/caddyserver/caddy.git
synced 2024-12-27 06:03:48 +03:00
fastcgi: Implement / redirect for index.php with php_fastcgi directive (#2754)
* fastcgi: Implement / redirect for index.php with php_fastcgi directive See #2752 and https://caddy.community/t/v2-redirect-path-to-path-index-php-with-assets/6196?u=matt * caddyhttp: MatchNegate implements json.Marshaler * fastcgi: Add /index.php element to try_files matcher * fastcgi: Make /index.php redirect permanent
This commit is contained in:
parent
d030bfdae0
commit
484cee1ac1
2 changed files with 42 additions and 9 deletions
|
@ -66,9 +66,9 @@ type (
|
||||||
|
|
||||||
// MatchNegate matches requests by negating its matchers' results.
|
// MatchNegate matches requests by negating its matchers' results.
|
||||||
MatchNegate struct {
|
MatchNegate struct {
|
||||||
matchersRaw map[string]json.RawMessage
|
MatchersRaw map[string]json.RawMessage `json:"-"`
|
||||||
|
|
||||||
matchers MatcherSet
|
Matchers MatcherSet `json:"-"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// MatchStarlarkExpr matches requests by evaluating a Starlark expression.
|
// MatchStarlarkExpr matches requests by evaluating a Starlark expression.
|
||||||
|
@ -400,7 +400,12 @@ func (MatchNegate) CaddyModule() caddy.ModuleInfo {
|
||||||
// the struct, but we need a struct because we need another
|
// the struct, but we need a struct because we need another
|
||||||
// field just for the provisioned modules.
|
// field just for the provisioned modules.
|
||||||
func (m *MatchNegate) UnmarshalJSON(data []byte) error {
|
func (m *MatchNegate) UnmarshalJSON(data []byte) error {
|
||||||
return json.Unmarshal(data, &m.matchersRaw)
|
return json.Unmarshal(data, &m.MatchersRaw)
|
||||||
|
}
|
||||||
|
|
||||||
|
// MarshalJSON marshals m's matchers.
|
||||||
|
func (m MatchNegate) MarshalJSON() ([]byte, error) {
|
||||||
|
return json.Marshal(m.MatchersRaw)
|
||||||
}
|
}
|
||||||
|
|
||||||
// UnmarshalCaddyfile implements caddyfile.Unmarshaler.
|
// UnmarshalCaddyfile implements caddyfile.Unmarshaler.
|
||||||
|
@ -411,21 +416,21 @@ func (m *MatchNegate) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
|
||||||
|
|
||||||
// Provision loads the matcher modules to be negated.
|
// Provision loads the matcher modules to be negated.
|
||||||
func (m *MatchNegate) Provision(ctx caddy.Context) error {
|
func (m *MatchNegate) Provision(ctx caddy.Context) error {
|
||||||
for modName, rawMsg := range m.matchersRaw {
|
for modName, rawMsg := range m.MatchersRaw {
|
||||||
val, err := ctx.LoadModule("http.matchers."+modName, rawMsg)
|
val, err := ctx.LoadModule("http.matchers."+modName, rawMsg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("loading matcher module '%s': %v", modName, err)
|
return fmt.Errorf("loading matcher module '%s': %v", modName, err)
|
||||||
}
|
}
|
||||||
m.matchers = append(m.matchers, val.(RequestMatcher))
|
m.Matchers = append(m.Matchers, val.(RequestMatcher))
|
||||||
}
|
}
|
||||||
m.matchersRaw = nil // allow GC to deallocate
|
m.MatchersRaw = nil // allow GC to deallocate
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Match returns true if r matches m. Since this matcher negates the
|
// Match returns true if r matches m. Since this matcher negates the
|
||||||
// embedded matchers, false is returned if any of its matchers match.
|
// embedded matchers, false is returned if any of its matchers match.
|
||||||
func (m MatchNegate) Match(r *http.Request) bool {
|
func (m MatchNegate) Match(r *http.Request) bool {
|
||||||
return !m.matchers.Match(r)
|
return !m.Matchers.Match(r)
|
||||||
}
|
}
|
||||||
|
|
||||||
// CaddyModule returns the Caddy module information.
|
// CaddyModule returns the Caddy module information.
|
||||||
|
@ -686,4 +691,7 @@ var (
|
||||||
_ caddyfile.Unmarshaler = (*MatchHeaderRE)(nil)
|
_ caddyfile.Unmarshaler = (*MatchHeaderRE)(nil)
|
||||||
_ caddyfile.Unmarshaler = (*MatchProtocol)(nil)
|
_ caddyfile.Unmarshaler = (*MatchProtocol)(nil)
|
||||||
_ caddyfile.Unmarshaler = (*MatchRemoteIP)(nil)
|
_ caddyfile.Unmarshaler = (*MatchRemoteIP)(nil)
|
||||||
|
|
||||||
|
_ json.Marshaler = (*MatchNegate)(nil)
|
||||||
|
_ json.Unmarshaler = (*MatchNegate)(nil)
|
||||||
)
|
)
|
||||||
|
|
|
@ -16,6 +16,7 @@ package fastcgi
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"net/http"
|
||||||
|
|
||||||
"github.com/caddyserver/caddy/v2/caddyconfig"
|
"github.com/caddyserver/caddy/v2/caddyconfig"
|
||||||
"github.com/caddyserver/caddy/v2/caddyconfig/caddyfile"
|
"github.com/caddyserver/caddy/v2/caddyconfig/caddyfile"
|
||||||
|
@ -114,10 +115,30 @@ func parsePHPFastCGI(h httpcaddyfile.Helper) ([]httpcaddyfile.ConfigValue, error
|
||||||
return nil, h.ArgErr()
|
return nil, h.ArgErr()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// route to redirect to canonical path if index PHP file
|
||||||
|
redirMatcherSet := map[string]json.RawMessage{
|
||||||
|
"file": h.JSON(fileserver.MatchFile{
|
||||||
|
TryFiles: []string{"{http.request.uri.path}/index.php"},
|
||||||
|
}, nil),
|
||||||
|
"not": h.JSON(caddyhttp.MatchNegate{
|
||||||
|
MatchersRaw: map[string]json.RawMessage{
|
||||||
|
"path": h.JSON(caddyhttp.MatchPath{"*/"}, nil),
|
||||||
|
},
|
||||||
|
}, nil),
|
||||||
|
}
|
||||||
|
redirHandler := caddyhttp.StaticResponse{
|
||||||
|
StatusCode: caddyhttp.WeakString("308"),
|
||||||
|
Headers: http.Header{"Location": []string{"{http.request.uri.path}/"}},
|
||||||
|
}
|
||||||
|
redirRoute := caddyhttp.Route{
|
||||||
|
MatcherSetsRaw: []map[string]json.RawMessage{redirMatcherSet},
|
||||||
|
HandlersRaw: []json.RawMessage{caddyconfig.JSONModuleObject(redirHandler, "handler", "static_response", nil)},
|
||||||
|
}
|
||||||
|
|
||||||
// route to rewrite to PHP index file
|
// route to rewrite to PHP index file
|
||||||
rewriteMatcherSet := map[string]json.RawMessage{
|
rewriteMatcherSet := map[string]json.RawMessage{
|
||||||
"file": h.JSON(fileserver.MatchFile{
|
"file": h.JSON(fileserver.MatchFile{
|
||||||
TryFiles: []string{"{http.request.uri.path}", "index.php"},
|
TryFiles: []string{"{http.request.uri.path}", "{http.request.uri.path}/index.php", "index.php"},
|
||||||
}, nil),
|
}, nil),
|
||||||
}
|
}
|
||||||
rewriteHandler := rewrite.Rewrite{
|
rewriteHandler := rewrite.Rewrite{
|
||||||
|
@ -175,7 +196,7 @@ func parsePHPFastCGI(h httpcaddyfile.Helper) ([]httpcaddyfile.ConfigValue, error
|
||||||
// wrap ours in a subroute and return that
|
// wrap ours in a subroute and return that
|
||||||
if hasUserMatcher {
|
if hasUserMatcher {
|
||||||
subroute := caddyhttp.Subroute{
|
subroute := caddyhttp.Subroute{
|
||||||
Routes: caddyhttp.RouteList{rewriteRoute, rpRoute},
|
Routes: caddyhttp.RouteList{redirRoute, rewriteRoute, rpRoute},
|
||||||
}
|
}
|
||||||
return []httpcaddyfile.ConfigValue{
|
return []httpcaddyfile.ConfigValue{
|
||||||
{
|
{
|
||||||
|
@ -191,6 +212,10 @@ func parsePHPFastCGI(h httpcaddyfile.Helper) ([]httpcaddyfile.ConfigValue, error
|
||||||
// if the user did not specify a matcher, then
|
// if the user did not specify a matcher, then
|
||||||
// we can just use our own matchers
|
// we can just use our own matchers
|
||||||
return []httpcaddyfile.ConfigValue{
|
return []httpcaddyfile.ConfigValue{
|
||||||
|
{
|
||||||
|
Class: "route",
|
||||||
|
Value: redirRoute,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
Class: "route",
|
Class: "route",
|
||||||
Value: rewriteRoute,
|
Value: rewriteRoute,
|
||||||
|
|
Loading…
Reference in a new issue