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