mirror of
https://github.com/nim-lang/Nim.git
synced 2025-12-28 17:04:41 +00:00
httpserver may work better now
This commit is contained in:
@@ -55,7 +55,7 @@ proc rawCompile(pattern: string, flags: cint): PPcre =
|
||||
return com
|
||||
|
||||
proc finalizeRegEx(x: TRegEx) =
|
||||
# XXX This is a hack, but PCRE does not export it's "free" function properly.
|
||||
# XXX This is a hack, but PCRE does not export its "free" function properly.
|
||||
# Sigh. The hack relies on PCRE's implementation (see ``pcre_get.c``).
|
||||
# Fortunately the implementation is unlikely to change.
|
||||
pcre.free_substring(cast[cstring](x.h))
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
## run(handleRequest, TPort(80))
|
||||
##
|
||||
|
||||
import strutils, os, osproc, strtabs, streams, sockets
|
||||
import parseutils, strutils, os, osproc, strtabs, streams, sockets
|
||||
|
||||
const
|
||||
wwwNL* = "\r\L"
|
||||
@@ -76,9 +76,9 @@ proc unimplemented(client: TSocket) =
|
||||
|
||||
proc discardHeaders(client: TSocket) = skip(client)
|
||||
|
||||
proc serveFile(client: TSocket, filename: string) =
|
||||
discardHeaders(client)
|
||||
|
||||
proc serveFile*(client: TSocket, filename: string) =
|
||||
## serves a file to the client.
|
||||
when false: discardHeaders(client)
|
||||
var f: TFile
|
||||
if open(f, filename):
|
||||
headers(client, filename)
|
||||
@@ -231,19 +231,33 @@ proc next*(s: var TServer) =
|
||||
## proceed to the first/next request.
|
||||
s.client = accept(s.socket)
|
||||
headers(s.client, "")
|
||||
var buf = ""
|
||||
discard recvLine(s.client, buf)
|
||||
var data = buf.split()
|
||||
if cmpIgnoreCase(data[0], "GET") == 0 or cmpIgnoreCase(data[0], "POST") == 0:
|
||||
var q = find(data[1], '?')
|
||||
if q >= 0:
|
||||
s.query = data[1].copy(q+1)
|
||||
s.path = data[1].copy(0, q-1)
|
||||
else:
|
||||
s.query = ""
|
||||
s.path = data[1]
|
||||
else:
|
||||
var data = recv(s.client)
|
||||
#discard recvLine(s.client, data)
|
||||
|
||||
var i = 0
|
||||
if skipIgnoreCase(data, "GET") > 0: i = 3
|
||||
elif skipIgnoreCase(data, "POST") > 0: i = 4
|
||||
elif data.len == 0:
|
||||
# Google Chrome sends an empty line first? the web is ugly ...
|
||||
nil
|
||||
else:
|
||||
unimplemented(s.client)
|
||||
return
|
||||
|
||||
var L = skipWhitespace(data, i)
|
||||
inc(i, L)
|
||||
# XXX we ignore "HTTP/1.1" etc. for now here
|
||||
var query = 0
|
||||
var last = i
|
||||
while last < data.len and data[last] notin whitespace:
|
||||
if data[last] == '?' and query == 0: query = last
|
||||
inc(last)
|
||||
if query > 0:
|
||||
s.query = data.copy(query+1, last-1)
|
||||
s.path = data.copy(i, query-1)
|
||||
else:
|
||||
s.query = ""
|
||||
s.path = data.copy(i, last-1)
|
||||
|
||||
proc close*(s: TServer) =
|
||||
## closes the server (and the socket the server uses).
|
||||
@@ -254,7 +268,7 @@ proc run*(handleRequest: proc (client: TSocket, path, query: string): bool,
|
||||
## encapsulates the server object and main loop
|
||||
var s: TServer
|
||||
open(s, port)
|
||||
#echo("httpserver running on port ", s.port)
|
||||
echo("httpserver running on port ", s.port)
|
||||
while true:
|
||||
next(s)
|
||||
if handleRequest(s.client, s.path, s.query): break
|
||||
@@ -265,8 +279,9 @@ when isMainModule:
|
||||
var counter = 0
|
||||
proc handleRequest(client: TSocket, path, query: string): bool {.procvar.} =
|
||||
inc(counter)
|
||||
client.send("Hello, Andreas, for the $#th time." % $counter & wwwNL)
|
||||
client.send("Hello, Andreas, for the $#th time. $# ? $#" % [
|
||||
$counter, path, query] & wwwNL)
|
||||
return false # do not stop processing
|
||||
|
||||
run(handleRequest, TPort(80))
|
||||
run(handleRequest, TPort(0))
|
||||
|
||||
|
||||
@@ -935,60 +935,60 @@ proc editDistance*(a, b: string): int {.noSideEffect,
|
||||
row[p] = x
|
||||
result = row[e]
|
||||
#dealloc(row)
|
||||
|
||||
|
||||
# floating point formating:
|
||||
|
||||
proc c_sprintf(buf, frmt: CString) {.nodecl, importc: "sprintf", varargs,
|
||||
noSideEffect.}
|
||||
|
||||
type
|
||||
TFloatFormat* = enum
|
||||
ffDefault, ## use the shorter floating point notation
|
||||
ffDecimal, ## use decimal floating point notation
|
||||
ffScientific ## use scientific notation (using ``e``) character
|
||||
|
||||
proc formatBiggestFloat*(f: BiggestFloat, format: TFloatFormat = ffDefault,
|
||||
|
||||
|
||||
# floating point formating:
|
||||
|
||||
proc c_sprintf(buf, frmt: CString) {.nodecl, importc: "sprintf", varargs,
|
||||
noSideEffect.}
|
||||
|
||||
type
|
||||
TFloatFormat* = enum
|
||||
ffDefault, ## use the shorter floating point notation
|
||||
ffDecimal, ## use decimal floating point notation
|
||||
ffScientific ## use scientific notation (using ``e``) character
|
||||
|
||||
proc formatBiggestFloat*(f: BiggestFloat, format: TFloatFormat = ffDefault,
|
||||
precision = 16): string {.noSideEffect,
|
||||
rtl, extern: "nsu$1".} =
|
||||
## converts a floating point value `f` to a string.
|
||||
##
|
||||
## If ``format == ffDecimal`` then precision is the number of digits to
|
||||
## be printed after the decimal point.
|
||||
## If ``format == ffScientific`` then precision is the maximum number
|
||||
## of significant digits to be printed.
|
||||
## `precision`'s default value is the maximum number of meaningful digits
|
||||
## after the decimal point for Nimrod's ``biggestFloat`` type.
|
||||
const floatFormatToChar: array[TFloatFormat, char] = ['g', 'f', 'e']
|
||||
var
|
||||
frmtstr: array[0..5, char]
|
||||
buf: array[0..80, char]
|
||||
frmtstr[0] = '%'
|
||||
frmtstr[1] = '#'
|
||||
if precision > 0:
|
||||
frmtstr[2] = '.'
|
||||
frmtstr[3] = '*'
|
||||
frmtstr[4] = floatFormatToChar[format]
|
||||
frmtstr[5] = '\0'
|
||||
c_sprintf(buf, frmtstr, precision, f)
|
||||
else:
|
||||
frmtstr[2] = floatFormatToChar[format]
|
||||
frmtstr[3] = '\0'
|
||||
c_sprintf(buf, frmtstr, f)
|
||||
result = $buf
|
||||
|
||||
proc formatFloat*(f: float, format: TFloatFormat = ffDefault,
|
||||
rtl, extern: "nsu$1".} =
|
||||
## converts a floating point value `f` to a string.
|
||||
##
|
||||
## If ``format == ffDecimal`` then precision is the number of digits to
|
||||
## be printed after the decimal point.
|
||||
## If ``format == ffScientific`` then precision is the maximum number
|
||||
## of significant digits to be printed.
|
||||
## `precision`'s default value is the maximum number of meaningful digits
|
||||
## after the decimal point for Nimrod's ``biggestFloat`` type.
|
||||
const floatFormatToChar: array[TFloatFormat, char] = ['g', 'f', 'e']
|
||||
var
|
||||
frmtstr: array[0..5, char]
|
||||
buf: array[0..80, char]
|
||||
frmtstr[0] = '%'
|
||||
frmtstr[1] = '#'
|
||||
if precision > 0:
|
||||
frmtstr[2] = '.'
|
||||
frmtstr[3] = '*'
|
||||
frmtstr[4] = floatFormatToChar[format]
|
||||
frmtstr[5] = '\0'
|
||||
c_sprintf(buf, frmtstr, precision, f)
|
||||
else:
|
||||
frmtstr[2] = floatFormatToChar[format]
|
||||
frmtstr[3] = '\0'
|
||||
c_sprintf(buf, frmtstr, f)
|
||||
result = $buf
|
||||
|
||||
proc formatFloat*(f: float, format: TFloatFormat = ffDefault,
|
||||
precision = 16): string {.noSideEffect,
|
||||
rtl, extern: "nsu$1".} =
|
||||
## converts a floating point value `f` to a string.
|
||||
##
|
||||
## If ``format == ffDecimal`` then precision is the number of digits to
|
||||
## be printed after the decimal point.
|
||||
## If ``format == ffScientific`` then precision is the maximum number
|
||||
## of significant digits to be printed.
|
||||
## `precision`'s default value is the maximum number of meaningful digits
|
||||
## after the decimal point for Nimrod's ``float`` type.
|
||||
result = formatBiggestFloat(f, format, precision)
|
||||
rtl, extern: "nsu$1".} =
|
||||
## converts a floating point value `f` to a string.
|
||||
##
|
||||
## If ``format == ffDecimal`` then precision is the number of digits to
|
||||
## be printed after the decimal point.
|
||||
## If ``format == ffScientific`` then precision is the maximum number
|
||||
## of significant digits to be printed.
|
||||
## `precision`'s default value is the maximum number of meaningful digits
|
||||
## after the decimal point for Nimrod's ``float`` type.
|
||||
result = formatBiggestFloat(f, format, precision)
|
||||
|
||||
{.pop.}
|
||||
|
||||
@@ -998,7 +998,7 @@ when isMainModule:
|
||||
assert align("1232", 6) == " 1232"
|
||||
echo wordWrap(""" this is a long text -- muchlongerthan10chars and here
|
||||
it goes""", 10, false)
|
||||
assert formatBiggestFloat(0.00000000001, ffDecimal, 11) == "0.00000000001"
|
||||
assert formatBiggestFloat(0.00000000001, ffScientific, 1) == "1.0e-11"
|
||||
|
||||
|
||||
assert formatBiggestFloat(0.00000000001, ffDecimal, 11) == "0.00000000001"
|
||||
assert formatBiggestFloat(0.00000000001, ffScientific, 1) == "1.0e-11"
|
||||
|
||||
|
||||
|
||||
@@ -627,7 +627,8 @@ proc semTypeNode(c: PContext, n: PNode, prev: PType): PType =
|
||||
of nkBlockType:
|
||||
result = semBlockType(c, n, prev)
|
||||
else:
|
||||
liMessage(n.info, errTypeExpected) #internalError(n.info, 'semTypeNode(' +{&} nodeKindToStr[n.kind] +{&} ')');
|
||||
liMessage(n.info, errTypeExpected)
|
||||
#internalError(n.info, 'semTypeNode(' +{&} nodeKindToStr[n.kind] +{&} ')');
|
||||
|
||||
proc setMagicType(m: PSym, kind: TTypeKind, size: int) =
|
||||
m.typ.kind = kind
|
||||
|
||||
Reference in New Issue
Block a user