allow reserved Nim keywords as REST params (#15)

This resolves a compilation error when specifying a reserved Nim keyword
as a REST parameter. The error was `node lacks field: strVal`, as the
corresponding identifiers need backticks embedding, e.g., `` `let` ``,
requiring an additional unwrap of `nnkAccQuoted` to get the raw ident.
This commit is contained in:
Etan Kissling 2021-10-28 18:00:14 +02:00 committed by GitHub
parent 89d321bc16
commit bfcbeceb65
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 37 additions and 2 deletions

View File

@ -254,7 +254,7 @@ macro api*(router: RestRouter, meth: static[HttpMethod],
block: block:
var res = newStmtList() var res = newStmtList()
for (paramName, paramType) in pathArguments: for (paramName, paramType) in pathArguments:
let strName = newStrLitNode(paramName.strVal) let strName = newStrLitNode($paramName)
res.add(quote do: res.add(quote do:
let `paramName` {.used.}: Result[`paramType`, cstring] = let `paramName` {.used.}: Result[`paramType`, cstring] =
decodeString(`paramType`, `pathParams`.getString(`strName`)) decodeString(`paramType`, `pathParams`.getString(`strName`))
@ -266,7 +266,7 @@ macro api*(router: RestRouter, meth: static[HttpMethod],
block: block:
var res = newStmtList() var res = newStmtList()
for (paramName, paramType) in optionalArguments: for (paramName, paramType) in optionalArguments:
let strName = newStrLitNode(paramName.strVal) let strName = newStrLitNode($paramName)
if isOptionalArg(paramType): if isOptionalArg(paramType):
# Optional arguments which has type `Option[T]`. # Optional arguments which has type `Option[T]`.
let optType = getOptionType(paramType) let optType = getOptionType(paramType)

View File

@ -166,6 +166,8 @@ proc testValidate*(pattern: string, value: string): int =
0 0
of "{smp3}": of "{smp3}":
if value.match({'0' .. '9', 'a' .. 'f', 'A' .. 'F', 'x'}): 0 else: 1 if value.match({'0' .. '9', 'a' .. 'f', 'A' .. 'F', 'x'}): 0 else: 1
of "{let}":
if value.match({'0' .. '9'}): 0 else: 1
else: else:
1 1
res res

View File

@ -78,6 +78,39 @@ suite "REST API router & macro tests":
bytesToString(r3.content.data) == "ok-3" bytesToString(r3.content.data) == "ok-3"
bytesToString(r4.content.data) == "ok-4" bytesToString(r4.content.data) == "ok-4"
test "Reserved keywords as parameters test":
var router = RestRouter.init(testValidate)
router.api(MethodGet,
"/test/keyword_args/1/{let}") do (
`let`: int) -> RestApiResponse:
let l = `let`.get()
if (l == 999999):
return RestApiResponse.response("ok-1", contentType = "test/test")
router.api(MethodGet,
"/test/keyword_args/2/{let}") do (
`let`: int,
`var`, `block`, `addr`, `custom`: Option[int]) -> RestApiResponse:
let l = `let`.get()
let v = `var`.get().get()
let b = `block`.get().get()
let a = `addr`.get().get()
let c = custom.get().get()
if (l == 888888) and (v == 777777) and (b == 666666) and
(a == 555555) and (c == 444444):
return RestApiResponse.response("ok-2", contentType = "test/test")
let r1 = router.sendMockRequest(MethodGet,
"http://l.to/test/keyword_args/1/999999")
let r2 = router.sendMockRequest(MethodGet,
"http://l.to/test/keyword_args/2/888888" &
"?var=777777&block=666666&addr=555555&custom=444444")
check:
r1.kind == RestApiResponseKind.Content
bytesToString(r1.content.data) == "ok-1"
r2.kind == RestApiResponseKind.Content
bytesToString(r2.content.data) == "ok-2"
test "Basic types as parameters test": test "Basic types as parameters test":
var router = RestRouter.init(testValidate) var router = RestRouter.init(testValidate)
router.api(MethodGet, router.api(MethodGet,