summary refs log tree commit diff stats
path: root/tests/accept/run
diff options
context:
space:
mode:
Diffstat (limited to 'tests/accept/run')
-rwxr-xr-xtests/accept/run/minit.nim2
-rwxr-xr-xtests/accept/run/tbintre2.nim4
-rwxr-xr-xtests/accept/run/tbintree.nim14
-rwxr-xr-xtests/accept/run/tinit.nim4
-rwxr-xr-xtests/accept/run/toverwr.nim4
-rwxr-xr-xtests/accept/run/tpos.nim4
-rwxr-xr-xtests/accept/run/tsimmeth.nim4
7 files changed, 18 insertions, 18 deletions
diff --git a/tests/accept/run/minit.nim b/tests/accept/run/minit.nim
index d3b4b0be1..75fcebb77 100755
--- a/tests/accept/run/minit.nim
+++ b/tests/accept/run/minit.nim
@@ -1,2 +1,2 @@
 # Test the new initialization for modules

-write(stdout, "Hallo from module! ")

+write(stdout, "Hello from module! ")

diff --git a/tests/accept/run/tbintre2.nim b/tests/accept/run/tbintre2.nim
index dedc87705..e85837dfa 100755
--- a/tests/accept/run/tbintre2.nim
+++ b/tests/accept/run/tbintre2.nim
@@ -4,7 +4,7 @@ import tbintree
 
 var
   root: PBinaryTree[string]
-  x = newNode("hallo")
+  x = newNode("hello")
 add(root, x)
 add(root, "world")
 if find(root, "world"):
@@ -21,5 +21,5 @@ add(r2, 99)
 for y in items(r2):
   stdout.write(y)
 
-#OUT halloworld99110223
+#OUT helloworld99110223
 
diff --git a/tests/accept/run/tbintree.nim b/tests/accept/run/tbintree.nim
index 89126eaa5..0561e004a 100755
--- a/tests/accept/run/tbintree.nim
+++ b/tests/accept/run/tbintree.nim
@@ -35,12 +35,12 @@ proc add*[Ty](root: var PBinaryTree[Ty], data: Ty) =
   # convenience proc:
   add(root, newNode(data))
 
-proc find*[Ty2](b: PBinaryTree[Ty2], data: Ty2): bool = 
+proc find*[Ty2](b: PBinaryTree[Ty2], data: Ty2): bool =
   # for testing this needs to be recursive, so that the
   # instantiated type is checked for proper tyGenericInst envelopes
-  if b == nil: 
+  if b == nil:
     result = false
-  else: 
+  else:
     var c = cmp(data, b.data)
     if c < 0: result = find(b.le, data)
     elif c > 0: result = find(b.ri, data)
@@ -66,7 +66,7 @@ iterator items*[T](root: PBinaryTree[T]): T =
     while n != nil:
       add(stack, n)
       n = n.le
-    if stack.len > 0: 
+    if stack.len > 0:
       n = stack.pop()
       yield n.data
       n = n.ri
@@ -81,7 +81,7 @@ proc debug[T](a: PBinaryTree[T]) =
 when isMainModule:
   var
     root: PBinaryTree[string]
-    x = newNode("hallo")
+    x = newNode("hello")
   add(root, x)
   add(root, "world")
   if find(root, "world"):
@@ -89,7 +89,7 @@ when isMainModule:
       stdout.write(str)
   else:
     stdout.writeln("BUG")
-  
+
   var
     r2: PBinaryTree[int]
   add(r2, newNode(110))
@@ -98,4 +98,4 @@ when isMainModule:
   for y in items(r2):
     stdout.write(y)
 
-#OUT halloworld99110223
+#OUT helloworld99110223
diff --git a/tests/accept/run/tinit.nim b/tests/accept/run/tinit.nim
index 85475ce94..386bfec37 100755
--- a/tests/accept/run/tinit.nim
+++ b/tests/accept/run/tinit.nim
@@ -2,5 +2,5 @@
 

 import minit

 

-write(stdout, "Hallo from main module!\n")

-#OUT Hallo from module! Hallo from main module!

+write(stdout, "Hello from main module!\n")

+#OUT Hello from module! Hello from main module!

diff --git a/tests/accept/run/toverwr.nim b/tests/accept/run/toverwr.nim
index f2b42df15..6705c6b3f 100755
--- a/tests/accept/run/toverwr.nim
+++ b/tests/accept/run/toverwr.nim
@@ -3,5 +3,5 @@
 proc write(t: TFile, s: string) =

   nil # a nop

 

-system.write(stdout, "hallo")

-#OUT hallo

+system.write(stdout, "hello")

+#OUT hello

diff --git a/tests/accept/run/tpos.nim b/tests/accept/run/tpos.nim
index 114d39c05..df701d3c5 100755
--- a/tests/accept/run/tpos.nim
+++ b/tests/accept/run/tpos.nim
@@ -23,7 +23,7 @@ proc mypos(sub, s: string, start: int = 0): int =
     else:

       result = -1

 

-var sub = "hallo"

-var s = "world hallo"

