mirror of
https://github.com/caddyserver/caddy.git
synced 2025-01-20 22:52:58 -05:00
Merge pull request #1274 from mholt/fastcgi-timeout-defaults
Fix read timeout and add default timeout values.
This commit is contained in:
commit
76f12f475b
4 changed files with 96 additions and 70 deletions
|
@ -332,9 +332,6 @@ func TestReadTimeout(t *testing.T) {
|
||||||
t.Fatalf("Unable to create listener for test: %v", err)
|
t.Fatalf("Unable to create listener for test: %v", err)
|
||||||
}
|
}
|
||||||
defer listener.Close()
|
defer listener.Close()
|
||||||
go fcgi.Serve(listener, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
||||||
time.Sleep(time.Second * 1)
|
|
||||||
}))
|
|
||||||
|
|
||||||
network, address := parseAddress(listener.Addr().String())
|
network, address := parseAddress(listener.Addr().String())
|
||||||
handler := Handler{
|
handler := Handler{
|
||||||
|
@ -354,6 +351,10 @@ func TestReadTimeout(t *testing.T) {
|
||||||
}
|
}
|
||||||
w := httptest.NewRecorder()
|
w := httptest.NewRecorder()
|
||||||
|
|
||||||
|
go fcgi.Serve(listener, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
time.Sleep(time.Millisecond * 130)
|
||||||
|
}))
|
||||||
|
|
||||||
_, err = handler.ServeHTTP(w, r)
|
_, err = handler.ServeHTTP(w, r)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
t.Error("Expected i/o timeout error but had none")
|
t.Error("Expected i/o timeout error but had none")
|
||||||
|
|
|
@ -212,6 +212,21 @@ func (c *FCGIClient) Close() error {
|
||||||
return c.rwc.Close()
|
return c.rwc.Close()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// setReadDeadline sets a read deadline on FCGIClient based on the configured
|
||||||
|
// readTimeout. A zero value for readTimeout means no deadline will be set.
|
||||||
|
func (c *FCGIClient) setReadDeadline() error {
|
||||||
|
if c.readTimeout > 0 {
|
||||||
|
conn, ok := c.rwc.(net.Conn)
|
||||||
|
if ok {
|
||||||
|
conn.SetReadDeadline(time.Now().Add(c.readTimeout))
|
||||||
|
} else {
|
||||||
|
return fmt.Errorf("Could not set Client ReadTimeout")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func (c *FCGIClient) writeRecord(recType uint8, content []byte) error {
|
func (c *FCGIClient) writeRecord(recType uint8, content []byte) error {
|
||||||
c.mutex.Lock()
|
c.mutex.Lock()
|
||||||
defer c.mutex.Unlock()
|
defer c.mutex.Unlock()
|
||||||
|
@ -350,20 +365,10 @@ func (w *streamReader) Read(p []byte) (n int, err error) {
|
||||||
|
|
||||||
if len(p) > 0 {
|
if len(p) > 0 {
|
||||||
if len(w.buf) == 0 {
|
if len(w.buf) == 0 {
|
||||||
|
|
||||||
// filter outputs for error log
|
// filter outputs for error log
|
||||||
for {
|
for {
|
||||||
rec := &record{}
|
rec := &record{}
|
||||||
var buf []byte
|
var buf []byte
|
||||||
if readTimeout := w.c.ReadTimeout(); readTimeout > 0 {
|
|
||||||
conn, ok := w.c.rwc.(net.Conn)
|
|
||||||
if ok {
|
|
||||||
conn.SetReadDeadline(time.Now().Add(readTimeout))
|
|
||||||
} else {
|
|
||||||
err = fmt.Errorf("Could not set Client ReadTimeout")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
buf, err = rec.read(w.c.rwc)
|
buf, err = rec.read(w.c.rwc)
|
||||||
if err == errInvalidHeaderVersion {
|
if err == errInvalidHeaderVersion {
|
||||||
continue
|
continue
|
||||||
|
@ -441,6 +446,10 @@ func (c *FCGIClient) Request(p map[string]string, req io.Reader) (resp *http.Res
|
||||||
tp := textproto.NewReader(rb)
|
tp := textproto.NewReader(rb)
|
||||||
resp = new(http.Response)
|
resp = new(http.Response)
|
||||||
|
|
||||||
|
if err = c.setReadDeadline(); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// Parse the response headers.
|
// Parse the response headers.
|
||||||
mimeHeader, err := tp.ReadMIMEHeader()
|
mimeHeader, err := tp.ReadMIMEHeader()
|
||||||
if err != nil && err != io.EOF {
|
if err != nil && err != io.EOF {
|
||||||
|
|
|
@ -53,15 +53,13 @@ func fastcgiParse(c *caddy.Controller) ([]Rule, error) {
|
||||||
var rules []Rule
|
var rules []Rule
|
||||||
|
|
||||||
for c.Next() {
|
for c.Next() {
|
||||||
var rule Rule
|
|
||||||
|
|
||||||
args := c.RemainingArgs()
|
args := c.RemainingArgs()
|
||||||
|
|
||||||
if len(args) < 2 || len(args) > 3 {
|
if len(args) < 2 || len(args) > 3 {
|
||||||
return rules, c.ArgErr()
|
return rules, c.ArgErr()
|
||||||
}
|
}
|
||||||
|
|
||||||
rule.Path = args[0]
|
rule := Rule{Path: args[0], ReadTimeout: 60 * time.Second}
|
||||||
upstreams := []string{args[1]}
|
upstreams := []string{args[1]}
|
||||||
|
|
||||||
if len(args) == 3 {
|
if len(args) == 3 {
|
||||||
|
@ -72,7 +70,7 @@ func fastcgiParse(c *caddy.Controller) ([]Rule, error) {
|
||||||
|
|
||||||
var err error
|
var err error
|
||||||
var pool int
|
var pool int
|
||||||
var timeout time.Duration
|
var connectTimeout = 60 * time.Second
|
||||||
var dialers []dialer
|
var dialers []dialer
|
||||||
var poolSize = -1
|
var poolSize = -1
|
||||||
|
|
||||||
|
@ -133,7 +131,7 @@ func fastcgiParse(c *caddy.Controller) ([]Rule, error) {
|
||||||
if !c.NextArg() {
|
if !c.NextArg() {
|
||||||
return rules, c.ArgErr()
|
return rules, c.ArgErr()
|
||||||
}
|
}
|
||||||
timeout, err = time.ParseDuration(c.Val())
|
connectTimeout, err = time.ParseDuration(c.Val())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return rules, err
|
return rules, err
|
||||||
}
|
}
|
||||||
|
@ -152,9 +150,18 @@ func fastcgiParse(c *caddy.Controller) ([]Rule, error) {
|
||||||
for _, rawAddress := range upstreams {
|
for _, rawAddress := range upstreams {
|
||||||
network, address := parseAddress(rawAddress)
|
network, address := parseAddress(rawAddress)
|
||||||
if poolSize >= 0 {
|
if poolSize >= 0 {
|
||||||
dialers = append(dialers, &persistentDialer{size: poolSize, network: network, address: address, timeout: timeout})
|
dialers = append(dialers, &persistentDialer{
|
||||||
|
size: poolSize,
|
||||||
|
network: network,
|
||||||
|
address: address,
|
||||||
|
timeout: connectTimeout,
|
||||||
|
})
|
||||||
} else {
|
} else {
|
||||||
dialers = append(dialers, basicDialer{network: network, address: address, timeout: timeout})
|
dialers = append(dialers, basicDialer{
|
||||||
|
network: network,
|
||||||
|
address: address,
|
||||||
|
timeout: connectTimeout,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -77,8 +77,9 @@ func TestFastcgiParse(t *testing.T) {
|
||||||
Address: "127.0.0.1:9000",
|
Address: "127.0.0.1:9000",
|
||||||
Ext: ".php",
|
Ext: ".php",
|
||||||
SplitPath: ".php",
|
SplitPath: ".php",
|
||||||
dialer: &loadBalancingDialer{dialers: []dialer{basicDialer{network: "tcp", address: "127.0.0.1:9000"}}},
|
dialer: &loadBalancingDialer{dialers: []dialer{basicDialer{network: "tcp", address: "127.0.0.1:9000", timeout: 60 * time.Second}}},
|
||||||
IndexFiles: []string{"index.php"},
|
IndexFiles: []string{"index.php"},
|
||||||
|
ReadTimeout: 60 * time.Second,
|
||||||
}}},
|
}}},
|
||||||
{`fastcgi /blog 127.0.0.1:9000 php {
|
{`fastcgi /blog 127.0.0.1:9000 php {
|
||||||
upstream 127.0.0.1:9001
|
upstream 127.0.0.1:9001
|
||||||
|
@ -88,8 +89,9 @@ func TestFastcgiParse(t *testing.T) {
|
||||||
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",
|
||||||
SplitPath: ".php",
|
SplitPath: ".php",
|
||||||
dialer: &loadBalancingDialer{dialers: []dialer{basicDialer{network: "tcp", address: "127.0.0.1:9000"}, basicDialer{network: "tcp", address: "127.0.0.1:9001"}}},
|
dialer: &loadBalancingDialer{dialers: []dialer{basicDialer{network: "tcp", address: "127.0.0.1:9000", timeout: 60 * time.Second}, basicDialer{network: "tcp", address: "127.0.0.1:9001", timeout: 60 * time.Second}}},
|
||||||
IndexFiles: []string{"index.php"},
|
IndexFiles: []string{"index.php"},
|
||||||
|
ReadTimeout: 60 * time.Second,
|
||||||
}}},
|
}}},
|
||||||
{`fastcgi /blog 127.0.0.1:9000 {
|
{`fastcgi /blog 127.0.0.1:9000 {
|
||||||
upstream 127.0.0.1:9001
|
upstream 127.0.0.1:9001
|
||||||
|
@ -99,8 +101,9 @@ func TestFastcgiParse(t *testing.T) {
|
||||||
Address: "127.0.0.1:9000,127.0.0.1:9001",
|
Address: "127.0.0.1:9000,127.0.0.1:9001",
|
||||||
Ext: "",
|
Ext: "",
|
||||||
SplitPath: "",
|
SplitPath: "",
|
||||||
dialer: &loadBalancingDialer{dialers: []dialer{basicDialer{network: "tcp", address: "127.0.0.1:9000"}, basicDialer{network: "tcp", address: "127.0.0.1:9001"}}},
|
dialer: &loadBalancingDialer{dialers: []dialer{basicDialer{network: "tcp", address: "127.0.0.1:9000", timeout: 60 * time.Second}, basicDialer{network: "tcp", address: "127.0.0.1:9001", timeout: 60 * time.Second}}},
|
||||||
IndexFiles: []string{},
|
IndexFiles: []string{},
|
||||||
|
ReadTimeout: 60 * time.Second,
|
||||||
}}},
|
}}},
|
||||||
{`fastcgi / ` + defaultAddress + ` {
|
{`fastcgi / ` + defaultAddress + ` {
|
||||||
split .html
|
split .html
|
||||||
|
@ -110,8 +113,9 @@ func TestFastcgiParse(t *testing.T) {
|
||||||
Address: defaultAddress,
|
Address: defaultAddress,
|
||||||
Ext: "",
|
Ext: "",
|
||||||
SplitPath: ".html",
|
SplitPath: ".html",
|
||||||
dialer: &loadBalancingDialer{dialers: []dialer{basicDialer{network: network, address: address}}},
|
dialer: &loadBalancingDialer{dialers: []dialer{basicDialer{network: network, address: address, timeout: 60 * time.Second}}},
|
||||||
IndexFiles: []string{},
|
IndexFiles: []string{},
|
||||||
|
ReadTimeout: 60 * time.Second,
|
||||||
}}},
|
}}},
|
||||||
{`fastcgi / ` + defaultAddress + ` {
|
{`fastcgi / ` + defaultAddress + ` {
|
||||||
split .html
|
split .html
|
||||||
|
@ -122,9 +126,10 @@ func TestFastcgiParse(t *testing.T) {
|
||||||
Address: "127.0.0.1:9001",
|
Address: "127.0.0.1:9001",
|
||||||
Ext: "",
|
Ext: "",
|
||||||
SplitPath: ".html",
|
SplitPath: ".html",
|
||||||
dialer: &loadBalancingDialer{dialers: []dialer{basicDialer{network: network, address: address}}},
|
dialer: &loadBalancingDialer{dialers: []dialer{basicDialer{network: network, address: address, timeout: 60 * time.Second}}},
|
||||||
IndexFiles: []string{},
|
IndexFiles: []string{},
|
||||||
IgnoredSubPaths: []string{"/admin", "/user"},
|
IgnoredSubPaths: []string{"/admin", "/user"},
|
||||||
|
ReadTimeout: 60 * time.Second,
|
||||||
}}},
|
}}},
|
||||||
{`fastcgi / ` + defaultAddress + ` {
|
{`fastcgi / ` + defaultAddress + ` {
|
||||||
pool 0
|
pool 0
|
||||||
|
@ -134,8 +139,9 @@ func TestFastcgiParse(t *testing.T) {
|
||||||
Address: defaultAddress,
|
Address: defaultAddress,
|
||||||
Ext: "",
|
Ext: "",
|
||||||
SplitPath: "",
|
SplitPath: "",
|
||||||
dialer: &loadBalancingDialer{dialers: []dialer{&persistentDialer{size: 0, network: network, address: address}}},
|
dialer: &loadBalancingDialer{dialers: []dialer{&persistentDialer{size: 0, network: network, address: address, timeout: 60 * time.Second}}},
|
||||||
IndexFiles: []string{},
|
IndexFiles: []string{},
|
||||||
|
ReadTimeout: 60 * time.Second,
|
||||||
}}},
|
}}},
|
||||||
{`fastcgi / 127.0.0.1:8080 {
|
{`fastcgi / 127.0.0.1:8080 {
|
||||||
upstream 127.0.0.1:9000
|
upstream 127.0.0.1:9000
|
||||||
|
@ -146,8 +152,9 @@ func TestFastcgiParse(t *testing.T) {
|
||||||
Address: "127.0.0.1:8080,127.0.0.1:9000",
|
Address: "127.0.0.1:8080,127.0.0.1:9000",
|
||||||
Ext: "",
|
Ext: "",
|
||||||
SplitPath: "",
|
SplitPath: "",
|
||||||
dialer: &loadBalancingDialer{dialers: []dialer{&persistentDialer{size: 5, network: "tcp", address: "127.0.0.1:8080"}, &persistentDialer{size: 5, network: "tcp", address: "127.0.0.1:9000"}}},
|
dialer: &loadBalancingDialer{dialers: []dialer{&persistentDialer{size: 5, network: "tcp", address: "127.0.0.1:8080", timeout: 60 * time.Second}, &persistentDialer{size: 5, network: "tcp", address: "127.0.0.1:9000", timeout: 60 * time.Second}}},
|
||||||
IndexFiles: []string{},
|
IndexFiles: []string{},
|
||||||
|
ReadTimeout: 60 * time.Second,
|
||||||
}}},
|
}}},
|
||||||
{`fastcgi / ` + defaultAddress + ` {
|
{`fastcgi / ` + defaultAddress + ` {
|
||||||
split .php
|
split .php
|
||||||
|
@ -157,8 +164,9 @@ func TestFastcgiParse(t *testing.T) {
|
||||||
Address: defaultAddress,
|
Address: defaultAddress,
|
||||||
Ext: "",
|
Ext: "",
|
||||||
SplitPath: ".php",
|
SplitPath: ".php",
|
||||||
dialer: &loadBalancingDialer{dialers: []dialer{basicDialer{network: network, address: address}}},
|
dialer: &loadBalancingDialer{dialers: []dialer{basicDialer{network: network, address: address, timeout: 60 * time.Second}}},
|
||||||
IndexFiles: []string{},
|
IndexFiles: []string{},
|
||||||
|
ReadTimeout: 60 * time.Second,
|
||||||
}}},
|
}}},
|
||||||
{`fastcgi / ` + defaultAddress + ` {
|
{`fastcgi / ` + defaultAddress + ` {
|
||||||
connect_timeout 5s
|
connect_timeout 5s
|
||||||
|
@ -170,6 +178,7 @@ func TestFastcgiParse(t *testing.T) {
|
||||||
SplitPath: "",
|
SplitPath: "",
|
||||||
dialer: &loadBalancingDialer{dialers: []dialer{basicDialer{network: network, address: address, timeout: 5 * time.Second}}},
|
dialer: &loadBalancingDialer{dialers: []dialer{basicDialer{network: network, address: address, timeout: 5 * time.Second}}},
|
||||||
IndexFiles: []string{},
|
IndexFiles: []string{},
|
||||||
|
ReadTimeout: 60 * time.Second,
|
||||||
}}},
|
}}},
|
||||||
{`fastcgi / ` + defaultAddress + ` {
|
{`fastcgi / ` + defaultAddress + ` {
|
||||||
read_timeout 5s
|
read_timeout 5s
|
||||||
|
@ -179,7 +188,7 @@ func TestFastcgiParse(t *testing.T) {
|
||||||
Address: defaultAddress,
|
Address: defaultAddress,
|
||||||
Ext: "",
|
Ext: "",
|
||||||
SplitPath: "",
|
SplitPath: "",
|
||||||
dialer: &loadBalancingDialer{dialers: []dialer{basicDialer{network: network, address: address}}},
|
dialer: &loadBalancingDialer{dialers: []dialer{basicDialer{network: network, address: address, timeout: 60 * time.Second}}},
|
||||||
IndexFiles: []string{},
|
IndexFiles: []string{},
|
||||||
ReadTimeout: 5 * time.Second,
|
ReadTimeout: 5 * time.Second,
|
||||||
}}},
|
}}},
|
||||||
|
|
Loading…
Add table
Reference in a new issue