OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-dev/] [or1k-gcc/] [libgo/] [go/] [net/] [http/] [httputil/] [chunked.go] - Blame information for rev 747

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 747 jeremybenn
// Copyright 2009 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.
4
 
5
// The wire protocol for HTTP's "chunked" Transfer-Encoding.
6
 
7
// This code is a duplicate of ../chunked.go with these edits:
8
//      s/newChunked/NewChunked/g
9
//      s/package http/package httputil/
10
// Please make any changes in both files.
11
 
12
package httputil
13
 
14
import (
15
        "bufio"
16
        "bytes"
17
        "errors"
18
        "io"
19
        "strconv"
20
)
21
 
22
const maxLineLength = 4096 // assumed <= bufio.defaultBufSize
23
 
24
var ErrLineTooLong = errors.New("header line too long")
25
 
26
// NewChunkedReader returns a new chunkedReader that translates the data read from r
27
// out of HTTP "chunked" format before returning it.
28
// The chunkedReader returns io.EOF when the final 0-length chunk is read.
29
//
30
// NewChunkedReader is not needed by normal applications. The http package
31
// automatically decodes chunking when reading response bodies.
32
func NewChunkedReader(r io.Reader) io.Reader {
33
        br, ok := r.(*bufio.Reader)
34
        if !ok {
35
                br = bufio.NewReader(r)
36
        }
37
        return &chunkedReader{r: br}
38
}
39
 
40
type chunkedReader struct {
41
        r   *bufio.Reader
42
        n   uint64 // unread bytes in chunk
43
        err error
44
}
45
 
46
func (cr *chunkedReader) beginChunk() {
47
        // chunk-size CRLF
48
        var line string
49
        line, cr.err = readLine(cr.r)
50
        if cr.err != nil {
51
                return
52
        }
53
        cr.n, cr.err = strconv.ParseUint(line, 16, 64)
54
        if cr.err != nil {
55
                return
56
        }
57
        if cr.n == 0 {
58
                cr.err = io.EOF
59
        }
60
}
61
 
62
func (cr *chunkedReader) Read(b []uint8) (n int, err error) {
63
        if cr.err != nil {
64
                return 0, cr.err
65
        }
66
        if cr.n == 0 {
67
                cr.beginChunk()
68
                if cr.err != nil {
69
                        return 0, cr.err
70
                }
71
        }
72
        if uint64(len(b)) > cr.n {
73
                b = b[0:cr.n]
74
        }
75
        n, cr.err = cr.r.Read(b)
76
        cr.n -= uint64(n)
77
        if cr.n == 0 && cr.err == nil {
78
                // end of chunk (CRLF)
79
                b := make([]byte, 2)
80
                if _, cr.err = io.ReadFull(cr.r, b); cr.err == nil {
81
                        if b[0] != '\r' || b[1] != '\n' {
82
                                cr.err = errors.New("malformed chunked encoding")
83
                        }
84
                }
85
        }
86
        return n, cr.err
87
}
88
 
89
// Read a line of bytes (up to \n) from b.
90
// Give up if the line exceeds maxLineLength.
91
// The returned bytes are a pointer into storage in
92
// the bufio, so they are only valid until the next bufio read.
93
func readLineBytes(b *bufio.Reader) (p []byte, err error) {
94
        if p, err = b.ReadSlice('\n'); err != nil {
95
                // We always know when EOF is coming.
96
                // If the caller asked for a line, there should be a line.
97
                if err == io.EOF {
98
                        err = io.ErrUnexpectedEOF
99
                } else if err == bufio.ErrBufferFull {
100
                        err = ErrLineTooLong
101
                }
102
                return nil, err
103
        }
104
        if len(p) >= maxLineLength {
105
                return nil, ErrLineTooLong
106
        }
107
 
108
        // Chop off trailing white space.
109
        p = bytes.TrimRight(p, " \r\t\n")
110
 
111
        return p, nil
112
}
113
 
114
// readLineBytes, but convert the bytes into a string.
115
func readLine(b *bufio.Reader) (s string, err error) {
116
        p, e := readLineBytes(b)
117
        if e != nil {
118
                return "", e
119
        }
120
        return string(p), nil
121
}
122
 
123
// NewChunkedWriter returns a new chunkedWriter that translates writes into HTTP
124
// "chunked" format before writing them to w. Closing the returned chunkedWriter
125
// sends the final 0-length chunk that marks the end of the stream.
126
//
127
// NewChunkedWriter is not needed by normal applications. The http
128
// package adds chunking automatically if handlers don't set a
129
// Content-Length header. Using NewChunkedWriter inside a handler
130
// would result in double chunking or chunking with a Content-Length
131
// length, both of which are wrong.
132
func NewChunkedWriter(w io.Writer) io.WriteCloser {
133
        return &chunkedWriter{w}
134
}
135
 
136
// Writing to chunkedWriter translates to writing in HTTP chunked Transfer
137
// Encoding wire format to the underlying Wire chunkedWriter.
138
type chunkedWriter struct {
139
        Wire io.Writer
140
}
141
 
142
// Write the contents of data as one chunk to Wire.
143
// NOTE: Note that the corresponding chunk-writing procedure in Conn.Write has
144
// a bug since it does not check for success of io.WriteString
145
func (cw *chunkedWriter) Write(data []byte) (n int, err error) {
146
 
147
        // Don't send 0-length data. It looks like EOF for chunked encoding.
148
        if len(data) == 0 {
149
                return 0, nil
150
        }
151
 
152
        head := strconv.FormatInt(int64(len(data)), 16) + "\r\n"
153
 
154
        if _, err = io.WriteString(cw.Wire, head); err != nil {
155
                return 0, err
156
        }
157
        if n, err = cw.Wire.Write(data); err != nil {
158
                return
159
        }
160
        if n != len(data) {
161
                err = io.ErrShortWrite
162
                return
163
        }
164
        _, err = io.WriteString(cw.Wire, "\r\n")
165
 
166
        return
167
}
168
 
169
func (cw *chunkedWriter) Close() error {
170
        _, err := io.WriteString(cw.Wire, "0\r\n")
171
        return err
172
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.