func (h *hdr) Recv() ([]byte, error) {
	var contentType, contentLength string
	for {
		raw, err := h.rd.ReadString('\n')
		if err == io.EOF && raw != "" {
		} else if err != nil {
			return nil, err
		}
		if line := strings.TrimRight(raw, "\r\n"); line == "" {
			break
		} else if parts := strings.SplitN(line, ":", 2); len(parts) == 2 {
			clean := strings.TrimSpace(parts[1])
			switch strings.ToLower(parts[0]) {
			case "content-type":
				contentType = clean
			case "content-length":
				contentLength = clean
			}
		} else {
			return nil, errors.New("invalid header line")
		}
	}
	var contentErr error
	if contentType != h.mtype {
		contentErr = &ContentTypeMismatchError{Got: contentType, Want: h.mtype}
	}
	if contentLength == "" {
		return nil, errors.New("missing required content-length")
	}
	size, err := strconv.Atoi(contentLength)
	if err != nil || size < 0 {
		return nil, errors.New("invalid content-length")
	}
	data := h.rbuf
	if len(data) < size || len(data) > (1<<20) && size < len(data)/4 {
		data = make([]byte, size*2)
		h.rbuf = data
	}
	if _, err := io.ReadFull(h.rd, data[:size]); err != nil {
		return nil, err
	}
	return data[:size], contentErr
}
Recv implements part of the Channel interface. If the content type of the
received message does not match the expected value, Recv returns the decoded
message along with an error of concrete type *ContentTypeMismatchError.  The
caller may choose to ignore this error by testing explicitly for this type.
package channel
import (
	"bufio"
	"bytes"
	"errors"
	"fmt"
	"io"
	"strconv"
	"strings"
)
func StrictHeader(mimeType string) Framing {
	return func(r io.Reader, wc io.WriteCloser) Channel {
		var ctype string
		if mimeType != "" {
			ctype = "Content-Type: " + mimeType + "\r\n"
		}
		return &hdr{
			mtype: mimeType,
			ctype: ctype,
			wc:    wc,
			rd:    bufio.NewReader(r),
			buf:   bytes.NewBuffer(nil),
		}
	}
}
type ContentTypeMismatchError struct {
	Got, Want string  
}
func (c *ContentTypeMismatchError) Error() string {
	return fmt.Sprintf("content type mismatch: got %q, want %q", c.Got, c.Want)
}
type hdr struct {
	mtype string
	ctype string
	wc    io.WriteCloser
	rd    *bufio.Reader
	buf   *bytes.Buffer
	rbuf  []byte
}
func (h *hdr) Send(msg []byte) error {
	h.buf.Reset()
	if h.ctype != "" {
		h.buf.WriteString(h.ctype)
	}
	h.buf.WriteString("Content-Length: ")
	h.buf.WriteString(strconv.Itoa(len(msg)))
	h.buf.WriteString("\r\n\r\n")
	h.buf.Write(msg)
	_, err := h.wc.Write(h.buf.Next(h.buf.Len()))
	return err
}