Merge branch 'master' of github.com:Araq/Nimrod
This commit is contained in:
commit
11eda851b0
3 changed files with 56 additions and 11 deletions
|
|
@ -208,6 +208,7 @@ type
|
||||||
port: TPort
|
port: TPort
|
||||||
client*: TSocket ## the socket to write the file data to
|
client*: TSocket ## the socket to write the file data to
|
||||||
path*, query*: string ## path and query the client requested
|
path*, query*: string ## path and query the client requested
|
||||||
|
headers*: PStringTable ## headers with which the client made the request
|
||||||
|
|
||||||
proc open*(s: var TServer, port = TPort(80)) =
|
proc open*(s: var TServer, port = TPort(80)) =
|
||||||
## creates a new server at port `port`. If ``port == 0`` a free port is
|
## creates a new server at port `port`. If ``port == 0`` a free port is
|
||||||
|
|
@ -224,6 +225,7 @@ proc open*(s: var TServer, port = TPort(80)) =
|
||||||
s.client = InvalidSocket
|
s.client = InvalidSocket
|
||||||
s.path = ""
|
s.path = ""
|
||||||
s.query = ""
|
s.query = ""
|
||||||
|
s.headers = {:}.newStringTable()
|
||||||
|
|
||||||
proc port*(s: var TServer): TPort =
|
proc port*(s: var TServer): TPort =
|
||||||
## get the port number the server has acquired.
|
## get the port number the server has acquired.
|
||||||
|
|
@ -232,15 +234,39 @@ proc port*(s: var TServer): TPort =
|
||||||
proc next*(s: var TServer) =
|
proc next*(s: var TServer) =
|
||||||
## proceed to the first/next request.
|
## proceed to the first/next request.
|
||||||
s.client = accept(s.socket)
|
s.client = accept(s.socket)
|
||||||
headers(s.client, "")
|
s.headers = {:}.newStringTable()
|
||||||
var data = recv(s.client).string
|
#headers(s.client, "")
|
||||||
#discard recvLine(s.client, data)
|
var data = ""
|
||||||
|
while not s.client.recvLine(data): nil
|
||||||
|
if data == "":
|
||||||
|
# Socket disconnected
|
||||||
|
s.client.close()
|
||||||
|
next(s)
|
||||||
|
return
|
||||||
|
var header = ""
|
||||||
|
while true:
|
||||||
|
if s.client.recvLine(header):
|
||||||
|
if header == "\c\L": break
|
||||||
|
if header != "":
|
||||||
|
var i = 0
|
||||||
|
var key = ""
|
||||||
|
var value = ""
|
||||||
|
i = header.parseUntil(key, ':')
|
||||||
|
i += header.skipWhiteSpace(i)
|
||||||
|
i += header.parseUntil(value, whitespace, i)
|
||||||
|
s.headers[key] = value
|
||||||
|
else:
|
||||||
|
s.client.close()
|
||||||
|
next(s)
|
||||||
|
return
|
||||||
|
|
||||||
var i = skipWhitespace(data)
|
var i = skipWhitespace(data)
|
||||||
if skipIgnoreCase(data, "GET") > 0: inc(i, 3)
|
if skipIgnoreCase(data, "GET") > 0: inc(i, 3)
|
||||||
elif skipIgnoreCase(data, "POST") > 0: inc(i, 4)
|
elif skipIgnoreCase(data, "POST") > 0: inc(i, 4)
|
||||||
else:
|
else:
|
||||||
unimplemented(s.client)
|
unimplemented(s.client)
|
||||||
|
s.client.close()
|
||||||
|
next(s)
|
||||||
return
|
return
|
||||||
|
|
||||||
var L = skipWhitespace(data, i)
|
var L = skipWhitespace(data, i)
|
||||||
|
|
|
||||||
|
|
@ -581,10 +581,19 @@ proc recv*(socket: TSocket, data: var string, size: int, timeout: int): int =
|
||||||
result = read
|
result = read
|
||||||
|
|
||||||
proc recvLine*(socket: TSocket, line: var TaintedString): bool =
|
proc recvLine*(socket: TSocket, line: var TaintedString): bool =
|
||||||
## returns false if no further data is available. `Line` must be initialized
|
## retrieves a line from ``socket``. If a full line is received ``\r\L`` is not
|
||||||
## and not nil! This does not throw an EOS exception.
|
## added to ``line``, however if solely ``\r\L`` is received then ``data``
|
||||||
## If ``socket`` is disconnected, ``true`` will be returned and line will be
|
## will be set to it.
|
||||||
## set to ``""``.
|
##
|
||||||
|
## ``True`` is returned if data is available. ``False`` usually suggests an
|
||||||
|
## error, EOS exceptions are not raised in favour of this.
|
||||||
|
##
|
||||||
|
## If the socket is disconnected, ``line`` will be set to ``""`` and ``True``
|
||||||
|
## will be returned.
|
||||||
|
template addNLIfEmpty(): stmt =
|
||||||
|
if line.len == 0:
|
||||||
|
line.add("\c\L")
|
||||||
|
|
||||||
setLen(line.string, 0)
|
setLen(line.string, 0)
|
||||||
while true:
|
while true:
|
||||||
var c: char
|
var c: char
|
||||||
|
|
@ -596,13 +605,19 @@ proc recvLine*(socket: TSocket, line: var TaintedString): bool =
|
||||||
if n > 0 and c == '\L':
|
if n > 0 and c == '\L':
|
||||||
discard recv(cint(socket), addr(c), 1, 0'i32)
|
discard recv(cint(socket), addr(c), 1, 0'i32)
|
||||||
elif n <= 0: return false
|
elif n <= 0: return false
|
||||||
|
addNlIfEmpty()
|
||||||
|
return true
|
||||||
|
elif c == '\L':
|
||||||
|
addNlIfEmpty()
|
||||||
return true
|
return true
|
||||||
elif c == '\L': return true
|
|
||||||
add(line.string, c)
|
add(line.string, c)
|
||||||
|
|
||||||
proc recvLine*(socket: TSocket, line: var TaintedString, timeout: int): bool =
|
proc recvLine*(socket: TSocket, line: var TaintedString, timeout: int): bool =
|
||||||
## variant with a ``timeout`` parameter, the timeout parameter specifies
|
## variant with a ``timeout`` parameter, the timeout parameter specifies
|
||||||
## how many miliseconds to wait for data.
|
## how many miliseconds to wait for data.
|
||||||
|
template addNLIfEmpty(): stmt =
|
||||||
|
if line.len == 0:
|
||||||
|
line.add("\c\L")
|
||||||
|
|
||||||
var waited = 0.0 # number of seconds already waited
|
var waited = 0.0 # number of seconds already waited
|
||||||
|
|
||||||
|
|
@ -619,8 +634,11 @@ proc recvLine*(socket: TSocket, line: var TaintedString, timeout: int): bool =
|
||||||
if n > 0 and c == '\L':
|
if n > 0 and c == '\L':
|
||||||
discard recv(cint(socket), addr(c), 1, 0'i32)
|
discard recv(cint(socket), addr(c), 1, 0'i32)
|
||||||
elif n <= 0: return false
|
elif n <= 0: return false
|
||||||
|
addNlIfEmpty()
|
||||||
|
return true
|
||||||
|
elif c == '\L':
|
||||||
|
addNlIfEmpty()
|
||||||
return true
|
return true
|
||||||
elif c == '\L': return true
|
|
||||||
add(line.string, c)
|
add(line.string, c)
|
||||||
|
|
||||||
proc recvLineAsync*(socket: TSocket, line: var TaintedString): TRecvLineResult =
|
proc recvLineAsync*(socket: TSocket, line: var TaintedString): TRecvLineResult =
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,8 @@ Bugfixes
|
||||||
- Fixed a bug concerning implicit type conversions in ``case`` statements.
|
- Fixed a bug concerning implicit type conversions in ``case`` statements.
|
||||||
- Fixed a serious code generation bug that caused ``algorithm.sort`` to
|
- Fixed a serious code generation bug that caused ``algorithm.sort`` to
|
||||||
produce segmentation faults.
|
produce segmentation faults.
|
||||||
|
- Fixed ambiguity in recvLine which meant that receiving ``\r\L`` was
|
||||||
|
indistinguishable from disconnections.
|
||||||
|
|
||||||
Library Additions
|
Library Additions
|
||||||
-----------------
|
-----------------
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue