func trimWSRight(p []byte) []byte { var i int for i = len(p); i > 0; i-- { if !web.IsSpaceByte(p[i-1]) { break } } return p[0:i] }
func parseHeader(b *bufio.Reader) (header web.StringsMap, err os.Error) { const ( // Max size for header line maxLineSize = 4096 // Max size for header value maxValueSize = 4096 // Maximum number of headers maxHeaderCount = 256 ) header = make(web.StringsMap) lastKey := "" headerCount := 0 for { p, err := b.ReadSlice('\n') if err != nil { if err == bufio.ErrBufferFull { err = ErrLineTooLong } else if err == os.EOF { err = io.ErrUnexpectedEOF } return nil, err } // remove line terminator if len(p) >= 2 && p[len(p)-2] == '\r' { // \r\n p = p[0 : len(p)-2] } else { // \n p = p[0 : len(p)-1] } // End of headers? if len(p) == 0 { break } // Don't allow huge header lines. if len(p) > maxLineSize { return nil, ErrLineTooLong } if web.IsSpaceByte(p[0]) { if lastKey == "" { return nil, ErrBadHeaderLine } p = trimWSLeft(trimWSRight(p)) if len(p) > 0 { values := header[lastKey] value := values[len(values)-1] value = value + " " + string(p) if len(value) > maxValueSize { return nil, ErrHeaderTooLong } values[len(values)-1] = value } } else { // New header headerCount = headerCount + 1 if headerCount > maxHeaderCount { return nil, ErrHeadersTooLong } // Key i := skipBytes(p, web.IsTokenByte) if i < 1 { return nil, ErrBadHeaderLine } key := web.HeaderNameBytes(p[0:i]) p = p[i:] lastKey = key p = trimWSLeft(p) // Colon if p[0] != ':' { return nil, ErrBadHeaderLine } p = p[1:] // Value p = trimWSLeft(p) value := string(trimWSRight(p)) header.Append(key, value) } } return header, nil }