@@ -4,10 +4,13 @@ import (
4
4
"bufio"
5
5
"bytes"
6
6
"encoding/binary"
7
+ "errors"
7
8
"fmt"
8
9
"io"
10
+ "io/ioutil"
9
11
"net"
10
12
"net/http"
13
+ "net/http/cgi"
11
14
"strings"
12
15
)
13
16
@@ -90,6 +93,7 @@ func (er fcgiEndReq) bytes() []byte {
90
93
91
94
type fcgiConn struct {
92
95
requestId uint16
96
+ req * http.Request
93
97
fd io.ReadWriteCloser
94
98
headers http.Header
95
99
wroteHeaders bool
@@ -129,51 +133,43 @@ func (conn *fcgiConn) fcgiWrite(data []byte) (err error) {
129
133
}
130
134
131
135
func (conn * fcgiConn ) Write (data []byte ) (n int , err error ) {
132
- var buf bytes.Buffer
133
136
if ! conn .wroteHeaders {
134
- conn .wroteHeaders = true
135
- for k , v := range conn .headers {
136
- for _ , i := range v {
137
- buf .WriteString (k + ": " + i + "\r \n " )
138
- }
139
- }
140
- buf .WriteString ("\r \n " )
141
- conn .fcgiWrite (buf .Bytes ())
137
+ conn .WriteHeader (200 )
142
138
}
143
139
140
+ if conn .req .Method == "HEAD" {
141
+ return 0 , errors .New ("Body Not Allowed" )
142
+ }
144
143
err = conn .fcgiWrite (data )
145
-
146
144
if err != nil {
147
145
return 0 , err
148
146
}
149
147
150
148
return len (data ), nil
151
149
}
152
150
153
- func (conn * fcgiConn ) StartResponse (status int ) {
154
- var buf bytes.Buffer
155
- text := statusText [status ]
156
- fmt .Fprintf (& buf , "HTTP/1.1 %d %s\r \n " , status , text )
157
- conn .fcgiWrite (buf .Bytes ())
158
- }
151
+ func (conn * fcgiConn ) WriteHeader (status int ) {
152
+ if ! conn .wroteHeaders {
153
+ conn .wroteHeaders = true
159
154
160
- func (conn * fcgiConn ) SetHeader (hdr string , val string , unique bool ) {
161
- if _ , contains := conn .headers [hdr ]; ! contains {
162
- conn .headers [hdr ] = []string {val }
163
- return
164
- }
155
+ var buf bytes.Buffer
156
+ text := statusText [status ]
157
+ fmt .Fprintf (& buf , "HTTP/1.1 %d %s\r \n " , status , text )
165
158
166
- if unique {
167
- //just overwrite the first value
168
- conn .headers [hdr ][0 ] = val
169
- } else {
170
- newHeaders := make ([]string , len (conn .headers )+ 1 )
171
- copy (newHeaders , conn .headers [hdr ])
172
- newHeaders [len (newHeaders )- 1 ] = val
173
- conn .headers [hdr ] = newHeaders
159
+ for k , v := range conn .headers {
160
+ for _ , i := range v {
161
+ buf .WriteString (k + ": " + i + "\r \n " )
162
+ }
163
+ }
164
+ buf .WriteString ("\r \n " )
165
+ conn .fcgiWrite (buf .Bytes ())
174
166
}
175
167
}
176
168
169
+ func (conn * fcgiConn ) Header () http.Header {
170
+ return conn .headers
171
+ }
172
+
177
173
func (conn * fcgiConn ) complete () {
178
174
content := fcgiEndReq {appStatus : 200 , protocolStatus : fcgiRequestComplete }.bytes ()
179
175
l := len (content )
@@ -213,7 +209,7 @@ func readFcgiParamSize(data []byte, index int) (int, int) {
213
209
}
214
210
215
211
//read the fcgi parameters contained in data, and store them in storage
216
- func readFcgiParams (data []byte , storage http. Header ) {
212
+ func readFcgiParams (data []byte , storage map [ string ] string ) {
217
213
for idx := 0 ; len (data ) > idx ; {
218
214
keySize , shift := readFcgiParamSize (data , idx )
219
215
idx += shift
@@ -223,16 +219,16 @@ func readFcgiParams(data []byte, storage http.Header) {
223
219
idx += keySize
224
220
val := data [idx : idx + valSize ]
225
221
idx += valSize
226
- storage . Set ( string (key ), string (val ) )
222
+ storage [ string (key )] = string (val )
227
223
}
228
224
}
229
225
230
226
func (s * Server ) handleFcgiConnection (fd io.ReadWriteCloser ) {
231
227
br := bufio .NewReader (fd )
232
- var req * Request
228
+ var req * http. Request
233
229
var fc * fcgiConn
234
230
var body bytes.Buffer
235
- headers := make (http. Header )
231
+ headers := map [ string ] string {}
236
232
237
233
for {
238
234
var h fcgiHeader
@@ -247,8 +243,8 @@ func (s *Server) handleFcgiConnection(fd io.ReadWriteCloser) {
247
243
content := make ([]byte , h .ContentLength )
248
244
_ , err = io .ReadFull (br , content )
249
245
if err != nil {
250
- s .Logger .Println ("FCGI Error" , err .Error ())
251
- break
246
+ s .Logger .Println ("FCGI Error" , err .Error ())
247
+ break
252
248
}
253
249
254
250
//read padding
@@ -263,7 +259,7 @@ func (s *Server) handleFcgiConnection(fd io.ReadWriteCloser) {
263
259
264
260
switch h .Type {
265
261
case fcgiBeginRequest :
266
- fc = & fcgiConn {h .RequestId , fd , make (map [string ][]string ), false }
262
+ fc = & fcgiConn {h .RequestId , req , fd , make (map [string ][]string ), false }
267
263
268
264
case fcgiParams :
269
265
if h .ContentLength > 0 {
@@ -273,7 +269,10 @@ func (s *Server) handleFcgiConnection(fd io.ReadWriteCloser) {
273
269
if h .ContentLength > 0 {
274
270
body .Write (content )
275
271
} else if h .ContentLength == 0 {
276
- req = newRequestCgi (headers , & body )
272
+
273
+ req , _ = cgi .RequestFromMap (headers )
274
+ req .Body = ioutil .NopCloser (& body )
275
+ fc .req = req
277
276
s .routeHandler (req , fc )
278
277
//we close the connection after processing
279
278
//TODO: is there a way to keep it open for future requests?
0 commit comments