aboutsummaryrefslogtreecommitdiff
path: root/src/lib
diff options
context:
space:
mode:
authorRuss Cox <rsc@golang.org>2009-03-11 12:45:53 -0700
committerRuss Cox <rsc@golang.org>2009-03-11 12:45:53 -0700
commit32bf48c6d8f5d8cdb163dc366fa2f8335c7e39d2 (patch)
tree28ada58f1daa77ed474758901de39ef20a5fcc4d /src/lib
parent5559ff6ece381c8ee1b27779708bc821f609eafb (diff)
downloadgo-32bf48c6d8f5d8cdb163dc366fa2f8335c7e39d2.tar.xz
document http
R=r DELTA=84 (63 added, 4 deleted, 17 changed) OCL=25950 CL=26126
Diffstat (limited to 'src/lib')
-rw-r--r--src/lib/http/request.go62
-rw-r--r--src/lib/http/status.go3
-rw-r--r--src/lib/http/url.go36
3 files changed, 80 insertions, 21 deletions
diff --git a/src/lib/http/request.go b/src/lib/http/request.go
index 5d1fd67d72..a2720ff01b 100644
--- a/src/lib/http/request.go
+++ b/src/lib/http/request.go
@@ -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);
diff --git a/src/lib/http/status.go b/src/lib/http/status.go
index 82a8b214c4..6d1c5ab28a 100644
--- a/src/lib/http/status.go
+++ b/src/lib/http/status.go
@@ -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;
diff --git a/src/lib/http/url.go b/src/lib/http/url.go
index f0a94d68bc..0b2e9783ad 100644
--- a/src/lib/http/url.go
+++ b/src/lib/http/url.go
@@ -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);