+var sub = "hello"

+var s = "world hello"

 write(stdout, mypos(sub, s))

 #OUT 6

diff --git a/tests/accept/run/tsimmeth.nim b/tests/accept/run/tsimmeth.nim
index 3f5f810e6..c6dbf69bb 100755
--- a/tests/accept/run/tsimmeth.nim
+++ b/tests/accept/run/tsimmeth.nim
@@ -2,7 +2,7 @@
 
 import strutils
 
-var x = "hallo world!".toLower.toUpper
+var x = "hello world!".toLower.toUpper
 x.echo()
-#OUT HALLO WORLD!
+#OUT HELLO WORLD!
 
2 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Double */ .highlight .se { color: #0044dd; background-color: #fff0f0 } /* Literal.String.Escape */ .highlight .sh { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Heredoc */ .highlight .si { color: #3333bb; background-color: #fff0f0 } /* Literal.String.Interpol */ .highlight .sx { color: #22bb22; background-color: #f0fff0 } /* Literal.String.Other */ .highlight .sr { color: #008800; background-color: #fff0ff } /* Literal.String.Regex */ .highlight .s1 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Single */ .highlight .ss { color: #aa6600; background-color: #fff0f0 } /* Literal.String.Symbol */ .highlight .bp { color: #003388 } /* Name.Builtin.Pseudo */ .highlight .fm { color: #0066bb; font-weight: bold } /* Name.Function.Magic */ .highlight .vc { color: #336699 } /* Name.Variable.Class */ .highlight .vg { color: #dd7700 } /* Name.Variable.Global */ .highlight .vi { color: #3333bb } /* Name.Variable.Instance */ .highlight .vm { color: #336699 } /* Name.Variable.Magic */ .highlight .il { color: #0000DD; font-weight: bold } /* Literal.Number.Integer.Long */
#
#
#            Nimrod's Runtime Library
#        (c) Copyright 2011 Andreas Rumpf
#
#    See the file "copying.txt", included in this
#    distribution, for details about the copyright.
#

## This module implements a simple HTTP-Server.
##
## Example:
##
## .. code-block:: nimrod
##  import strutils, sockets, httpserver
##
##  var counter = 0
##  proc handleRequest(client: TSocket, path, query: string): bool {.procvar.} =
##    inc(counter)
##    client.send("Hello for the $#th time." % $counter & wwwNL)
##    return false # do not stop processing
##
##  run(handleRequest, TPort(80))
##

import parseutils, strutils, os, osproc, strtabs, streams, sockets

const
  wwwNL* = "\r\L"
  ServerSig = "Server: httpserver.nim/1.0.0" & wwwNL

# --------------- output messages --------------------------------------------

proc sendTextContentType(client: TSocket) =
  send(client, "Content-type: text/html" & wwwNL)
  send(client, wwwNL)

proc badRequest(client: TSocket) =
  # Inform the client that a request it has made has a problem.
  send(client, "HTTP/1.0 400 BAD REQUEST" & wwwNL)
  sendTextContentType(client)
  send(client, "<p>Your browser sent a bad request, " &
               "such as a POST without a Content-Length." & wwwNL)

proc cannotExec(client: TSocket) =
  send(client, "HTTP/1.0 500 Internal Server Error" & wwwNL)
  sendTextContentType(client)
  send(client, "<P>Error prohibited CGI execution." & wwwNL)

proc headers(client: TSocket, filename: string) =
  # XXX could use filename to determine file type
  send(client, "HTTP/1.0 200 OK" & wwwNL)
  send(client, ServerSig)
  sendTextContentType(client)

proc notFound(client: TSocket) =
  send(client, "HTTP/1.0 404 NOT FOUND" & wwwNL)
  send(client, ServerSig)
  sendTextContentType(client)
  send(client, "<html><title>Not Found</title>" & wwwNL)
  send(client, "<body><p>The server could not fulfill" & wwwNL)
  send(client, "your request because the resource specified" & wwwNL)
  send(client, "is unavailable or nonexistent.</p>" & wwwNL)
  send(client, "</body></html>" & wwwNL)

proc unimplemented(client: TSocket) =
  send(client, "HTTP/1.0 501 Method Not Implemented" & wwwNL)
  send(client, ServerSig)
  sendTextContentType(client)
  send(client, "<html><head><title>Method Not Implemented" &
               "</title></head>" &
               "<body><p>HTTP request method not supported.</p>" &
               "</body></HTML>" & wwwNL)

# ----------------- file serving ---------------------------------------------

proc discardHeaders(client: TSocket) = skip(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)
    const bufSize = 8000 # != 8K might be good for memory manager
    var buf = alloc(bufsize)
    while True:
      var bytesread = readBuffer(f, buf, bufsize)
      if bytesread > 0:
        var byteswritten = send(client, buf, bytesread)
        if bytesread != bytesWritten:
          dealloc(buf)
          close(f)
          OSError()
      if bytesread != bufSize: break
    dealloc(buf)
    close(f)
  else:
    notFound(client)

# ------------------ CGI execution -------------------------------------------

type
  TRequestMethod = enum reqGet, reqPost

proc executeCgi(client: TSocket, path, query: string, meth: TRequestMethod) =
  var env = newStringTable(modeCaseInsensitive)
  var contentLength = -1
  case meth
  of reqGet:
    discardHeaders(client)

    env["REQUEST_METHOD"] = "GET"
    env["QUERY_STRING"] = query
  of reqPost:
    var buf = ""
    var dataAvail = false
    while dataAvail:
      dataAvail = recvLine(client, buf)
      var L = toLower(buf)
      if L.startsWith("content-length:"):
        var i = len("content-length:")
        while L[i] in Whitespace: inc(i)
        contentLength = parseInt(substr(L, i))

    if contentLength < 0:
      badRequest(client)
      return

    env["REQUEST_METHOD"] = "POST"
    env["CONTENT_LENGTH"] = $contentLength

  send(client, "HTTP/1.0 200 OK" & wwwNL)

  var process = startProcess(command=path, env=env)
  if meth == reqPost:
    # get from client and post to CGI program:
    var buf = alloc(contentLength)
    if recv(client, buf, contentLength) != contentLength: 
      dealloc(buf)
      OSError()
    var inp = process.inputStream
    inp.writeData(inp, buf, contentLength)
    dealloc(buf)

  var outp = process.outputStream
  while running(process) or not outp.atEnd(outp):
    var line = outp.readLine()
    send(client, line)
    send(client, wwwNL)

# --------------- Server Setup -----------------------------------------------

proc acceptRequest(client: TSocket) =
  var cgi = false
  var query = ""
  var buf = ""
  discard recvLine(client, buf)
  var path = ""
  var data = buf.split()
  var meth = reqGet

  var q = find(data[1], '?')

  # extract path
  if q >= 0:
    # strip "?..." from path, this may be found in both POST and GET
    path = "." & data[1].substr(0, q-1)
  else:
    path = "." & data[1]
  # path starts with "/", by adding "." in front of it we serve files from cwd
  
  if cmpIgnoreCase(data[0], "GET") == 0:
    if q >= 0:
      cgi = true
      query = data[1].substr(q+1)
  elif cmpIgnoreCase(data[0], "POST") == 0:
    cgi = true
    meth = reqPost
  else:
    unimplemented(client)

  if path[path.len-1] == '/' or existsDir(path):
    path = path / "index.html"

  if not ExistsFile(path):
    discardHeaders(client)
    notFound(client)
  else:
    when defined(Windows):
      var ext = splitFile(path).ext.toLower
      if ext == ".exe" or ext == ".cgi":
        # XXX: extract interpreter information here?
        cgi = true
    else:
      if {fpUserExec, fpGroupExec, fpOthersExec} * path.getFilePermissions != {}:
        cgi = true
    if not cgi:
      serveFile(client, path)
    else:
      executeCgi(client, path, query, meth)

type
  TServer* = object       ## contains the current server state
    socket: TSocket
    port: TPort
    client*: TSocket      ## the socket to write the file data to
    path*, query*: string ## path and query the client requested

proc open*(s: var TServer, port = TPort(80)) =
  ## creates a new server at port `port`. If ``port == 0`` a free port is
  ## acquired that can be accessed later by the ``port`` proc.
  s.socket = socket(AF_INET)
  if s.socket == InvalidSocket: OSError()
  bindAddr(s.socket, port)
  listen(s.socket)

  if port == TPort(0):
    s.port = getSockName(s.socket)
  else:
    s.port = port
  s.client = InvalidSocket
  s.path = ""
  s.query = ""

proc port*(s: var TServer): TPort =
  ## get the port number the server has acquired.
  result = s.port

proc next*(s: var TServer) =
  ## proceed to the first/next request.
  s.client = accept(s.socket)
  headers(s.client, "")
  var data = recv(s.client)
  #discard recvLine(s.client, data)
  
  var i = skipWhitespace(data)
  if skipIgnoreCase(data, "GET") > 0: inc(i, 3)
  elif skipIgnoreCase(data, "POST") > 0: inc(i, 4)
  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.substr(query+1, last-1)
    s.path = data.substr(i, query-1)
  else:
    s.query = ""
    s.path = data.substr(i, last-1)

proc close*(s: TServer) =
  ## closes the server (and the socket the server uses).
  close(s.socket)

proc run*(handleRequest: proc (client: TSocket, path, query: string): bool,
          port = TPort(80)) =
  ## encapsulates the server object and main loop
  var s: TServer
  open(s, port)
  #echo("httpserver running on port ", s.port)
  while true:
    next(s)
    if handleRequest(s.client, s.path, s.query): break
    close(s.client)
  close(s)

when isMainModule:
  var counter = 0

  var s: TServer
  open(s, TPort(0))
  echo("httpserver running on port ", s.port)
  while true:
    next(s)
    
    inc(counter)
    s.client.send("Hello, Andreas, for the $#th time. $# ? $#" % [
      $counter, s.path, s.query] & wwwNL)
    
    close(s.client)
  close(s)