mirror of
https://github.com/golang/go
synced 2024-11-25 23:07:58 -07:00
Basic HTTP POST support.
R=rsc APPROVED=rsc DELTA=45 (37 added, 1 deleted, 7 changed) OCL=29964 CL=29990
This commit is contained in:
parent
0d2c63a0b9
commit
0cb585f970
@ -13,10 +13,12 @@ package http
|
||||
|
||||
import (
|
||||
"bufio";
|
||||
"fmt";
|
||||
"http";
|
||||
"io";
|
||||
"os";
|
||||
"strings"
|
||||
"strconv";
|
||||
"strings";
|
||||
)
|
||||
|
||||
const (
|
||||
@ -33,6 +35,8 @@ var (
|
||||
LineTooLong = &ProtocolError{"http header line too long"};
|
||||
ValueTooLong = &ProtocolError{"http header value too long"};
|
||||
HeaderTooLong = &ProtocolError{"http header too long"};
|
||||
BadContentLength = &ProtocolError{"invalid content length"};
|
||||
ShortEntityBody = &ProtocolError{"entity body too short"};
|
||||
BadHeader = &ProtocolError{"malformed http header"};
|
||||
BadRequest = &ProtocolError{"invalid http request"};
|
||||
BadHTTPVersion = &ProtocolError{"unsupported http version"};
|
||||
@ -40,9 +44,9 @@ var (
|
||||
|
||||
// A Request represents a parsed HTTP request header.
|
||||
type Request struct {
|
||||
Method string; // GET, PUT,etc.
|
||||
Method string; // GET, POST, PUT, etc.
|
||||
RawUrl string; // The raw URL given in the request.
|
||||
Url *URL; // URL after GET, PUT etc.
|
||||
Url *URL; // Parsed URL.
|
||||
Proto string; // "HTTP/1.0"
|
||||
ProtoMajor int; // 1
|
||||
ProtoMinor int; // 0
|
||||
@ -68,6 +72,9 @@ type Request struct {
|
||||
// following a hyphen uppercase and the rest lowercase.
|
||||
Header map[string] string;
|
||||
|
||||
// The message body.
|
||||
Body io.Reader;
|
||||
|
||||
// Whether to close the connection after replying to this request.
|
||||
Close bool;
|
||||
|
||||
@ -386,5 +393,21 @@ func ReadRequest(b *bufio.Reader) (req *Request, err os.Error) {
|
||||
// Via
|
||||
// Warning
|
||||
|
||||
return req, nil;
|
||||
// A message body exists when either Content-Length or Transfer-Encoding
|
||||
// headers are present. TODO: Handle Transfer-Encoding.
|
||||
if v, present := req.Header["Content-Length"]; present {
|
||||
length, err := strconv.Btoui64(v, 10);
|
||||
if err != nil {
|
||||
return nil, BadContentLength
|
||||
}
|
||||
// TODO: limit the Content-Length. This is an easy DoS vector.
|
||||
raw := make([]byte, length);
|
||||
n, err := b.Read(raw);
|
||||
if err != nil || uint64(n) < length {
|
||||
return nil, ShortEntityBody
|
||||
}
|
||||
req.Body = io.NewByteReader(raw);
|
||||
}
|
||||
|
||||
return req, nil
|
||||
}
|
||||
|
@ -14,6 +14,7 @@ import (
|
||||
"log";
|
||||
"net";
|
||||
"os";
|
||||
"strconv";
|
||||
)
|
||||
|
||||
|
||||
@ -24,7 +25,7 @@ func HelloServer(c *http.Conn, req *http.Request) {
|
||||
io.WriteString(c, "hello, world!\n");
|
||||
}
|
||||
|
||||
// simple counter server
|
||||
// Simple counter server. POSTing to it will set the value.
|
||||
type Counter struct {
|
||||
n int;
|
||||
}
|
||||
@ -36,8 +37,21 @@ func (ctr *Counter) String() string {
|
||||
}
|
||||
|
||||
func (ctr *Counter) ServeHTTP(c *http.Conn, req *http.Request) {
|
||||
switch req.Method {
|
||||
case "GET":
|
||||
ctr.n++;
|
||||
case "POST":
|
||||
buf := new(io.ByteBuffer);
|
||||
io.Copy(req.Body, buf);
|
||||
body := string(buf.Data());
|
||||
if n, err := strconv.Atoi(body); err != nil {
|
||||
fmt.Fprintf(c, "bad POST: %v\nbody: [%v]\n", err, body);
|
||||
} else {
|
||||
ctr.n = n;
|
||||
fmt.Fprint(c, "counter reset\n");
|
||||
}
|
||||
}
|
||||
fmt.Fprintf(c, "counter = %d\n", ctr.n);
|
||||
ctr.n++;
|
||||
}
|
||||
|
||||
// simple file server
|
||||
|
Loading…
Reference in New Issue
Block a user