Added a basic example how to handle a Post request. (#13339)

* Added a basic example how to handle a Post request.

They were also made minor cosmetic changes.

* Minor fixes suggested by Yardanico

* Fixed a wrong value in chunkSize constant.

* Re-added the request.body for compatibility!
This commit is contained in:
Henrique Dias 2020-02-07 08:59:28 +00:00 • committed by GitHub
commit abd660c407
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

@ -29,6 +29,54 @@
## await req.respond(Http200, "Hello World") ## await req.respond(Http200, "Hello World")
## ##
## waitFor server.serve(Port(8080), cb) ## waitFor server.serve(Port(8080), cb)
##
## Basic Post request handle
## =========================
##
## This example will create an HTTP server on port 8080. The server will
## respond with a page with the actual and expected body length after
## submitting a file.
##
## .. code-block::nim
## import asynchttpserver, asyncdispatch
## import strutils, strformat
##
## proc htmlpage(contentLength, bodyLength: int): string =
## return &"""
## <!Doctype html>
## <html lang="en">
## <head>
## <meta charset="utf-8"/>
## </head>
## <body>
## <form action="/" method="post" enctype="multipart/form-data">
## File: <input type="file" name="testfile" accept="text/*"><br />
## <input style="margin:10px 0;" type="submit">
## </form><br />
## Expected Body Length: {contentLength} bytes<br />
## Actual Body Length: {bodyLength} bytes
## </body>
## </html>
## """
##
## proc cb(req: Request) {.async.} =
## var
## contentLength = 0
## bodyLength = 0
## if req.reqMethod == HttpPost:
## contentLength = req.headers["Content-length"].parseInt
## if contentLength < 8*1024: # the default chunkSize
## # read the request body at once
## let body = await req.bodyStream.readAll();
## bodyLength = body.len
## else:
## # read 8*1024 bytes at a time
## while (let data = await req.bodyStream.read(); data[0]):
## bodyLength += data[1].len
## await req.respond(Http200, htmlpage(contentLength, bodyLength))
##
## let server = newAsyncHttpServer(maxBody = 10485760) # 10 MB
## waitFor server.serve(Port(8080), cb)
import tables, asyncnet, asyncdispatch, parseutils, uri, strutils import tables, asyncnet, asyncdispatch, parseutils, uri, strutils
import httpcore import httpcore
@ -46,7 +94,7 @@ const
when (NimMajor, NimMinor) >= (1, 1): when (NimMajor, NimMinor) >= (1, 1):
const const
chunkSize = 8*1048 ## This seems perfectly reasonable for default chunkSize. chunkSize = 8*1024 ## This seems perfectly reasonable for default chunkSize.
type type
Request* = object Request* = object
@ -56,7 +104,7 @@ when (NimMajor, NimMinor) >= (1, 1):
protocol*: tuple[orig: string, major, minor: int] protocol*: tuple[orig: string, major, minor: int]
url*: Uri url*: Uri
hostname*: string ## The hostname of the client that made the request. hostname*: string ## The hostname of the client that made the request.
body*: string body*: string # For future removal
bodyStream*: FutureStream[string] bodyStream*: FutureStream[string]
else: else:
type type
@ -162,12 +210,16 @@ proc processRequest(
# Header: val # Header: val
# \n # \n
request.headers.clear() request.headers.clear()
request.body = ""
request.hostname.shallowCopy(address) request.hostname.shallowCopy(address)
assert client != nil assert client != nil
request.client = client request.client = client
when (NimMajor, NimMinor) >= (1, 1): when (NimMajor, NimMinor) >= (1, 1):
request.bodyStream = newFutureStream[string]() request.bodyStream = newFutureStream[string]()
# To uncomment in the future after compatibility issues
# with third parties are solved
# else:
# request.body = ""
request.body = "" # Temporary fix for future removal
# We should skip at least one empty line before the request # We should skip at least one empty line before the request
# https://tools.ietf.org/html/rfc7230#section-3.5 # https://tools.ietf.org/html/rfc7230#section-3.5