From fef495a4a77534c56000726f6db6508b2955fa5d Mon Sep 17 00:00:00 2001 From: Torben Carstens Date: Mon, 18 Sep 2023 19:08:02 +0200 Subject: [PATCH] Add support for duplicate keys in parameters by adding `paramValuesAsSeq` In contrast to `params` this returns a `Table[string, seq[string]]`. Closes #247 --- jester/request.nim | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/jester/request.nim b/jester/request.nim index 205f832..cc1d957 100644 --- a/jester/request.nim +++ b/jester/request.nim @@ -1,4 +1,5 @@ import uri, cgi, tables, logging, strutils, re, options +from sequtils import map import jester/private/utils @@ -116,6 +117,41 @@ proc params*(req: Request): Table[string, string] = except: logging.warn("Could not parse URL query.") +proc paramValuesAsSeq*(req: Request): Table[string, seq[string]] = + ## Parameters from the pattern and the query string. + ## + ## This allows for duplicated keys in the query (in contrast to `params`) + if req.patternParams.isSome(): + let patternParams: Table[string, string] = req.patternParams.get() + var patternParamsSeq: seq[(string, string)] = @[] + for key, val in pairs(patternParams): + patternParamsSeq.add (key, val) + + # We are not url-decoding the key/value for the patternParams (matches implementation in `params` + result = sequtils.map(patternParamsSeq, + proc(entry: (string, string)): (string, seq[string]) = + (entry[0], @[entry[1]]) + ).toTable() + else: + result = initTable[string, seq[string]]() + + var queriesToDecode: seq[string] = @[] + queriesToDecode.add query(req) + + let contentType = req.headers.getOrDefault("Content-Type") + if contentType.startswith("application/x-www-form-urlencoded"): + queriesToDecode.add req.body + + for query in queriesToDecode: + try: + for key, value in cgi.decodeData(query): + if result.hasKey(key): + result[key].add value + else: + result[key] = @[value] + except CgiError: + logging.warn("Incorrect query. Got: $1" % [query]) + proc formData*(req: Request): MultiData = let contentType = req.headers.getOrDefault("Content-Type") if contentType.startsWith("multipart/form-data"):