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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-dev/] [or1k-gcc/] [libgo/] [go/] [net/] [http/] [httputil/] [dump.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
package httputil
6
 
7
import (
8
        "bufio"
9
        "bytes"
10
        "fmt"
11
        "io"
12
        "io/ioutil"
13
        "net"
14
        "net/http"
15
        "strings"
16
        "time"
17
)
18
 
19
// One of the copies, say from b to r2, could be avoided by using a more
20
// elaborate trick where the other copy is made during Request/Response.Write.
21
// This would complicate things too much, given that these functions are for
22
// debugging only.
23
func drainBody(b io.ReadCloser) (r1, r2 io.ReadCloser, err error) {
24
        var buf bytes.Buffer
25
        if _, err = buf.ReadFrom(b); err != nil {
26
                return nil, nil, err
27
        }
28
        if err = b.Close(); err != nil {
29
                return nil, nil, err
30
        }
31
        return ioutil.NopCloser(&buf), ioutil.NopCloser(bytes.NewBuffer(buf.Bytes())), nil
32
}
33
 
34
// dumpConn is a net.Conn which writes to Writer and reads from Reader
35
type dumpConn struct {
36
        io.Writer
37
        io.Reader
38
}
39
 
40
func (c *dumpConn) Close() error                       { return nil }
41
func (c *dumpConn) LocalAddr() net.Addr                { return nil }
42
func (c *dumpConn) RemoteAddr() net.Addr               { return nil }
43
func (c *dumpConn) SetDeadline(t time.Time) error      { return nil }
44
func (c *dumpConn) SetReadDeadline(t time.Time) error  { return nil }
45
func (c *dumpConn) SetWriteDeadline(t time.Time) error { return nil }
46
 
47
// DumpRequestOut is like DumpRequest but includes
48
// headers that the standard http.Transport adds,
49
// such as User-Agent.
50
func DumpRequestOut(req *http.Request, body bool) ([]byte, error) {
51
        save := req.Body
52
        if !body || req.Body == nil {
53
                req.Body = nil
54
        } else {
55
                var err error
56
                save, req.Body, err = drainBody(req.Body)
57
                if err != nil {
58
                        return nil, err
59
                }
60
        }
61
 
62
        // Use the actual Transport code to record what we would send
63
        // on the wire, but not using TCP.  Use a Transport with a
64
        // customer dialer that returns a fake net.Conn that waits
65
        // for the full input (and recording it), and then responds
66
        // with a dummy response.
67
        var buf bytes.Buffer // records the output
68
        pr, pw := io.Pipe()
69
        dr := &delegateReader{c: make(chan io.Reader)}
70
        // Wait for the request before replying with a dummy response:
71
        go func() {
72
                http.ReadRequest(bufio.NewReader(pr))
73
                dr.c <- strings.NewReader("HTTP/1.1 204 No Content\r\n\r\n")
74
        }()
75
 
76
        t := &http.Transport{
77
                Dial: func(net, addr string) (net.Conn, error) {
78
                        return &dumpConn{io.MultiWriter(pw, &buf), dr}, nil
79
                },
80
        }
81
 
82
        _, err := t.RoundTrip(req)
83
 
84
        req.Body = save
85
        if err != nil {
86
                return nil, err
87
        }
88
        return buf.Bytes(), nil
89
}
90
 
91
// delegateReader is a reader that delegates to another reader,
92
// once it arrives on a channel.
93
type delegateReader struct {
94
        c chan io.Reader
95
        r io.Reader // nil until received from c
96
}
97
 
98
func (r *delegateReader) Read(p []byte) (int, error) {
99
        if r.r == nil {
100
                r.r = <-r.c
101
        }
102
        return r.r.Read(p)
103
}
104
 
105
// Return value if nonempty, def otherwise.
106
func valueOrDefault(value, def string) string {
107
        if value != "" {
108
                return value
109
        }
110
        return def
111
}
112
 
113
var reqWriteExcludeHeaderDump = map[string]bool{
114
        "Host":              true, // not in Header map anyway
115
        "Content-Length":    true,
116
        "Transfer-Encoding": true,
117
        "Trailer":           true,
118
}
119
 
120
// dumpAsReceived writes req to w in the form as it was received, or
121
// at least as accurately as possible from the information retained in
122
// the request.
123
func dumpAsReceived(req *http.Request, w io.Writer) error {
124
        return nil
125
}
126
 
127
// DumpRequest returns the as-received wire representation of req,
128
// optionally including the request body, for debugging.
129
// DumpRequest is semantically a no-op, but in order to
130
// dump the body, it reads the body data into memory and
131
// changes req.Body to refer to the in-memory copy.
132
// The documentation for http.Request.Write details which fields
133
// of req are used.
134
func DumpRequest(req *http.Request, body bool) (dump []byte, err error) {
135
        save := req.Body
136
        if !body || req.Body == nil {
137
                req.Body = nil
138
        } else {
139
                save, req.Body, err = drainBody(req.Body)
140
                if err != nil {
141
                        return
142
                }
143
        }
144
 
145
        var b bytes.Buffer
146
 
147
        fmt.Fprintf(&b, "%s %s HTTP/%d.%d\r\n", valueOrDefault(req.Method, "GET"),
148
                req.URL.RequestURI(), req.ProtoMajor, req.ProtoMinor)
149
 
150
        host := req.Host
151
        if host == "" && req.URL != nil {
152
                host = req.URL.Host
153
        }
154
        if host != "" {
155
                fmt.Fprintf(&b, "Host: %s\r\n", host)
156
        }
157
 
158
        chunked := len(req.TransferEncoding) > 0 && req.TransferEncoding[0] == "chunked"
159
        if len(req.TransferEncoding) > 0 {
160
                fmt.Fprintf(&b, "Transfer-Encoding: %s\r\n", strings.Join(req.TransferEncoding, ","))
161
        }
162
        if req.Close {
163
                fmt.Fprintf(&b, "Connection: close\r\n")
164
        }
165
 
166
        err = req.Header.WriteSubset(&b, reqWriteExcludeHeaderDump)
167
        if err != nil {
168
                return
169
        }
170
 
171
        io.WriteString(&b, "\r\n")
172
 
173
        if req.Body != nil {
174
                var dest io.Writer = &b
175
                if chunked {
176
                        dest = NewChunkedWriter(dest)
177
                }
178
                _, err = io.Copy(dest, req.Body)
179
                if chunked {
180
                        dest.(io.Closer).Close()
181
                        io.WriteString(&b, "\r\n")
182
                }
183
        }
184
 
185
        req.Body = save
186
        if err != nil {
187
                return
188
        }
189
        dump = b.Bytes()
190
        return
191
}
192
 
193
// DumpResponse is like DumpRequest but dumps a response.
194
func DumpResponse(resp *http.Response, body bool) (dump []byte, err error) {
195
        var b bytes.Buffer
196
        save := resp.Body
197
        savecl := resp.ContentLength
198
        if !body || resp.Body == nil {
199
                resp.Body = nil
200
                resp.ContentLength = 0
201
        } else {
202
                save, resp.Body, err = drainBody(resp.Body)
203
                if err != nil {
204
                        return
205
                }
206
        }
207
        err = resp.Write(&b)
208
        resp.Body = save
209
        resp.ContentLength = savecl
210
        if err != nil {
211
                return
212
        }
213
        dump = b.Bytes()
214
        return
215
}

powered by: WebSVN 2.1.0

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