Commit 0cb585f9 authored by David Symonds's avatar David Symonds

Basic HTTP POST support.

R=rsc
APPROVED=rsc
DELTA=45  (37 added, 1 deleted, 7 changed)
OCL=29964
CL=29990
parent 0d2c63a0
...@@ -13,10 +13,12 @@ package http ...@@ -13,10 +13,12 @@ package http
import ( import (
"bufio"; "bufio";
"fmt";
"http"; "http";
"io"; "io";
"os"; "os";
"strings" "strconv";
"strings";
) )
const ( const (
...@@ -33,6 +35,8 @@ var ( ...@@ -33,6 +35,8 @@ var (
LineTooLong = &ProtocolError{"http header line too long"}; LineTooLong = &ProtocolError{"http header line too long"};
ValueTooLong = &ProtocolError{"http header value too long"}; ValueTooLong = &ProtocolError{"http header value too long"};
HeaderTooLong = &ProtocolError{"http header too long"}; HeaderTooLong = &ProtocolError{"http header too long"};
BadContentLength = &ProtocolError{"invalid content length"};
ShortEntityBody = &ProtocolError{"entity body too short"};
BadHeader = &ProtocolError{"malformed http header"}; BadHeader = &ProtocolError{"malformed http header"};
BadRequest = &ProtocolError{"invalid http request"}; BadRequest = &ProtocolError{"invalid http request"};
BadHTTPVersion = &ProtocolError{"unsupported http version"}; BadHTTPVersion = &ProtocolError{"unsupported http version"};
...@@ -40,9 +44,9 @@ var ( ...@@ -40,9 +44,9 @@ var (
// A Request represents a parsed HTTP request header. // A Request represents a parsed HTTP request header.
type Request struct { type Request struct {
Method string; // GET, PUT,etc. Method string; // GET, POST, PUT, etc.
RawUrl string; // The raw URL given in the request. 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" Proto string; // "HTTP/1.0"
ProtoMajor int; // 1 ProtoMajor int; // 1
ProtoMinor int; // 0 ProtoMinor int; // 0
...@@ -68,6 +72,9 @@ type Request struct { ...@@ -68,6 +72,9 @@ type Request struct {
// following a hyphen uppercase and the rest lowercase. // following a hyphen uppercase and the rest lowercase.
Header map[string] string; Header map[string] string;
// The message body.
Body io.Reader;
// Whether to close the connection after replying to this request. // Whether to close the connection after replying to this request.
Close bool; Close bool;
...@@ -386,5 +393,21 @@ func ReadRequest(b *bufio.Reader) (req *Request, err os.Error) { ...@@ -386,5 +393,21 @@ func ReadRequest(b *bufio.Reader) (req *Request, err os.Error) {
// Via // Via
// Warning // 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 ( ...@@ -14,6 +14,7 @@ import (
"log"; "log";
"net"; "net";
"os"; "os";
"strconv";
) )
...@@ -24,7 +25,7 @@ func HelloServer(c *http.Conn, req *http.Request) { ...@@ -24,7 +25,7 @@ func HelloServer(c *http.Conn, req *http.Request) {
io.WriteString(c, "hello, world!\n"); io.WriteString(c, "hello, world!\n");
} }
// simple counter server // Simple counter server. POSTing to it will set the value.
type Counter struct { type Counter struct {
n int; n int;
} }
...@@ -36,8 +37,21 @@ func (ctr *Counter) String() string { ...@@ -36,8 +37,21 @@ func (ctr *Counter) String() string {
} }
func (ctr *Counter) ServeHTTP(c *http.Conn, req *http.Request) { 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); fmt.Fprintf(c, "counter = %d\n", ctr.n);
ctr.n++;
} }
// simple file server // simple file server
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment