mirror of
https://github.com/caddyserver/caddy.git
synced 2025-01-21 09:55:45 +03:00
Add root option to fastcgi directive (#1337)
This commit is contained in:
parent
8464020f7c
commit
6bac558c98
3 changed files with 61 additions and 10 deletions
|
@ -23,7 +23,6 @@ type Handler struct {
|
||||||
Next httpserver.Handler
|
Next httpserver.Handler
|
||||||
Rules []Rule
|
Rules []Rule
|
||||||
Root string
|
Root string
|
||||||
AbsRoot string // same as root, but absolute path
|
|
||||||
FileSys http.FileSystem
|
FileSys http.FileSystem
|
||||||
|
|
||||||
// These are sent to CGI scripts in env variables
|
// These are sent to CGI scripts in env variables
|
||||||
|
@ -184,7 +183,7 @@ func (h Handler) buildEnv(r *http.Request, rule Rule, fpath string) (map[string]
|
||||||
var env map[string]string
|
var env map[string]string
|
||||||
|
|
||||||
// Get absolute path of requested resource
|
// Get absolute path of requested resource
|
||||||
absPath := filepath.Join(h.AbsRoot, fpath)
|
absPath := filepath.Join(rule.Root, fpath)
|
||||||
|
|
||||||
// Separate remote IP and port; more lenient than net.SplitHostPort
|
// Separate remote IP and port; more lenient than net.SplitHostPort
|
||||||
var ip, port string
|
var ip, port string
|
||||||
|
@ -244,7 +243,7 @@ func (h Handler) buildEnv(r *http.Request, rule Rule, fpath string) (map[string]
|
||||||
"SERVER_SOFTWARE": h.SoftwareName + "/" + h.SoftwareVersion,
|
"SERVER_SOFTWARE": h.SoftwareName + "/" + h.SoftwareVersion,
|
||||||
|
|
||||||
// Other variables
|
// Other variables
|
||||||
"DOCUMENT_ROOT": h.AbsRoot,
|
"DOCUMENT_ROOT": rule.Root,
|
||||||
"DOCUMENT_URI": docURI,
|
"DOCUMENT_URI": docURI,
|
||||||
"HTTP_HOST": r.Host, // added here, since not always part of headers
|
"HTTP_HOST": r.Host, // added here, since not always part of headers
|
||||||
"REQUEST_URI": reqURI,
|
"REQUEST_URI": reqURI,
|
||||||
|
@ -256,7 +255,7 @@ func (h Handler) buildEnv(r *http.Request, rule Rule, fpath string) (map[string]
|
||||||
// should only exist if PATH_INFO is defined.
|
// should only exist if PATH_INFO is defined.
|
||||||
// Info: https://www.ietf.org/rfc/rfc3875 Page 14
|
// Info: https://www.ietf.org/rfc/rfc3875 Page 14
|
||||||
if env["PATH_INFO"] != "" {
|
if env["PATH_INFO"] != "" {
|
||||||
env["PATH_TRANSLATED"] = filepath.Join(h.AbsRoot, pathInfo) // Info: http://www.oreilly.com/openbook/cgi/ch02_04.html
|
env["PATH_TRANSLATED"] = filepath.Join(rule.Root, pathInfo) // Info: http://www.oreilly.com/openbook/cgi/ch02_04.html
|
||||||
}
|
}
|
||||||
|
|
||||||
// Some web apps rely on knowing HTTPS or not
|
// Some web apps rely on knowing HTTPS or not
|
||||||
|
@ -295,6 +294,10 @@ type Rule struct {
|
||||||
// Always process files with this extension with fastcgi.
|
// Always process files with this extension with fastcgi.
|
||||||
Ext string
|
Ext string
|
||||||
|
|
||||||
|
// Use this directory as the fastcgi root directory. Defaults to the root
|
||||||
|
// directory of the parent virtual host.
|
||||||
|
Root string
|
||||||
|
|
||||||
// The path in the URL will be split into two, with the first piece ending
|
// 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
|
// 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
|
// actual resource (CGI script) name, and the second piece will be set to
|
||||||
|
|
|
@ -22,10 +22,6 @@ func init() {
|
||||||
// setup configures a new FastCGI middleware instance.
|
// setup configures a new FastCGI middleware instance.
|
||||||
func setup(c *caddy.Controller) error {
|
func setup(c *caddy.Controller) error {
|
||||||
cfg := httpserver.GetConfig(c)
|
cfg := httpserver.GetConfig(c)
|
||||||
absRoot, err := filepath.Abs(cfg.Root)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
rules, err := fastcgiParse(c)
|
rules, err := fastcgiParse(c)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -37,7 +33,6 @@ func setup(c *caddy.Controller) error {
|
||||||
Next: next,
|
Next: next,
|
||||||
Rules: rules,
|
Rules: rules,
|
||||||
Root: cfg.Root,
|
Root: cfg.Root,
|
||||||
AbsRoot: absRoot,
|
|
||||||
FileSys: http.Dir(cfg.Root),
|
FileSys: http.Dir(cfg.Root),
|
||||||
SoftwareName: caddy.AppName,
|
SoftwareName: caddy.AppName,
|
||||||
SoftwareVersion: caddy.AppVersion,
|
SoftwareVersion: caddy.AppVersion,
|
||||||
|
@ -52,6 +47,12 @@ func setup(c *caddy.Controller) error {
|
||||||
func fastcgiParse(c *caddy.Controller) ([]Rule, error) {
|
func fastcgiParse(c *caddy.Controller) ([]Rule, error) {
|
||||||
var rules []Rule
|
var rules []Rule
|
||||||
|
|
||||||
|
cfg := httpserver.GetConfig(c)
|
||||||
|
absRoot, err := filepath.Abs(cfg.Root)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
for c.Next() {
|
for c.Next() {
|
||||||
args := c.RemainingArgs()
|
args := c.RemainingArgs()
|
||||||
|
|
||||||
|
@ -59,7 +60,12 @@ func fastcgiParse(c *caddy.Controller) ([]Rule, error) {
|
||||||
return rules, c.ArgErr()
|
return rules, c.ArgErr()
|
||||||
}
|
}
|
||||||
|
|
||||||
rule := Rule{Path: args[0], ReadTimeout: 60 * time.Second, SendTimeout: 60 * time.Second}
|
rule := Rule{
|
||||||
|
Root: absRoot,
|
||||||
|
Path: args[0],
|
||||||
|
ReadTimeout: 60 * time.Second,
|
||||||
|
SendTimeout: 60 * time.Second,
|
||||||
|
}
|
||||||
upstreams := []string{args[1]}
|
upstreams := []string{args[1]}
|
||||||
|
|
||||||
if len(args) == 3 {
|
if len(args) == 3 {
|
||||||
|
@ -76,6 +82,12 @@ func fastcgiParse(c *caddy.Controller) ([]Rule, error) {
|
||||||
|
|
||||||
for c.NextBlock() {
|
for c.NextBlock() {
|
||||||
switch c.Val() {
|
switch c.Val() {
|
||||||
|
case "root":
|
||||||
|
if !c.NextArg() {
|
||||||
|
return rules, c.ArgErr()
|
||||||
|
}
|
||||||
|
rule.Root = c.Val()
|
||||||
|
|
||||||
case "ext":
|
case "ext":
|
||||||
if !c.NextArg() {
|
if !c.NextArg() {
|
||||||
return rules, c.ArgErr()
|
return rules, c.ArgErr()
|
||||||
|
|
|
@ -2,6 +2,7 @@ package fastcgi
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"os"
|
||||||
"reflect"
|
"reflect"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
@ -61,6 +62,11 @@ func (p *persistentDialer) Equals(q *persistentDialer) bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestFastcgiParse(t *testing.T) {
|
func TestFastcgiParse(t *testing.T) {
|
||||||
|
rootPath, err := os.Getwd()
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("Can't determine current working directory; got '%v'", err)
|
||||||
|
}
|
||||||
|
|
||||||
defaultAddress := "127.0.0.1:9001"
|
defaultAddress := "127.0.0.1:9001"
|
||||||
network, address := parseAddress(defaultAddress)
|
network, address := parseAddress(defaultAddress)
|
||||||
t.Logf("Address '%v' was parsed to network '%v' and address '%v'", defaultAddress, network, address)
|
t.Logf("Address '%v' was parsed to network '%v' and address '%v'", defaultAddress, network, address)
|
||||||
|
@ -73,6 +79,21 @@ func TestFastcgiParse(t *testing.T) {
|
||||||
|
|
||||||
{`fastcgi /blog 127.0.0.1:9000 php`,
|
{`fastcgi /blog 127.0.0.1:9000 php`,
|
||||||
false, []Rule{{
|
false, []Rule{{
|
||||||
|
Root: rootPath,
|
||||||
|
Path: "/blog",
|
||||||
|
Address: "127.0.0.1:9000",
|
||||||
|
Ext: ".php",
|
||||||
|
SplitPath: ".php",
|
||||||
|
dialer: &loadBalancingDialer{dialers: []dialer{basicDialer{network: "tcp", address: "127.0.0.1:9000", timeout: 60 * time.Second}}},
|
||||||
|
IndexFiles: []string{"index.php"},
|
||||||
|
ReadTimeout: 60 * time.Second,
|
||||||
|
SendTimeout: 60 * time.Second,
|
||||||
|
}}},
|
||||||
|
{`fastcgi /blog 127.0.0.1:9000 php {
|
||||||
|
root /tmp
|
||||||
|
}`,
|
||||||
|
false, []Rule{{
|
||||||
|
Root: "/tmp",
|
||||||
Path: "/blog",
|
Path: "/blog",
|
||||||
Address: "127.0.0.1:9000",
|
Address: "127.0.0.1:9000",
|
||||||
Ext: ".php",
|
Ext: ".php",
|
||||||
|
@ -86,6 +107,7 @@ func TestFastcgiParse(t *testing.T) {
|
||||||
upstream 127.0.0.1:9001
|
upstream 127.0.0.1:9001
|
||||||
}`,
|
}`,
|
||||||
false, []Rule{{
|
false, []Rule{{
|
||||||
|
Root: rootPath,
|
||||||
Path: "/blog",
|
Path: "/blog",
|
||||||
Address: "127.0.0.1:9000,127.0.0.1:9001",
|
Address: "127.0.0.1:9000,127.0.0.1:9001",
|
||||||
Ext: ".php",
|
Ext: ".php",
|
||||||
|
@ -99,6 +121,7 @@ func TestFastcgiParse(t *testing.T) {
|
||||||
upstream 127.0.0.1:9001
|
upstream 127.0.0.1:9001
|
||||||
}`,
|
}`,
|
||||||
false, []Rule{{
|
false, []Rule{{
|
||||||
|
Root: rootPath,
|
||||||
Path: "/blog",
|
Path: "/blog",
|
||||||
Address: "127.0.0.1:9000,127.0.0.1:9001",
|
Address: "127.0.0.1:9000,127.0.0.1:9001",
|
||||||
Ext: "",
|
Ext: "",
|
||||||
|
@ -112,6 +135,7 @@ func TestFastcgiParse(t *testing.T) {
|
||||||
split .html
|
split .html
|
||||||
}`,
|
}`,
|
||||||
false, []Rule{{
|
false, []Rule{{
|
||||||
|
Root: rootPath,
|
||||||
Path: "/",
|
Path: "/",
|
||||||
Address: defaultAddress,
|
Address: defaultAddress,
|
||||||
Ext: "",
|
Ext: "",
|
||||||
|
@ -126,6 +150,7 @@ func TestFastcgiParse(t *testing.T) {
|
||||||
except /admin /user
|
except /admin /user
|
||||||
}`,
|
}`,
|
||||||
false, []Rule{{
|
false, []Rule{{
|
||||||
|
Root: rootPath,
|
||||||
Path: "/",
|
Path: "/",
|
||||||
Address: "127.0.0.1:9001",
|
Address: "127.0.0.1:9001",
|
||||||
Ext: "",
|
Ext: "",
|
||||||
|
@ -140,6 +165,7 @@ func TestFastcgiParse(t *testing.T) {
|
||||||
pool 0
|
pool 0
|
||||||
}`,
|
}`,
|
||||||
false, []Rule{{
|
false, []Rule{{
|
||||||
|
Root: rootPath,
|
||||||
Path: "/",
|
Path: "/",
|
||||||
Address: defaultAddress,
|
Address: defaultAddress,
|
||||||
Ext: "",
|
Ext: "",
|
||||||
|
@ -154,6 +180,7 @@ func TestFastcgiParse(t *testing.T) {
|
||||||
pool 5
|
pool 5
|
||||||
}`,
|
}`,
|
||||||
false, []Rule{{
|
false, []Rule{{
|
||||||
|
Root: rootPath,
|
||||||
Path: "/",
|
Path: "/",
|
||||||
Address: "127.0.0.1:8080,127.0.0.1:9000",
|
Address: "127.0.0.1:8080,127.0.0.1:9000",
|
||||||
Ext: "",
|
Ext: "",
|
||||||
|
@ -167,6 +194,7 @@ func TestFastcgiParse(t *testing.T) {
|
||||||
split .php
|
split .php
|
||||||
}`,
|
}`,
|
||||||
false, []Rule{{
|
false, []Rule{{
|
||||||
|
Root: rootPath,
|
||||||
Path: "/",
|
Path: "/",
|
||||||
Address: defaultAddress,
|
Address: defaultAddress,
|
||||||
Ext: "",
|
Ext: "",
|
||||||
|
@ -180,6 +208,7 @@ func TestFastcgiParse(t *testing.T) {
|
||||||
connect_timeout 5s
|
connect_timeout 5s
|
||||||
}`,
|
}`,
|
||||||
false, []Rule{{
|
false, []Rule{{
|
||||||
|
Root: rootPath,
|
||||||
Path: "/",
|
Path: "/",
|
||||||
Address: defaultAddress,
|
Address: defaultAddress,
|
||||||
Ext: "",
|
Ext: "",
|
||||||
|
@ -198,6 +227,7 @@ func TestFastcgiParse(t *testing.T) {
|
||||||
read_timeout 5s
|
read_timeout 5s
|
||||||
}`,
|
}`,
|
||||||
false, []Rule{{
|
false, []Rule{{
|
||||||
|
Root: rootPath,
|
||||||
Path: "/",
|
Path: "/",
|
||||||
Address: defaultAddress,
|
Address: defaultAddress,
|
||||||
Ext: "",
|
Ext: "",
|
||||||
|
@ -216,6 +246,7 @@ func TestFastcgiParse(t *testing.T) {
|
||||||
send_timeout 5s
|
send_timeout 5s
|
||||||
}`,
|
}`,
|
||||||
false, []Rule{{
|
false, []Rule{{
|
||||||
|
Root: rootPath,
|
||||||
Path: "/",
|
Path: "/",
|
||||||
Address: defaultAddress,
|
Address: defaultAddress,
|
||||||
Ext: "",
|
Ext: "",
|
||||||
|
@ -250,6 +281,11 @@ func TestFastcgiParse(t *testing.T) {
|
||||||
}
|
}
|
||||||
for j, actualFastcgiConfig := range actualFastcgiConfigs {
|
for j, actualFastcgiConfig := range actualFastcgiConfigs {
|
||||||
|
|
||||||
|
if actualFastcgiConfig.Root != test.expectedFastcgiConfig[j].Root {
|
||||||
|
t.Errorf("Test %d expected %dth FastCGI Root to be %s , but got %s",
|
||||||
|
i, j, test.expectedFastcgiConfig[j].Root, actualFastcgiConfig.Root)
|
||||||
|
}
|
||||||
|
|
||||||
if actualFastcgiConfig.Path != test.expectedFastcgiConfig[j].Path {
|
if actualFastcgiConfig.Path != test.expectedFastcgiConfig[j].Path {
|
||||||
t.Errorf("Test %d expected %dth FastCGI Path to be %s , but got %s",
|
t.Errorf("Test %d expected %dth FastCGI Path to be %s , but got %s",
|
||||||
i, j, test.expectedFastcgiConfig[j].Path, actualFastcgiConfig.Path)
|
i, j, test.expectedFastcgiConfig[j].Path, actualFastcgiConfig.Path)
|
||||||
|
|
Loading…
Reference in a new issue