summary refs log tree commit diff stats
path: root/examples/httpserver2.nim
diff options
context:
space:
mode:
authorAraq <rumpf_a@web.de>2018-09-03 18:29:00 +0200
committerAraq <rumpf_a@web.de>2018-09-03 18:29:11 +0200
commit320582a55c9ba1f91d70a3f120413e305fda2962 (patch)
tree6114d47a5342adfd4d1f472bb3484a73ad11cf06 /examples/httpserver2.nim
parent1a60ffcf1dc265c6b92dfd757e1bfd5e904c1f3d (diff)
downloadNim-320582a55c9ba1f91d70a3f120413e305fda2962.tar.gz
cleanup Nim's examples/ directory; closes #7725
Diffstat (limited to 'examples/httpserver2.nim')
-rw-r--r--examples/httpserver2.nim247
1 files changed, 0 insertions, 247 deletions
diff --git a/examples/httpserver2.nim b/examples/httpserver2.nim
deleted file mode 100644
index 1843ff967..000000000
--- a/examples/httpserver2.nim
+++ /dev/null
@@ -1,247 +0,0 @@
-import strutils, os, osproc, strtabs, streams, sockets
-
-const
-  wwwNL* = "\r\L"
-  ServerSig = "Server: httpserver.nim/1.0.0" & wwwNL
-
-type
-  TRequestMethod = enum reqGet, reqPost
-  TServer* = object       ## contains the current server state
-    s: Socket
-    job: seq[TJob]
-  TJob* = object
-    client: Socket
-    process: Process
-
-# --------------- output messages --------------------------------------------
-
-proc sendTextContentType(client: Socket) =
-  send(client, "Content-type: text/html" & wwwNL)
-  send(client, wwwNL)
-
-proc badRequest(client: Socket) =
-  # 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.</p>" & wwwNL)
-
-
-proc cannotExec(client: Socket) =
-  send(client, "HTTP/1.0 500 Internal Server Error" & wwwNL)
-  sendTextContentType(client)
-  send(client, "<P>Error prohibited CGI execution.</p>" & wwwNL)
-
-
-proc headers(client: Socket, 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: Socket, path: string) =
-  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 <b>" & path & "</b>" & wwwNL)
-  send(client, "is unavailable or nonexistent.</p>" & wwwNL)
-  send(client, "</body></html>" & wwwNL)
-
-
-proc unimplemented(client: Socket) =
-  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: Socket) = skip(client)
-
-proc serveFile(client: Socket, filename: string) =
-  discardHeaders(client)
-
-  var f: File
-  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:
-          let err = osLastError()
-          dealloc(buf)
-          close(f)
-          raiseOSError(err)
-      if bytesread != bufSize: break
-    dealloc(buf)
-    close(f)
-    client.close()
-  else:
-    notFound(client, filename)
-
-# ------------------ CGI execution -------------------------------------------
-
-proc executeCgi(server: var TServer, client: Socket, 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 = true
-    while dataAvail:
-      dataAvail = recvLine(client, buf)
-      if buf.len == 0:
-        break
-      var L = toLowerAscii(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)
-
-  var job: TJob
-  job.process = process
-  job.client = client
-  server.job.add(job)
-
-  if meth == reqPost:
-    # get from client and post to CGI program:
-    var buf = alloc(contentLength)
-    if recv(client, buf, contentLength) != contentLength:
-      let err = osLastError()
-      dealloc(buf)
-      raiseOSError(err)
-    var inp = process.inputStream
-    inp.writeData(buf, contentLength)
-    dealloc(buf)
-
-proc animate(server: var TServer) =
-  # checks list of jobs, removes finished ones (pretty sloppy by seq copying)
-  var active_jobs: seq[TJob] = @[]
-  for i in 0..server.job.len-1:
-    var job = server.job[i]
-    if running(job.process):
-      active_jobs.add(job)
-    else:
-      # read process output stream and send it to client
-      var outp = job.process.outputStream
-      while true:
-        var line = outp.readstr(1024)
-        if line.len == 0:
-          break
-        else:
-          try:
-            send(job.client, line)
-          except:
-            echo("send failed, client diconnected")
-      close(job.client)
-
-  server.job = active_jobs
-
-# --------------- Server Setup -----------------------------------------------
-
-proc acceptRequest(server: var TServer, client: Socket) =
-  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
-  path = "." & path
-
-  echo("accept: " & path)
-
-  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, path)
-    client.close()
-  else:
-    when defined(Windows):
-      var ext = splitFile(path).ext.toLowerAscii
-      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(server, client, path, query, meth)
-
-when isMainModule:
-  var port = 80
-
-  var server: TServer
-  server.job = @[]
-  server.s = socket(AF_INET)
-  if server.s == invalidSocket: raiseOSError(osLastError())
-  server.s.bindAddr(port=Port(port))
-  listen(server.s)
-  echo("server up on port " & $port)
-
-  while true:
-    # check for new new connection & handle it
-    var list: seq[Socket] = @[server.s]
-    if select(list, 10) > 0:
-      var client: Socket
-      new(client)
-      accept(server.s, client)
-      try:
-        acceptRequest(server, client)
-      except:
-        echo("failed to accept client request")
-
-    # pooling events
-    animate(server)
-    # some slack for CPU
-    sleep(10)
-  server.s.close()