1 // Copyright 2010 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
16 // A Reader implements convenience methods for reading requests
17 // or responses from a text protocol network connection.
21 buf
[]byte // a re-usable buffer for readContinuedLineSlice
24 // NewReader returns a new Reader reading from r.
26 // To avoid denial of service attacks, the provided bufio.Reader
27 // should be reading from an io.LimitReader or similar Reader to bound
28 // the size of responses.
29 func NewReader(r
*bufio
.Reader
) *Reader
{
33 // ReadLine reads a single line from r,
34 // eliding the final \n or \r\n from the returned string.
35 func (r
*Reader
) ReadLine() (string, error
) {
36 line
, err
:= r
.readLineSlice()
37 return string(line
), err
40 // ReadLineBytes is like ReadLine but returns a []byte instead of a string.
41 func (r
*Reader
) ReadLineBytes() ([]byte, error
) {
42 line
, err
:= r
.readLineSlice()
44 buf
:= make([]byte, len(line
))
51 func (r
*Reader
) readLineSlice() ([]byte, error
) {
55 l
, more
, err
:= r
.R
.ReadLine()
59 // Avoid the copy if the first call produced a full line.
60 if line
== nil && !more
{
63 line
= append(line
, l
...)
71 // ReadContinuedLine reads a possibly continued line from r,
72 // eliding the final trailing ASCII white space.
73 // Lines after the first are considered continuations if they
74 // begin with a space or tab character. In the returned data,
75 // continuation lines are separated from the previous line
76 // only by a single space: the newline and leading white space
79 // For example, consider this input:
85 // The first call to ReadContinuedLine will return "Line 1 continued..."
86 // and the second will return "Line 2".
88 // A line consisting of only white space is never continued.
90 func (r
*Reader
) ReadContinuedLine() (string, error
) {
91 line
, err
:= r
.readContinuedLineSlice()
92 return string(line
), err
95 // trim returns s with leading and trailing spaces and tabs removed.
96 // It does not assume Unicode or UTF-8.
97 func trim(s
[]byte) []byte {
99 for i
< len(s
) && (s
[i
] == ' ' || s
[i
] == '\t') {
103 for n
> i
&& (s
[n
-1] == ' ' || s
[n
-1] == '\t') {
109 // ReadContinuedLineBytes is like ReadContinuedLine but
110 // returns a []byte instead of a string.
111 func (r
*Reader
) ReadContinuedLineBytes() ([]byte, error
) {
112 line
, err
:= r
.readContinuedLineSlice()
114 buf
:= make([]byte, len(line
))
121 func (r
*Reader
) readContinuedLineSlice() ([]byte, error
) {
122 // Read the first line.
123 line
, err
:= r
.readLineSlice()
127 if len(line
) == 0 { // blank line - no continuation
131 // Optimistically assume that we have started to buffer the next line
132 // and it starts with an ASCII letter (the next header key), so we can
133 // avoid copying that buffered data around in memory and skipping over
134 // non-existent whitespace.
135 if r
.R
.Buffered() > 1 {
136 peek
, err
:= r
.R
.Peek(1)
137 if err
== nil && isASCIILetter(peek
[0]) {
138 return trim(line
), nil
142 // ReadByte or the next readLineSlice will flush the read buffer;
143 // copy the slice into buf.
144 r
.buf
= append(r
.buf
[:0], trim(line
)...)
146 // Read continuation lines.
147 for r
.skipSpace() > 0 {
148 line
, err
:= r
.readLineSlice()
152 r
.buf
= append(r
.buf
, ' ')
153 r
.buf
= append(r
.buf
, trim(line
)...)
158 // skipSpace skips R over all spaces and returns the number of bytes skipped.
159 func (r
*Reader
) skipSpace() int {
162 c
, err
:= r
.R
.ReadByte()
164 // Bufio will keep err until next read.
167 if c
!= ' ' && c
!= '\t' {
176 func (r
*Reader
) readCodeLine(expectCode
int) (code
int, continued
bool, message
string, err error
) {
177 line
, err
:= r
.ReadLine()
181 return parseCodeLine(line
, expectCode
)
184 func parseCodeLine(line
string, expectCode
int) (code
int, continued
bool, message
string, err error
) {
185 if len(line
) < 4 || line
[3] != ' ' && line
[3] != '-' {
186 err
= ProtocolError("short response: " + line
)
189 continued
= line
[3] == '-'
190 code
, err
= strconv
.Atoi(line
[0:3])
191 if err
!= nil || code
< 100 {
192 err
= ProtocolError("invalid response code: " + line
)
196 if 1 <= expectCode
&& expectCode
< 10 && code
/100 != expectCode ||
197 10 <= expectCode
&& expectCode
< 100 && code
/10 != expectCode ||
198 100 <= expectCode
&& expectCode
< 1000 && code
!= expectCode
{
199 err
= &Error
{code
, message
}
204 // ReadCodeLine reads a response code line of the form
206 // where code is a three-digit status code and the message
207 // extends to the rest of the line. An example of such a line is:
208 // 220 plan9.bell-labs.com ESMTP
210 // If the prefix of the status does not match the digits in expectCode,
211 // ReadCodeLine returns with err set to &Error{code, message}.
212 // For example, if expectCode is 31, an error will be returned if
213 // the status is not in the range [310,319].
215 // If the response is multi-line, ReadCodeLine returns an error.
217 // An expectCode <= 0 disables the check of the status code.
219 func (r
*Reader
) ReadCodeLine(expectCode
int) (code
int, message
string, err error
) {
220 code
, continued
, message
, err
:= r
.readCodeLine(expectCode
)
221 if err
== nil && continued
{
222 err
= ProtocolError("unexpected multi-line response: " + message
)
227 // ReadResponse reads a multi-line response of the form:
229 // code-message line 1
230 // code-message line 2
232 // code message line n
234 // where code is a three-digit status code. The first line starts with the
235 // code and a hyphen. The response is terminated by a line that starts
236 // with the same code followed by a space. Each line in message is
237 // separated by a newline (\n).
239 // See page 36 of RFC 959 (http://www.ietf.org/rfc/rfc959.txt) for
240 // details of another form of response accepted:
242 // code-message line 1
245 // code message line n
247 // If the prefix of the status does not match the digits in expectCode,
248 // ReadResponse returns with err set to &Error{code, message}.
249 // For example, if expectCode is 31, an error will be returned if
250 // the status is not in the range [310,319].
252 // An expectCode <= 0 disables the check of the status code.
254 func (r
*Reader
) ReadResponse(expectCode
int) (code
int, message
string, err error
) {
255 code
, continued
, message
, err
:= r
.readCodeLine(expectCode
)
258 line
, err
:= r
.ReadLine()
264 var moreMessage
string
265 code2
, continued
, moreMessage
, err
= parseCodeLine(line
, 0)
266 if err
!= nil || code2
!= code
{
267 message
+= "\n" + strings
.TrimRight(line
, "\r\n")
271 message
+= "\n" + moreMessage
273 if err
!= nil && multi
&& message
!= "" {
274 // replace one line error message with all lines (full message)
275 err
= &Error
{code
, message
}
280 // DotReader returns a new Reader that satisfies Reads using the
281 // decoded text of a dot-encoded block read from r.
282 // The returned Reader is only valid until the next call
285 // Dot encoding is a common framing used for data blocks
286 // in text protocols such as SMTP. The data consists of a sequence
287 // of lines, each of which ends in "\r\n". The sequence itself
288 // ends at a line containing just a dot: ".\r\n". Lines beginning
289 // with a dot are escaped with an additional dot to avoid
290 // looking like the end of the sequence.
292 // The decoded form returned by the Reader's Read method
293 // rewrites the "\r\n" line endings into the simpler "\n",
294 // removes leading dot escapes if present, and stops with error io.EOF
295 // after consuming (and discarding) the end-of-sequence line.
296 func (r
*Reader
) DotReader() io
.Reader
{
298 r
.dot
= &dotReader
{r
: r
}
302 type dotReader
struct {
307 // Read satisfies reads by decoding dot-encoded data read from d.r.
308 func (d
*dotReader
) Read(b
[]byte) (n
int, err error
) {
309 // Run data through a simple state machine to
310 // elide leading dots, rewrite trailing \r\n into \n,
311 // and detect ending .\r\n line.
313 stateBeginLine
= iota // beginning of line; initial state; must be zero
314 stateDot
// read . at beginning of line
315 stateDotCR
// read .\r at beginning of line
316 stateCR
// read \r (possibly at end of line)
317 stateData
// reading data in middle of line
318 stateEOF
// reached .\r\n end marker line
321 for n
< len(b
) && d
.state
!= stateEOF
{
323 c
, err
= br
.ReadByte()
326 err
= io
.ErrUnexpectedEOF
358 // Not part of .\r\n.
359 // Consume leading dot and emit saved \r.
366 d
.state
= stateBeginLine
369 // Not part of \r\n. Emit saved \r
380 d
.state
= stateBeginLine
386 if err
== nil && d
.state
== stateEOF
{
389 if err
!= nil && d
.r
.dot
== d
{
395 // closeDot drains the current DotReader if any,
396 // making sure that it reads until the ending dot line.
397 func (r
*Reader
) closeDot() {
401 buf
:= make([]byte, 128)
403 // When Read reaches EOF or an error,
404 // it will set r.dot == nil.
409 // ReadDotBytes reads a dot-encoding and returns the decoded data.
411 // See the documentation for the DotReader method for details about dot-encoding.
412 func (r
*Reader
) ReadDotBytes() ([]byte, error
) {
413 return ioutil
.ReadAll(r
.DotReader())
416 // ReadDotLines reads a dot-encoding and returns a slice
417 // containing the decoded lines, with the final \r\n or \n elided from each.
419 // See the documentation for the DotReader method for details about dot-encoding.
420 func (r
*Reader
) ReadDotLines() ([]string, error
) {
421 // We could use ReadDotBytes and then Split it,
422 // but reading a line at a time avoids needing a
423 // large contiguous block of memory and is simpler.
428 line
, err
= r
.ReadLine()
431 err
= io
.ErrUnexpectedEOF
436 // Dot by itself marks end; otherwise cut one dot.
437 if len(line
) > 0 && line
[0] == '.' {
448 // ReadMIMEHeader reads a MIME-style header from r.
449 // The header is a sequence of possibly continued Key: Value lines
450 // ending in a blank line.
451 // The returned map m maps CanonicalMIMEHeaderKey(key) to a
452 // sequence of values in the same order encountered in the input.
454 // For example, consider this input:
461 // Given that input, ReadMIMEHeader returns the map:
463 // map[string][]string{
464 // "My-Key": {"Value 1", "Value 2"},
465 // "Long-Key": {"Even Longer Value"},
468 func (r
*Reader
) ReadMIMEHeader() (MIMEHeader
, error
) {
469 // Avoid lots of small slice allocations later by allocating one
470 // large one ahead of time which we'll cut up into smaller
471 // slices. If this isn't big enough later, we allocate small ones.
473 hint
:= r
.upcomingHeaderNewlines()
475 strs
= make([]string, hint
)
478 m
:= make(MIMEHeader
, hint
)
480 kv
, err
:= r
.readContinuedLineSlice()
485 // Key ends at first colon; should not have spaces but
486 // they appear in the wild, violating specs, so we
487 // remove them if present.
488 i
:= bytes
.IndexByte(kv
, ':')
490 return m
, ProtocolError("malformed MIME header line: " + string(kv
))
493 for endKey
> 0 && kv
[endKey
-1] == ' ' {
496 key
:= canonicalMIMEHeaderKey(kv
[:endKey
])
498 // As per RFC 7230 field-name is a token, tokens consist of one or more chars.
499 // We could return a ProtocolError here, but better to be liberal in what we
500 // accept, so if we get an empty key, skip it.
505 // Skip initial spaces in value.
507 for i
< len(kv
) && (kv
[i
] == ' ' || kv
[i
] == '\t') {
510 value
:= string(kv
[i
:])
513 if vv
== nil && len(strs
) > 0 {
514 // More than likely this will be a single-element key.
515 // Most headers aren't multi-valued.
516 // Set the capacity on strs[0] to 1, so any future append
517 // won't extend the slice into the other strings.
518 vv
, strs
= strs
[:1:1], strs
[1:]
522 m
[key
] = append(vv
, value
)
531 // upcomingHeaderNewlines returns an approximation of the number of newlines
532 // that will be in this header. If it gets confused, it returns 0.
533 func (r
*Reader
) upcomingHeaderNewlines() (n
int) {
534 // Try to determine the 'hint' size.
535 r
.R
.Peek(1) // force a buffer load if empty
540 peek
, _
:= r
.R
.Peek(s
)
542 i
:= bytes
.IndexByte(peek
, '\n')
544 // Not present (-1) or found within the next few bytes,
545 // implying we're at the end ("\r\n\r\n" or "\n\n")
554 // CanonicalMIMEHeaderKey returns the canonical format of the
555 // MIME header key s. The canonicalization converts the first
556 // letter and any letter following a hyphen to upper case;
557 // the rest are converted to lowercase. For example, the
558 // canonical key for "accept-encoding" is "Accept-Encoding".
559 // MIME header keys are assumed to be ASCII only.
560 // If s contains a space or invalid header field bytes, it is
561 // returned without modifications.
562 func CanonicalMIMEHeaderKey(s
string) string {
563 // Quick check for canonical encoding.
565 for i
:= 0; i
< len(s
); i
++ {
567 if !validHeaderFieldByte(c
) {
570 if upper
&& 'a' <= c
&& c
<= 'z' {
571 return canonicalMIMEHeaderKey([]byte(s
))
573 if !upper
&& 'A' <= c
&& c
<= 'Z' {
574 return canonicalMIMEHeaderKey([]byte(s
))
581 const toLower
= 'a' - 'A'
583 // validHeaderFieldByte reports whether b is a valid byte in a header
584 // field name. RFC 7230 says:
585 // header-field = field-name ":" OWS field-value OWS
586 // field-name = token
587 // tchar = "!" / "#" / "$" / "%" / "&" / "'" / "*" / "+" / "-" / "." /
588 // "^" / "_" / "`" / "|" / "~" / DIGIT / ALPHA
590 func validHeaderFieldByte(b
byte) bool {
591 return int(b
) < len(isTokenTable
) && isTokenTable
[b
]
594 // canonicalMIMEHeaderKey is like CanonicalMIMEHeaderKey but is
595 // allowed to mutate the provided byte slice before returning the
598 // For invalid inputs (if a contains spaces or non-token bytes), a
599 // is unchanged and a string copy is returned.
600 func canonicalMIMEHeaderKey(a
[]byte) string {
601 // See if a looks like a header key. If not, return it unchanged.
602 for _
, c
:= range a
{
603 if validHeaderFieldByte(c
) {
606 // Don't canonicalize.
611 for i
, c
:= range a
{
612 // Canonicalize: first letter upper case
613 // and upper case after each dash.
614 // (Host, User-Agent, If-Modified-Since).
615 // MIME headers are ASCII only, so no Unicode issues.
616 if upper
&& 'a' <= c
&& c
<= 'z' {
618 } else if !upper
&& 'A' <= c
&& c
<= 'Z' {
622 upper
= c
== '-' // for next time
624 // The compiler recognizes m[string(byteSlice)] as a special
625 // case, so a copy of a's bytes into a new string does not
626 // happen in this map lookup:
627 if v
:= commonHeader
[string(a
)]; v
!= "" {
633 // commonHeader interns common header strings.
634 var commonHeader
= make(map[string]string)
637 for _
, v
:= range []string{
649 "Content-Transfer-Encoding",
682 // isTokenTable is a copy of net/http/lex.go's isTokenTable.
683 // See https://httpwg.github.io/specs/rfc7230.html#rule.token.separators
684 var isTokenTable
= [127]bool{