package hw3test import ( "fmt" "net" "net/http" "strings" "time" ) // validateResponseFraming checks headers before reading the response body. func validateResponseFraming(resp *http.Response) error { // net/http removes Connection: close from Header and records it in Close. // With HTTP/1.1 and explicit framing, Close reflects that header. closeFound := resp.ProtoMajor == 1 && resp.ProtoMinor == 1 && resp.Close for _, value := range resp.Header.Values("Connection") { for _, token := range strings.Split(value, ",") { closeFound = closeFound || strings.EqualFold(strings.TrimSpace(token), "close") } } if !closeFound { return fmt.Errorf("expected Connection: close") } if len(resp.TransferEncoding) != 0 || len(resp.Header.Values("Transfer-Encoding")) != 0 { return fmt.Errorf("Transfer-Encoding is not supported") } lengths := resp.Header.Values("Content-Length") if resp.StatusCode == http.StatusNoContent { if len(lengths) != 0 { return fmt.Errorf("204 must not contain Content-Length") } } else if len(lengths) != 1 || resp.ContentLength < 0 { return fmt.Errorf("expected exactly one valid Content-Length") } return nil } // Bound a stalled peer, without imposing a total duration on large transfers. type idleDeadlineReader struct { net.Conn Timeout time.Duration } func (r *idleDeadlineReader) Read(p []byte) (int, error) { if err := r.Conn.SetReadDeadline(time.Now().Add(r.Timeout)); err != nil { return 0, err } return r.Conn.Read(p) }