@@ -5,33 +5,32 @@ import (
5
5
"bufio"
6
6
"encoding/binary"
7
7
"fmt"
8
- "http"
9
8
"io"
10
9
"log"
11
10
"net"
12
11
"os"
13
12
)
14
13
15
14
const (
16
- FcgiBeginRequest = iota + 1
17
- FcgiAbortRequest
18
- FcgiEndRequest
19
- FcgiParams
20
- FcgiStdin
21
- FcgiStdout
22
- FcgiStderr
23
- FcgiData
24
- FcgiGetValues
25
- FcgiGetValuesResult
26
- FcgiUnknownType
27
- FcgiMaxType = FcgiUnknownType
15
+ fcgiBeginRequest = iota + 1
16
+ fcgiAbortRequest
17
+ fcgiEndRequest
18
+ fcgiParams
19
+ fcgiStdin
20
+ fcgiStdout
21
+ fcgiStderr
22
+ fcgiData
23
+ fcgiGetValues
24
+ fcgiGetValuesResult
25
+ fcgiUnknownType
26
+ fcgiMaxType = fcgiUnknownType
28
27
)
29
28
30
29
const (
31
- FcgiRequestComplete = iota
32
- FcgiCantMpxConn
33
- FcgiOverloaded
34
- FcgiUnknownRole
30
+ fcgiRequestComplete = iota
31
+ fcgiCantMpxConn
32
+ fcgiOverloaded
33
+ fcgiUnknownRole
35
34
)
36
35
37
36
type fcgiHeader struct {
@@ -76,13 +75,13 @@ func newFcgiRecord(typ int, requestId int, data []byte) []byte {
76
75
return record .Bytes ()
77
76
}
78
77
79
- type fcgiEndRequest struct {
78
+ type fcgiEndReq struct {
80
79
appStatus uint32
81
80
protocolStatus uint8
82
81
reserved [3 ]uint8
83
82
}
84
83
85
- func (er fcgiEndRequest ) bytes () []byte {
84
+ func (er fcgiEndReq ) bytes () []byte {
86
85
buf := make ([]byte , 8 )
87
86
binary .BigEndian .PutUint32 (buf , er .appStatus )
88
87
buf [4 ] = er .protocolStatus
@@ -92,7 +91,7 @@ func (er fcgiEndRequest) bytes() []byte {
92
91
type fcgiConn struct {
93
92
requestId uint16
94
93
fd io.ReadWriteCloser
95
- headers map [string ]string
94
+ headers map [string ][] string
96
95
wroteHeaders bool
97
96
}
98
97
@@ -102,7 +101,7 @@ func (conn *fcgiConn) fcgiWrite(data []byte) (err os.Error) {
102
101
padding := make ([]byte , uint8 (- l & 7 ))
103
102
hdr := fcgiHeader {
104
103
Version : 1 ,
105
- Type : FcgiStdout ,
104
+ Type : fcgiStdout ,
106
105
RequestId : conn .requestId ,
107
106
ContentLength : uint16 (l ),
108
107
PaddingLength : uint8 (len (padding )),
@@ -134,7 +133,9 @@ func (conn *fcgiConn) Write(data []byte) (n int, err os.Error) {
134
133
if ! conn .wroteHeaders {
135
134
conn .wroteHeaders = true
136
135
for k , v := range conn .headers {
137
- buf .WriteString (k + ": " + v + "\r \n " )
136
+ for _ , i := range v {
137
+ buf .WriteString (k + ": " + i + "\r \n " )
138
+ }
138
139
}
139
140
buf .WriteString ("\r \n " )
140
141
conn .fcgiWrite (buf .Bytes ())
@@ -162,17 +163,30 @@ func (conn *fcgiConn) StartResponse(status int) {
162
163
conn .fcgiWrite (buf .Bytes ())
163
164
}
164
165
165
- func (conn * fcgiConn ) SetHeader (hdr string , val string ) {
166
- conn .headers [hdr ] = val
166
+ func (conn * fcgiConn ) SetHeader (hdr string , val string , unique bool ) {
167
+ if _ , contains := conn .headers [hdr ]; ! contains {
168
+ conn .headers [hdr ] = []string {val }
169
+ return
170
+ }
171
+
172
+ if unique {
173
+ //just overwrite the first value
174
+ conn .headers [hdr ][0 ] = val
175
+ } else {
176
+ newHeaders := make ([]string , len (conn .headers )+ 1 )
177
+ copy (newHeaders , conn .headers [hdr ])
178
+ newHeaders [len (newHeaders )- 1 ] = val
179
+ conn .headers [hdr ] = newHeaders
180
+ }
167
181
}
168
182
169
183
func (conn * fcgiConn ) complete () {
170
- content := fcgiEndRequest {appStatus : 200 , protocolStatus : FcgiRequestComplete }.bytes ()
184
+ content := fcgiEndReq {appStatus : 200 , protocolStatus : fcgiRequestComplete }.bytes ()
171
185
l := len (content )
172
186
173
187
hdr := fcgiHeader {
174
188
Version : 1 ,
175
- Type : FcgiEndRequest ,
189
+ Type : fcgiEndRequest ,
176
190
RequestId : uint16 (conn .requestId ),
177
191
ContentLength : uint16 (l ),
178
192
PaddingLength : 0 ,
@@ -218,46 +232,13 @@ func readFcgiParams(data []byte, storage map[string]string) {
218
232
}
219
233
}
220
234
221
- func buildRequest (headers map [string ]string ) * Request {
222
- method , _ := headers ["REQUEST_METHOD" ]
223
- host , _ := headers ["HTTP_HOST" ]
224
- path , _ := headers ["REQUEST_URI" ]
225
- port , _ := headers ["SERVER_PORT" ]
226
- proto , _ := headers ["SERVER_PROTOCOL" ]
227
- rawurl := "http://" + host + ":" + port + path
228
-
229
- url , _ := http .ParseURL (rawurl )
230
- useragent , _ := headers ["USER_AGENT" ]
231
-
232
- httpheader := map [string ]string {}
233
- if method == "POST" {
234
- if ctype , ok := headers ["CONTENT_TYPE" ]; ok {
235
- httpheader ["Content-Type" ] = ctype
236
- }
237
-
238
- if clength , ok := headers ["CONTENT_LENGTH" ]; ok {
239
- httpheader ["Content-Length" ] = clength
240
- }
241
- }
242
-
243
- req := Request {Method : method ,
244
- RawURL : rawurl ,
245
- URL : url ,
246
- Proto : proto ,
247
- Host : host ,
248
- UserAgent : useragent ,
249
- Header : httpheader ,
250
- }
251
-
252
- return & req
253
- }
254
-
255
235
func handleFcgiConnection (fd io.ReadWriteCloser ) {
256
236
br := bufio .NewReader (fd )
257
237
var req * Request
258
238
var fc * fcgiConn
259
239
var body bytes.Buffer
260
240
headers := map [string ]string {}
241
+
261
242
for {
262
243
var h fcgiHeader
263
244
err := binary .Read (br , binary .BigEndian , & h )
@@ -278,32 +259,26 @@ func handleFcgiConnection(fd io.ReadWriteCloser) {
278
259
}
279
260
280
261
switch h .Type {
281
- case FcgiBeginRequest :
282
- fc = & fcgiConn {h .RequestId , fd , make (map [string ]string ), false }
262
+ case fcgiBeginRequest :
263
+ fc = & fcgiConn {h .RequestId , fd , make (map [string ][] string ), false }
283
264
284
- case FcgiParams :
265
+ case fcgiParams :
285
266
if h .ContentLength > 0 {
286
267
readFcgiParams (content , headers )
287
- } else if h .ContentLength == 0 {
288
- req = buildRequest (headers )
289
268
}
290
- case FcgiStdin :
269
+ case fcgiStdin :
291
270
if h .ContentLength > 0 {
292
271
body .Write (content )
293
272
} else if h .ContentLength == 0 {
294
- if req == nil {
295
- log .Stderrf ("Invalid fcgi request params\n " )
296
- return
297
- }
298
- req .Body = & body
273
+ req = newRequestCgi (headers , & body )
299
274
routeHandler (req , fc )
300
275
fc .complete ()
301
276
}
302
- case FcgiData :
277
+ case fcgiData :
303
278
if h .ContentLength > 0 {
304
279
body .Write (content )
305
280
}
306
- case FcgiAbortRequest :
281
+ case fcgiAbortRequest :
307
282
}
308
283
}
309
284
}
0 commit comments