Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in
Toggle navigation
G
golang
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Commits
Issue Boards
Open sidebar
go
golang
Commits
876e9d1b
Commit
876e9d1b
authored
Feb 10, 2011
by
Brad Fitzpatrick
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
http: add Server type supporting timeouts
R=rsc CC=golang-dev
https://golang.org/cl/4172041
parent
12bdb29b
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
107 additions
and
7 deletions
+107
-7
serve_test.go
src/pkg/http/serve_test.go
+66
-0
server.go
src/pkg/http/server.go
+41
-7
No files found.
src/pkg/http/serve_test.go
View file @
876e9d1b
...
...
@@ -9,10 +9,13 @@ package http
import
(
"bufio"
"bytes"
"fmt"
"io"
"io/ioutil"
"os"
"net"
"testing"
"time"
)
type
dummyAddr
string
...
...
@@ -283,3 +286,66 @@ func TestMuxRedirectLeadingSlashes(t *testing.T) {
}
}
}
func
TestServerTimeouts
(
t
*
testing
.
T
)
{
l
,
err
:=
net
.
ListenTCP
(
"tcp"
,
&
net
.
TCPAddr
{
Port
:
0
})
if
err
!=
nil
{
t
.
Fatalf
(
"listen error: %v"
,
err
)
}
addr
,
_
:=
l
.
Addr
()
.
(
*
net
.
TCPAddr
)
reqNum
:=
0
handler
:=
HandlerFunc
(
func
(
res
ResponseWriter
,
req
*
Request
)
{
reqNum
++
fmt
.
Fprintf
(
res
,
"req=%d"
,
reqNum
)
})
const
second
=
1000000000
/* nanos */
server
:=
&
Server
{
Handler
:
handler
,
ReadTimeout
:
0.25
*
second
,
WriteTimeout
:
0.25
*
second
}
go
server
.
Serve
(
l
)
url
:=
fmt
.
Sprintf
(
"http://localhost:%d/"
,
addr
.
Port
)
// Hit the HTTP server successfully.
r
,
_
,
err
:=
Get
(
url
)
if
err
!=
nil
{
t
.
Fatalf
(
"http Get #1: %v"
,
err
)
}
got
,
_
:=
ioutil
.
ReadAll
(
r
.
Body
)
expected
:=
"req=1"
if
string
(
got
)
!=
expected
{
t
.
Errorf
(
"Unexpected response for request #1; got %q; expected %q"
,
string
(
got
),
expected
)
}
// Slow client that should timeout.
t1
:=
time
.
Nanoseconds
()
conn
,
err
:=
net
.
Dial
(
"tcp"
,
""
,
fmt
.
Sprintf
(
"localhost:%d"
,
addr
.
Port
))
if
err
!=
nil
{
t
.
Fatalf
(
"Dial: %v"
,
err
)
}
buf
:=
make
([]
byte
,
1
)
n
,
err
:=
conn
.
Read
(
buf
)
latency
:=
time
.
Nanoseconds
()
-
t1
if
n
!=
0
||
err
!=
os
.
EOF
{
t
.
Errorf
(
"Read = %v, %v, wanted %v, %v"
,
n
,
err
,
0
,
os
.
EOF
)
}
if
latency
<
second
*
0.20
/* fudge from 0.25 above */
{
t
.
Errorf
(
"got EOF after %d ns, want >= %d"
,
latency
,
second
*
0.20
)
}
// Hit the HTTP server successfully again, verifying that the
// previous slow connection didn't run our handler. (that we
// get "req=2", not "req=3")
r
,
_
,
err
=
Get
(
url
)
if
err
!=
nil
{
t
.
Fatalf
(
"http Get #2: %v"
,
err
)
}
got
,
_
=
ioutil
.
ReadAll
(
r
.
Body
)
expected
=
"req=2"
if
string
(
got
)
!=
expected
{
t
.
Errorf
(
"Get #2 got %q, want %q"
,
string
(
got
),
expected
)
}
l
.
Close
()
}
src/pkg/http/server.go
View file @
876e9d1b
...
...
@@ -670,6 +670,39 @@ func HandleFunc(pattern string, handler func(ResponseWriter, *Request)) {
// read requests and then call handler to reply to them.
// Handler is typically nil, in which case the DefaultServeMux is used.
func
Serve
(
l
net
.
Listener
,
handler
Handler
)
os
.
Error
{
srv
:=
&
Server
{
Handler
:
handler
}
return
srv
.
Serve
(
l
)
}
// A Server defines parameters for running an HTTP server.
type
Server
struct
{
Addr
string
// TCP address to listen on, ":http" if empty
Handler
Handler
// handler to invoke, http.DefaultServeMux if nil
ReadTimeout
int64
// the net.Conn.SetReadTimeout value for new connections
WriteTimeout
int64
// the net.Conn.SetWriteTimeout value for new connections
}
// ListenAndServe listens on the TCP network address srv.Addr and then
// calls Serve to handle requests on incoming connections. If
// srv.Addr is blank, ":http" is used.
func
(
srv
*
Server
)
ListenAndServe
()
os
.
Error
{
addr
:=
srv
.
Addr
if
addr
==
""
{
addr
=
":http"
}
l
,
e
:=
net
.
Listen
(
"tcp"
,
addr
)
if
e
!=
nil
{
return
e
}
return
srv
.
Serve
(
l
)
}
// Serve accepts incoming connections on the Listener l, creating a
// new service thread for each. The service threads read requests and
// then call srv.Handler to reply to them.
func
(
srv
*
Server
)
Serve
(
l
net
.
Listener
)
os
.
Error
{
defer
l
.
Close
()
handler
:=
srv
.
Handler
if
handler
==
nil
{
handler
=
DefaultServeMux
}
...
...
@@ -678,6 +711,12 @@ func Serve(l net.Listener, handler Handler) os.Error {
if
e
!=
nil
{
return
e
}
if
srv
.
ReadTimeout
!=
0
{
rw
.
SetReadTimeout
(
srv
.
ReadTimeout
)
}
if
srv
.
WriteTimeout
!=
0
{
rw
.
SetWriteTimeout
(
srv
.
WriteTimeout
)
}
c
,
err
:=
newConn
(
rw
,
handler
)
if
err
!=
nil
{
continue
...
...
@@ -715,13 +754,8 @@ func Serve(l net.Listener, handler Handler) os.Error {
// }
// }
func
ListenAndServe
(
addr
string
,
handler
Handler
)
os
.
Error
{
l
,
e
:=
net
.
Listen
(
"tcp"
,
addr
)
if
e
!=
nil
{
return
e
}
e
=
Serve
(
l
,
handler
)
l
.
Close
()
return
e
server
:=
&
Server
{
Addr
:
addr
,
Handler
:
handler
}
return
server
.
ListenAndServe
()
}
// ListenAndServeTLS acts identically to ListenAndServe, except that it
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment