Source file
src/net/http/filetransport.go
1
2
3
4
5 package http
6
7 import (
8 "fmt"
9 "io"
10 )
11
12
13 type fileTransport struct {
14 fh fileHandler
15 }
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30 func NewFileTransport(fs FileSystem) RoundTripper {
31 return fileTransport{fileHandler{fs}}
32 }
33
34 func (t fileTransport) RoundTrip(req *Request) (resp *Response, err error) {
35
36
37
38
39
40
41 rw, resc := newPopulateResponseWriter()
42 go func() {
43 t.fh.ServeHTTP(rw, req)
44 rw.finish()
45 }()
46 return <-resc, nil
47 }
48
49 func newPopulateResponseWriter() (*populateResponse, <-chan *Response) {
50 pr, pw := io.Pipe()
51 rw := &populateResponse{
52 ch: make(chan *Response),
53 pw: pw,
54 res: &Response{
55 Proto: "HTTP/1.0",
56 ProtoMajor: 1,
57 Header: make(Header),
58 Close: true,
59 Body: pr,
60 },
61 }
62 return rw, rw.ch
63 }
64
65
66
67
68
69 type populateResponse struct {
70 res *Response
71 ch chan *Response
72 wroteHeader bool
73 hasContent bool
74 sentResponse bool
75 pw *io.PipeWriter
76 }
77
78 func (pr *populateResponse) finish() {
79 if !pr.wroteHeader {
80 pr.WriteHeader(500)
81 }
82 if !pr.sentResponse {
83 pr.sendResponse()
84 }
85 pr.pw.Close()
86 }
87
88 func (pr *populateResponse) sendResponse() {
89 if pr.sentResponse {
90 return
91 }
92 pr.sentResponse = true
93
94 if pr.hasContent {
95 pr.res.ContentLength = -1
96 }
97 pr.ch <- pr.res
98 }
99
100 func (pr *populateResponse) Header() Header {
101 return pr.res.Header
102 }
103
104 func (pr *populateResponse) WriteHeader(code int) {
105 if pr.wroteHeader {
106 return
107 }
108 pr.wroteHeader = true
109
110 pr.res.StatusCode = code
111 pr.res.Status = fmt.Sprintf("%d %s", code, StatusText(code))
112 }
113
114 func (pr *populateResponse) Write(p []byte) (n int, err error) {
115 if !pr.wroteHeader {
116 pr.WriteHeader(StatusOK)
117 }
118 pr.hasContent = true
119 if !pr.sentResponse {
120 pr.sendResponse()
121 }
122 return pr.pw.Write(p)
123 }
124
View as plain text