LEFT | RIGHT |
1 // Copyright 2009 The Go Authors. All rights reserved. | 1 // Copyright 2009 The Go Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style | 2 // Use of this source code is governed by a BSD-style |
3 // license that can be found in the LICENSE file. | 3 // license that can be found in the LICENSE file. |
4 | 4 |
5 // The wire protocol for HTTP's "chunked" Transfer-Encoding. | 5 // The wire protocol for HTTP's "chunked" Transfer-Encoding. |
6 | 6 |
7 // This code is duplicated in httputil/chunked.go. | 7 // This code is duplicated in httputil/chunked.go. |
8 // Please make any changes in both files. | 8 // Please make any changes in both files. |
9 | 9 |
10 package http | 10 package http |
11 | 11 |
12 import ( | 12 import ( |
13 "bufio" | 13 "bufio" |
14 "bytes" | |
15 "errors" | 14 "errors" |
16 "fmt" | 15 "fmt" |
17 "io" | 16 "io" |
18 ) | 17 ) |
19 | 18 |
20 const maxLineLength = 4096 // assumed <= bufio.defaultBufSize | 19 const maxLineLength = 4096 // assumed <= bufio.defaultBufSize |
21 | 20 |
22 var ErrLineTooLong = errors.New("header line too long") | 21 var ErrLineTooLong = errors.New("header line too long") |
23 | 22 |
24 // newChunkedReader returns a new chunkedReader that translates the data read fr
om r | 23 // newChunkedReader returns a new chunkedReader that translates the data read fr
om r |
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
95 if err == io.EOF { | 94 if err == io.EOF { |
96 err = io.ErrUnexpectedEOF | 95 err = io.ErrUnexpectedEOF |
97 } else if err == bufio.ErrBufferFull { | 96 } else if err == bufio.ErrBufferFull { |
98 err = ErrLineTooLong | 97 err = ErrLineTooLong |
99 } | 98 } |
100 return nil, err | 99 return nil, err |
101 } | 100 } |
102 if len(p) >= maxLineLength { | 101 if len(p) >= maxLineLength { |
103 return nil, ErrLineTooLong | 102 return nil, ErrLineTooLong |
104 } | 103 } |
| 104 return trimTrailingWhitespace(p), nil |
| 105 } |
105 | 106 |
106 » // Chop off trailing white space. | 107 func trimTrailingWhitespace(b []byte) []byte { |
107 » p = bytes.TrimRight(p, " \r\t\n") | 108 » for len(b) > 0 && isASCIISpace(b[len(b)-1]) { |
| 109 » » b = b[:len(b)-1] |
| 110 » } |
| 111 » return b |
| 112 } |
108 | 113 |
109 » return p, nil | 114 func isASCIISpace(b byte) bool { |
| 115 » return b == ' ' || b == '\t' || b == '\n' || b == '\r' |
110 } | 116 } |
111 | 117 |
112 // newChunkedWriter returns a new chunkedWriter that translates writes into HTTP | 118 // newChunkedWriter returns a new chunkedWriter that translates writes into HTTP |
113 // "chunked" format before writing them to w. Closing the returned chunkedWriter | 119 // "chunked" format before writing them to w. Closing the returned chunkedWriter |
114 // sends the final 0-length chunk that marks the end of the stream. | 120 // sends the final 0-length chunk that marks the end of the stream. |
115 // | 121 // |
116 // newChunkedWriter is not needed by normal applications. The http | 122 // newChunkedWriter is not needed by normal applications. The http |
117 // package adds chunking automatically if handlers don't set a | 123 // package adds chunking automatically if handlers don't set a |
118 // Content-Length header. Using newChunkedWriter inside a handler | 124 // Content-Length header. Using newChunkedWriter inside a handler |
119 // would result in double chunking or chunking with a Content-Length | 125 // would result in double chunking or chunking with a Content-Length |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
168 b = b - 'a' + 10 | 174 b = b - 'a' + 10 |
169 case 'A' <= b && b <= 'F': | 175 case 'A' <= b && b <= 'F': |
170 b = b - 'A' + 10 | 176 b = b - 'A' + 10 |
171 default: | 177 default: |
172 return 0, errors.New("invalid byte in chunk length") | 178 return 0, errors.New("invalid byte in chunk length") |
173 } | 179 } |
174 n |= uint64(b) | 180 n |= uint64(b) |
175 } | 181 } |
176 return | 182 return |
177 } | 183 } |
LEFT | RIGHT |