예제 #1
0
파일: http.go 프로젝트: qiaoxueshi/cow
func skipCRLF(r *bufio.Reader) error {
	// There maybe servers using single '\n' for line ending
	if _, err := r.ReadSlice('\n'); err != nil {
		errl.Println("Error reading CRLF:", err)
		return err
	}
	return nil
}
예제 #2
0
파일: http.go 프로젝트: paieer/cow
// Learned from net.textproto. One difference is that this one keeps the
// ending '\n' in the returned line. Buf if there's only CRLF in the line,
// return nil for the line.
func readContinuedLineSlice(r *bufio.Reader) ([]byte, error) {
	// feedly.com request headers contains things like:
	// "$Authorization.feedly: $FeedlyAuth\r\n", so we must test for only
	// continuation spaces.
	isspace := func(b byte) bool {
		return b == ' ' || b == '\t'
	}

	// Read the first line.
	line, err := r.ReadSlice('\n')
	if err != nil {
		return nil, err
	}

	// There are servers that use \n for line ending, so trim first before check ending.
	// For example, the 404 page for http://plan9.bell-labs.com/magic/man2html/1/2l
	trimmed := TrimSpace(line)
	if len(trimmed) == 0 {
		if len(line) > 2 {
			return nil, fmt.Errorf("malformed end of headers, len: %d, %#v", len(line), string(line))
		}
		return nil, nil
	}

	if isspace(line[0]) {
		return nil, fmt.Errorf("malformed header, start with space: %#v", string(line))
	}

	// Optimistically assume that we have started to buffer the next line
	// and it starts with an ASCII letter (the next header key), so we can
	// avoid copying that buffered data around in memory and skipping over
	// non-existent whitespace.
	if r.Buffered() > 0 {
		peek, err := r.Peek(1)
		if err == nil && !isspace(peek[0]) {
			return line, nil
		}
	}

	var buf []byte
	buf = append(buf, trimmed...)

	// Read continuation lines.
	for skipSpace(r) > 0 {
		line, err := r.ReadSlice('\n')
		if err != nil {
			break
		}
		buf = append(buf, ' ')
		buf = append(buf, TrimTrailingSpace(line)...)
	}
	buf = append(buf, '\r', '\n')
	return buf, nil
}
예제 #3
0
파일: http.go 프로젝트: qiaoxueshi/cow
// Only add headers that are of interest for a proxy into request/response's header map.
func (h *Header) parseHeader(reader *bufio.Reader, raw *bytes.Buffer, url *URL) (err error) {
	h.ContLen = -1
	dummyLastLine := []byte{}
	// Read request header and body
	var s, name, val, lastLine []byte
	for {
		if s, err = reader.ReadSlice('\n'); err != nil {
			return
		}
		// There are servers that use \n for line ending, so trim first before check ending.
		// For example, the 404 page for http://plan9.bell-labs.com/magic/man2html/1/2l
		trimmed := TrimSpace(s)
		if len(trimmed) == 0 { // end of headers
			return
		}
		if (s[0] == ' ' || s[0] == '\t') && lastLine != nil { // multi-line header
			// I've never seen multi-line header used in headers that's of interest.
			// Disable multi-line support to avoid copy for now.
			errl.Printf("Multi-line support disabled: %v %s", url, s)
			return errNotSupported
			// combine previous line with current line
			// trimmed = bytes.Join([][]byte{lastLine, []byte{' '}, trimmed}, nil)
		}
		if name, val, err = splitHeader(trimmed); err != nil {
			return
		}
		// Wait Go to solve/provide the string<->[]byte optimization
		kn := string(name)
		if parseFunc, ok := headerParser[kn]; ok {
			// lastLine = append([]byte(nil), trimmed...) // copy to avoid next read invalidating the trimmed line
			lastLine = dummyLastLine
			val = TrimSpace(val)
			if len(val) == 0 {
				continue
			}
			parseFunc(h, ASCIIToLower(val), raw)
		} else {
			// mark this header as not of interest to proxy
			lastLine = nil
		}
		if hopByHopHeader[kn] {
			continue
		}
		raw.Write(s)
		// debug.Printf("len %d %s", len(s), s)
	}
	return
}
예제 #4
0
파일: proxy.go 프로젝트: sbyinin/MEOW
// Use this function until we find Trailer headers actually in use.
func skipTrailer(r *bufio.Reader) error {
	// It's possible to get trailer headers, but the body will always end with
	// a line with just CRLF.
	for {
		s, err := r.ReadSlice('\n')
		if err != nil {
			errl.Println("skip trailer:", err)
			return err
		}
		if len(s) == 2 && s[0] == '\r' && s[1] == '\n' {
			return nil
		}
		errl.Printf("skip trailer: %#v", string(s))
		if len(s) == 1 || len(s) == 2 {
			return fmt.Errorf("malformed chunk body end: %#v", string(s))
		}
	}
}