copying fcgi code from https://github.com/NicolasPetton/fcgi
This commit is contained in:
parent
6d5b6cad00
commit
8536099e74
@ -299,6 +299,10 @@ class(#byte) ByteArray(Array)
|
|||||||
{
|
{
|
||||||
## TODO: is it ok for ByteArray to inherit from Array?
|
## TODO: is it ok for ByteArray to inherit from Array?
|
||||||
|
|
||||||
|
## method asByteString
|
||||||
|
## {
|
||||||
|
## }
|
||||||
|
|
||||||
method decodeToCharacter
|
method decodeToCharacter
|
||||||
{
|
{
|
||||||
## TODO: support other encodings. it only supports utf8 as of now.
|
## TODO: support other encodings. it only supports utf8 as of now.
|
||||||
@ -319,6 +323,10 @@ class(#byte) ByteArray(Array)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class(#byte) ByteString(Array)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
## -------------------------------------------------------------------------------
|
## -------------------------------------------------------------------------------
|
||||||
|
|
||||||
class OrderedCollection(SequenceableCollection)
|
class OrderedCollection(SequenceableCollection)
|
||||||
|
@ -11,6 +11,257 @@ class Fcgi(Object)
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class Fcgi.Header(Object)
|
||||||
|
{
|
||||||
|
var(#get,#set) version := 0.
|
||||||
|
var(#get,#set) type := 0.
|
||||||
|
var(#get,#set) requestId := 0.
|
||||||
|
var(#get,#set) contentLength := 0.
|
||||||
|
var(#get) paddingLength := 0.
|
||||||
|
var reserved := 0.
|
||||||
|
|
||||||
|
method readFrom: aStream
|
||||||
|
{
|
||||||
|
self.version := aStream uint8.
|
||||||
|
self.type := aStream uint8.
|
||||||
|
self.requestId := aStream uint16.
|
||||||
|
self.contentLength := aStream uint16.
|
||||||
|
self.paddingLength := aStream uint8.
|
||||||
|
self.reserved := aStream uint8
|
||||||
|
}
|
||||||
|
|
||||||
|
method storeOn: aStream
|
||||||
|
{
|
||||||
|
aStream uint8: version.
|
||||||
|
aStream uint8: type.
|
||||||
|
aStream uint16: requestId.
|
||||||
|
aStream uint16: self contentLength.
|
||||||
|
aStream uint8: self paddingLength.
|
||||||
|
aStream uint8: 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class Fcgi.Record(Object)
|
||||||
|
{
|
||||||
|
var(#get,#set) header.
|
||||||
|
|
||||||
|
method(#class) type: anInteger
|
||||||
|
{
|
||||||
|
^self new type: anInteger
|
||||||
|
}
|
||||||
|
|
||||||
|
method ensureHeader
|
||||||
|
{
|
||||||
|
^self.header ifNil: [self.header := Fcgi.Header new]
|
||||||
|
}
|
||||||
|
|
||||||
|
method type
|
||||||
|
{
|
||||||
|
^self.header type
|
||||||
|
}
|
||||||
|
|
||||||
|
method type: anInteger
|
||||||
|
{
|
||||||
|
self ensureHeader type: anInteger
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class Fcgi.BeginRequestRecord(Fcgi.Record)
|
||||||
|
{
|
||||||
|
var role.
|
||||||
|
var(#get) flags.
|
||||||
|
var reserved.
|
||||||
|
|
||||||
|
method readFrom: aStream
|
||||||
|
{
|
||||||
|
self.role := aStream uint16.
|
||||||
|
self.flags := aStream uint8.
|
||||||
|
self.reserved := aStream next: 5
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class Fcgi.EndRequestRecord(Fcgi.Record)
|
||||||
|
{
|
||||||
|
var(#get,#set) appStatus.
|
||||||
|
var(#get,#set) protocolStatus.
|
||||||
|
var reserved.
|
||||||
|
|
||||||
|
method readFrom: aStream
|
||||||
|
{
|
||||||
|
self.appStatus := aStream uint32.
|
||||||
|
self.protocolStatus := aStream uint8.
|
||||||
|
self.reserved := aStream next: 3
|
||||||
|
}
|
||||||
|
|
||||||
|
method storeOn: aStream
|
||||||
|
{
|
||||||
|
aStream uint32: self.appStatus.
|
||||||
|
aStream uint8: self.protocolStatus.
|
||||||
|
1 to: 3 do: [:each | aStream uint8: 0]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class Fcgi.DefaultRecord(Fcgi.Record)
|
||||||
|
{
|
||||||
|
var contentData.
|
||||||
|
var paddingData.
|
||||||
|
|
||||||
|
method content
|
||||||
|
{
|
||||||
|
^self.contentData
|
||||||
|
}
|
||||||
|
|
||||||
|
method content: aString
|
||||||
|
{
|
||||||
|
self.contentData := aString.
|
||||||
|
self ensureHeader contentLength: aString size
|
||||||
|
}
|
||||||
|
|
||||||
|
method readFrom: aStream
|
||||||
|
{
|
||||||
|
self.contentData := aStream next: header contentLength.
|
||||||
|
self.paddingData := aStream next: header paddingLength
|
||||||
|
}
|
||||||
|
|
||||||
|
method storeOn: aStream
|
||||||
|
{
|
||||||
|
aStream nextPutAll: self.contentData.
|
||||||
|
1 to: self header paddingLength do: [:each | aStream uint8: 0]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class Fcgi.ParamRecord(Fcgi.Record)
|
||||||
|
{
|
||||||
|
var namesAndValues.
|
||||||
|
var cookies.
|
||||||
|
var(#get,#set) post.
|
||||||
|
var fields.
|
||||||
|
var postFields.
|
||||||
|
var getFields.
|
||||||
|
|
||||||
|
|
||||||
|
method initialize
|
||||||
|
{
|
||||||
|
super initialize.
|
||||||
|
self.namesAndValues := OrderedCollection new
|
||||||
|
}
|
||||||
|
|
||||||
|
method at: aKey
|
||||||
|
{
|
||||||
|
^(self.namesAndValues detect: [:assoc | assoc key = aKey]) value
|
||||||
|
}
|
||||||
|
|
||||||
|
method at: aKey ifAbsent: aBlock
|
||||||
|
{
|
||||||
|
^(self.namesAndValues detect: [:assoc | assoc key = aKey] ifNone: aBlock) value
|
||||||
|
}
|
||||||
|
|
||||||
|
method at: aKey put: aValue
|
||||||
|
{
|
||||||
|
self.namesAndValues add: aKey -> aValue
|
||||||
|
}
|
||||||
|
|
||||||
|
method cookieString
|
||||||
|
{
|
||||||
|
^self at: 'HTTP_COOKIE' ifAbsent: ['']
|
||||||
|
}
|
||||||
|
|
||||||
|
method cookies
|
||||||
|
{
|
||||||
|
^self.cookies ifNil: [self.cookies := self parseToFields: self cookieString separatedBy: $;]
|
||||||
|
}
|
||||||
|
|
||||||
|
method fields
|
||||||
|
{
|
||||||
|
^self.fields ifNil: [self.fields := (Dictionary new) addAll: self postFields; addAll: self getFields; yourself]
|
||||||
|
}
|
||||||
|
|
||||||
|
method getFields
|
||||||
|
{
|
||||||
|
^getFields ifNil: [getFields := self parseToFields: self query separatedBy: $&]
|
||||||
|
}
|
||||||
|
|
||||||
|
method header
|
||||||
|
{
|
||||||
|
^self
|
||||||
|
}
|
||||||
|
|
||||||
|
method method
|
||||||
|
{
|
||||||
|
^self at: 'REQUEST_METHOD'
|
||||||
|
}
|
||||||
|
|
||||||
|
method postFields
|
||||||
|
{
|
||||||
|
^self.postFields ifNil: [
|
||||||
|
postFields := self method = 'POST'
|
||||||
|
ifTrue: [ self parseToFields: self post unescapePercents separatedBy: $&]
|
||||||
|
ifFalse: [Dictionary new]
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
method query
|
||||||
|
{
|
||||||
|
^self at: 'QUERY_STRING'
|
||||||
|
}
|
||||||
|
|
||||||
|
method url
|
||||||
|
{
|
||||||
|
^(self at: 'SCRIPT_NAME') & (self at: 'PATH_INFO')
|
||||||
|
}
|
||||||
|
|
||||||
|
method parseToFields: aString separatedBy: char
|
||||||
|
{
|
||||||
|
| equal tempFields |
|
||||||
|
|
||||||
|
tempFields := Dictionary new.
|
||||||
|
|
||||||
|
if (aString notNil)
|
||||||
|
{
|
||||||
|
(aString subStrings: %(char)) do: [:each |
|
||||||
|
equal := each indexOf: $=.
|
||||||
|
equal = 0
|
||||||
|
ifTrue: [tempFields at: each put: nil]
|
||||||
|
ifFalse: [
|
||||||
|
tempFields
|
||||||
|
at: (each first: equal - 1)
|
||||||
|
put: (each allButFirst: equal)]
|
||||||
|
]
|
||||||
|
}.
|
||||||
|
|
||||||
|
^tempFields
|
||||||
|
}
|
||||||
|
|
||||||
|
method readFrom: aStream
|
||||||
|
{
|
||||||
|
| buffer stream |
|
||||||
|
buffer := aStream next: header contentLength.
|
||||||
|
(* TODO:
|
||||||
|
stream := ReadStream on: buffer.
|
||||||
|
[stream atEnd] whileFalse: [self readNameValueFrom: stream]
|
||||||
|
*)
|
||||||
|
}
|
||||||
|
|
||||||
|
method readNameValueFrom: aStream
|
||||||
|
{
|
||||||
|
| nameLength valueLength name value |
|
||||||
|
nameLength := aStream uint8.
|
||||||
|
(nameLength bitShift: -7) = 0 ifFalse: [
|
||||||
|
nameLength := (nameLength bitShift: 24) + aStream uint24].
|
||||||
|
valueLength := aStream uint8.
|
||||||
|
(valueLength bitShift: -7) = 0 ifFalse:
|
||||||
|
[valueLength := (valueLength bitShift: 24) + aStream uint24].
|
||||||
|
name := aStream next: nameLength.
|
||||||
|
value := aStream next: valueLength.
|
||||||
|
self at: name put: value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
pooldic Fcgi.Type
|
pooldic Fcgi.Type
|
||||||
{
|
{
|
||||||
BEGIN_REQUEST := 1.
|
BEGIN_REQUEST := 1.
|
||||||
@ -163,13 +414,14 @@ class FcgiSocket(SyncSocket)
|
|||||||
## unsigned char paddingLength;
|
## unsigned char paddingLength;
|
||||||
## unsigned char reserved;
|
## unsigned char reserved;
|
||||||
## } FCGI_Header;
|
## } FCGI_Header;
|
||||||
|
(*
|
||||||
ver := self.bs next.
|
ver := self.bs next.
|
||||||
type := self.bs next.
|
type := self.bs next.
|
||||||
reqid := (self.bs next bitShift: 8) bitAnd: (self.bs next). ## can i implement nextUint16??
|
reqid := (self.bs next bitShift: 8) bitAnd: (self.bs next). ## can i implement nextUint16??
|
||||||
clen := (self.bs next bitShift: 8) bitAnd: (self.bs next).
|
clen := (self.bs next bitShift: 8) bitAnd: (self.bs next).
|
||||||
plen := self.bs next.
|
plen := self.bs next.
|
||||||
self.bs next. ## eat up the reserved byte.
|
self.bs next. ## eat up the reserved byte.
|
||||||
|
*)
|
||||||
|
|
||||||
## typedef struct {
|
## typedef struct {
|
||||||
## unsigned char roleB1;
|
## unsigned char roleB1;
|
||||||
@ -186,9 +438,10 @@ class FcgiSocket(SyncSocket)
|
|||||||
## unsigned char reserved[3];
|
## unsigned char reserved[3];
|
||||||
## } FCGI_EndRequestBody;
|
## } FCGI_EndRequestBody;
|
||||||
|
|
||||||
|
(*
|
||||||
if (type == Fcgi.Type.BEGIN_REQUEST)
|
if (type == Fcgi.Type.BEGIN_REQUEST)
|
||||||
{
|
{
|
||||||
}
|
} *)
|
||||||
|
|
||||||
(*
|
(*
|
||||||
i := 0.
|
i := 0.
|
||||||
@ -500,10 +753,14 @@ class MyObject(Object)
|
|||||||
|
|
||||||
'----- END OF ANOTHER PROC ------' dump.
|
'----- END OF ANOTHER PROC ------' dump.
|
||||||
}
|
}
|
||||||
|
|
||||||
method(#class) main
|
method(#class) main
|
||||||
{
|
{
|
||||||
| fcgi addr |
|
| fcgi addr oc |
|
||||||
|
|
||||||
|
oc := Fcgi.ParamRecord new.
|
||||||
|
(oc parseToFields: 'a=b&d=f' separatedBy: $&) dump.
|
||||||
|
thisProcess terminate.
|
||||||
|
|
||||||
(*
|
(*
|
||||||
[
|
[
|
||||||
|
Loading…
Reference in New Issue
Block a user