Commit 32bf48c6 authored by Russ Cox's avatar Russ Cox

document http

R=r
DELTA=84  (63 added, 4 deleted, 17 changed)
OCL=25950
CL=26126
parent 5559ff6e
......@@ -4,6 +4,11 @@
// HTTP Request reading and parsing.
// The http package implements parsing of HTTP requests and URLs
// and provides an extensible HTTP server.
//
// In the future it should also implement parsing of HTTP replies
// and provide methods to fetch URLs via HTTP.
package http
import (
......@@ -20,6 +25,7 @@ const (
maxHeaderLines = 1024;
)
// HTTP request parsing errors.
var (
LineTooLong = os.NewError("http header line too long");
ValueTooLong = os.NewError("http header value too long");
......@@ -29,29 +35,67 @@ var (
BadHTTPVersion = os.NewError("unsupported http version");
)
// HTTP Request
// A Request represents a parsed HTTP request header.
type Request struct {
Method string; // GET, PUT,etc.
RawUrl string;
Url *URL; // URI after GET, PUT etc.
RawUrl string; // The raw URL given in the request.
Url *URL; // URL after GET, PUT etc.
Proto string; // "HTTP/1.0"
ProtoMajor int; // 1
ProtoMinor int; // 0
// A header mapping request lines to their values.
// If the header says
//
// Accept-Language: en-us
// accept-encoding: gzip, deflate
// Connection: keep-alive
//
// then
//
// Header = map[string]string{
// "Accept-Encoding": "en-us",
// "Accept-Language": "gzip, deflate",
// "Connection": "keep-alive"
// }
//
// HTTP defines that header names are case-insensitive.
// The request parser implements this by canonicalizing the
// name, making the first character and any characters
// following a hyphen uppercase and the rest lowercase.
Header map[string] string;
// Whether to close the connection after replying to this request.
Close bool;
// The host on which the URL is sought.
// Per RFC 2616, this is either the value of the Host: header
// or the host name given in the URL itself.
Host string;
Referer string; // referer [sic]
// The referring URL, if sent in the request.
//
// Referer is misspelled as in the request itself,
// a mistake from the earliest days of HTTP.
// This value can also be fetched from the Header map
// as Header["Referer"]; the benefit of making it
// available as a structure field is that the compiler
// can diagnose programs that use the alternate
// (correct English) spelling req.Referrer but cannot
// diagnose programs that use Header["Referrer"].
Referer string;
// The User-Agent: header string, if sent in the request.
UserAgent string;
}
// ProtoAtLeast returns whether the HTTP protocol used
// in the request is at least major.minor.
func (r *Request) ProtoAtLeast(major, minor int) bool {
return r.ProtoMajor > major ||
r.ProtoMajor == major && r.ProtoMinor >= minor
}
// Read a line of bytes (up to \n) from b.
// Give up if the line exceeds maxLineLength.
// The returned bytes are a pointer into storage in
......@@ -188,6 +232,11 @@ func parseHTTPVersion(vers string) (int, int, bool) {
var cmap = make(map[string]string)
// CanonicalHeaderKey returns the canonical format of the
// HTTP header key s. The canonicalization converts the first
// letter and any letter following a hyphen to upper case;
// the rest are converted to lowercase. For example, the
// canonical key for "accept-encoding" is "Accept-Encoding".
func CanonicalHeaderKey(s string) string {
if t, ok := cmap[s]; ok {
return t;
......@@ -216,8 +265,7 @@ func CanonicalHeaderKey(s string) string {
return t;
}
// Read and parse a request from b.
// ReadRequest reads and parses a request from b.
func ReadRequest(b *bufio.BufRead) (req *Request, err *os.Error) {
req = new(Request);
......
......@@ -2,10 +2,9 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// HTTP status codes. See RFC 2616.
package http
// HTTP status codes, defined in RFC 2616.
const (
StatusContinue = 100;
StatusSwitchingProtocols = 101;
......
......@@ -12,6 +12,7 @@ import (
"strings"
)
// Errors introduced by ParseURL.
var (
BadURL = os.NewError("bad url syntax")
)
......@@ -40,7 +41,10 @@ func unhex(c byte) byte {
return 0
}
// Unescape %xx into hex.
// URLUnescape unescapes a URL-encoded string,
// converting %AB into the byte 0xAB.
// It returns a BadURL error if each % is not followed
// by two hexadecimal digits.
func URLUnescape(s string) (string, *os.Error) {
// Count %, check that they're well-formed.
n := 0;
......@@ -76,16 +80,19 @@ func URLUnescape(s string) (string, *os.Error) {
return string(t), nil;
}
// A URL represents a parsed URL (technically, a URI reference).
// The general form represented is:
// scheme://[userinfo@]host/path[?query][#fragment]
type URL struct {
Raw string;
Scheme string;
RawPath string;
Authority string;
Userinfo string;
Host string;
Path string;
Query string;
Fragment string;
Raw string; // the original string
Scheme string; // scheme
RawPath string; // //[userinfo@]host/path[?query][#fragment]
Authority string; // [userinfo@]host
Userinfo string; // userinfo
Host string; // host
Path string; // /path
Query string; // query
Fragment string; // fragment
}
// Maybe rawurl is of the form scheme:path.
......@@ -126,7 +133,12 @@ func split(s string, c byte, cutc bool) (string, string) {
return s, ""
}
// Parse rawurl into a URL structure.
// BUG(rsc): ParseURL should canonicalize the path,
// removing unnecessary . and .. elements.
// ParseURL parses rawurl into a URL structure.
// The string rawurl is assumed not to have a #fragment suffix.
// (Web browsers strip #fragment before sending the URL to a web server.)
func ParseURL(rawurl string) (url *URL, err *os.Error) {
if rawurl == "" {
return nil, BadURL
......@@ -171,7 +183,7 @@ func ParseURL(rawurl string) (url *URL, err *os.Error) {
return url, nil
}
// A URL reference is a URL with #frag potentially added. Parse it.
// ParseURLReference is like ParseURL but allows a trailing #fragment.
func ParseURLReference(rawurlref string) (url *URL, err *os.Error) {
// Cut off #frag.
rawurl, frag := split(rawurlref, '#', true);
......
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