diff options
Diffstat (limited to 'libgo/go/http/response.go')
-rw-r--r-- | libgo/go/http/response.go | 78 |
1 files changed, 26 insertions, 52 deletions
diff --git a/libgo/go/http/response.go b/libgo/go/http/response.go index a247261..3f919c86 100644 --- a/libgo/go/http/response.go +++ b/libgo/go/http/response.go @@ -10,6 +10,7 @@ import ( "bufio" "fmt" "io" + "net/textproto" "os" "sort" "strconv" @@ -43,7 +44,7 @@ type Response struct { // omitted from Header. // // Keys in the map are canonicalized (see CanonicalHeaderKey). - Header map[string]string + Header Header // Body represents the response body. Body io.ReadCloser @@ -66,7 +67,7 @@ type Response struct { // Trailer maps trailer keys to values. Like for Header, if the // response has multiple trailer lines with the same key, they will be // concatenated, delimited by commas. - Trailer map[string]string + Trailer map[string][]string } // ReadResponse reads and returns an HTTP response from r. The RequestMethod @@ -76,13 +77,17 @@ type Response struct { // key/value pairs included in the response trailer. func ReadResponse(r *bufio.Reader, requestMethod string) (resp *Response, err os.Error) { + tp := textproto.NewReader(r) resp = new(Response) resp.RequestMethod = strings.ToUpper(requestMethod) // Parse the first line of the response. - line, err := readLine(r) + line, err := tp.ReadLine() if err != nil { + if err == os.EOF { + err = io.ErrUnexpectedEOF + } return nil, err } f := strings.Split(line, " ", 3) @@ -101,26 +106,16 @@ func ReadResponse(r *bufio.Reader, requestMethod string) (resp *Response, err os resp.Proto = f[0] var ok bool - if resp.ProtoMajor, resp.ProtoMinor, ok = parseHTTPVersion(resp.Proto); !ok { + if resp.ProtoMajor, resp.ProtoMinor, ok = ParseHTTPVersion(resp.Proto); !ok { return nil, &badStringError{"malformed HTTP version", resp.Proto} } // Parse the response headers. - nheader := 0 - resp.Header = make(map[string]string) - for { - key, value, err := readKeyValue(r) - if err != nil { - return nil, err - } - if key == "" { - break // end of response header - } - if nheader++; nheader >= maxHeaderLines { - return nil, ErrHeaderTooLong - } - resp.AddHeader(key, value) + mimeHeader, err := tp.ReadMIMEHeader() + if err != nil { + return nil, err } + resp.Header = Header(mimeHeader) fixPragmaCacheControl(resp.Header) @@ -136,34 +131,14 @@ func ReadResponse(r *bufio.Reader, requestMethod string) (resp *Response, err os // Pragma: no-cache // like // Cache-Control: no-cache -func fixPragmaCacheControl(header map[string]string) { - if header["Pragma"] == "no-cache" { +func fixPragmaCacheControl(header Header) { + if hp, ok := header["Pragma"]; ok && len(hp) > 0 && hp[0] == "no-cache" { if _, presentcc := header["Cache-Control"]; !presentcc { - header["Cache-Control"] = "no-cache" + header["Cache-Control"] = []string{"no-cache"} } } } -// AddHeader adds a value under the given key. Keys are not case sensitive. -func (r *Response) AddHeader(key, value string) { - key = CanonicalHeaderKey(key) - - oldValues, oldValuesPresent := r.Header[key] - if oldValuesPresent { - r.Header[key] = oldValues + "," + value - } else { - r.Header[key] = value - } -} - -// GetHeader returns the value of the response header with the given key. -// If there were multiple headers with this key, their values are concatenated, -// with a comma delimiter. If there were no response headers with the given -// key, GetHeader returns an empty string. Keys are not case sensitive. -func (r *Response) GetHeader(key string) (value string) { - return r.Header[CanonicalHeaderKey(key)] -} - // ProtoAtLeast returns whether the HTTP protocol used // in the response is at least major.minor. func (r *Response) ProtoAtLeast(major, minor int) bool { @@ -231,20 +206,19 @@ func (resp *Response) Write(w io.Writer) os.Error { return nil } -func writeSortedKeyValue(w io.Writer, kvm map[string]string, exclude map[string]bool) os.Error { - kva := make([]string, len(kvm)) - i := 0 - for k, v := range kvm { +func writeSortedKeyValue(w io.Writer, kvm map[string][]string, exclude map[string]bool) os.Error { + keys := make([]string, 0, len(kvm)) + for k := range kvm { if !exclude[k] { - kva[i] = fmt.Sprint(k + ": " + v + "\r\n") - i++ + keys = append(keys, k) } } - kva = kva[0:i] - sort.SortStrings(kva) - for _, l := range kva { - if _, err := io.WriteString(w, l); err != nil { - return err + sort.SortStrings(keys) + for _, k := range keys { + for _, v := range kvm[k] { + if _, err := fmt.Fprintf(w, "%s: %s\r\n", k, v); err != nil { + return err + } } } return nil |