636 lines
22 KiB
Nim
636 lines
22 KiB
Nim
import std/[unittest, strutils]
|
|
import helpers
|
|
import chronos, chronos/apps
|
|
import stew/byteutils
|
|
import ../presto/route, ../presto/segpath, ../presto/server
|
|
|
|
when defined(nimHasUsed): {.used.}
|
|
|
|
type
|
|
ClientResponse = object
|
|
status*: int
|
|
data*: string
|
|
|
|
proc httpClient(server: TransportAddress, meth: HttpMethod, url: string,
|
|
body: string, ctype = "",
|
|
accept = ""): Future[ClientResponse] {.async.} =
|
|
var request = $meth & " " & $parseUri(url) & " HTTP/1.1\r\n"
|
|
request.add("Host: " & $server & "\r\n")
|
|
request.add("Content-Length: " & $len(body) & "\r\n")
|
|
if len(ctype) > 0:
|
|
request.add("Content-Type: " & ctype & "\r\n")
|
|
if len(accept) > 0:
|
|
request.add("Accept: " & accept & "\r\n")
|
|
request.add("\r\n")
|
|
|
|
if len(body) > 0:
|
|
request.add(body)
|
|
|
|
var headersBuf = newSeq[byte](4096)
|
|
let transp = await connect(server)
|
|
let wres {.used.} = await transp.write(request)
|
|
let rlen = await transp.readUntil(addr headersBuf[0], len(headersBuf),
|
|
HeadersMark)
|
|
headersBuf.setLen(rlen)
|
|
let resp = parseResponse(headersBuf, true)
|
|
doAssert(resp.success())
|
|
let length = resp.contentLength()
|
|
doAssert(length >= 0)
|
|
let cresp =
|
|
if length > 0:
|
|
var dataBuf = newString(length)
|
|
await transp.readExactly(addr dataBuf[0], len(dataBuf))
|
|
ClientResponse(status: resp.code, data: dataBuf)
|
|
else:
|
|
ClientResponse(status: resp.code, data: "")
|
|
await transp.closeWait()
|
|
return cresp
|
|
|
|
template asyncTest*(name: string, body: untyped): untyped =
|
|
test name:
|
|
waitFor((
|
|
proc() {.async, gcsafe.} =
|
|
body
|
|
)())
|
|
|
|
suite "REST API server test suite":
|
|
let serverAddress = initTAddress("127.0.0.1:30180")
|
|
asyncTest "Responses test":
|
|
var router = RestRouter.init(testValidate)
|
|
router.api(MethodGet, "/test/simple/1") do () -> RestApiResponse:
|
|
discard
|
|
|
|
router.api(MethodGet, "/test/simple/2") do () -> RestApiResponse:
|
|
return RestApiResponse.response("ok-1")
|
|
|
|
router.api(MethodGet, "/test/simple/3") do () -> RestApiResponse:
|
|
return RestApiResponse.error(Http505, "Some error", "text/error")
|
|
|
|
router.api(MethodGet, "/test/simple/4") do () -> RestApiResponse:
|
|
if true:
|
|
raise newException(ValueError, "Some exception")
|
|
|
|
var sres = RestServerRef.new(router, serverAddress)
|
|
let server = sres.get()
|
|
server.start()
|
|
try:
|
|
# Handler returned empty response.
|
|
let res1 = await httpClient(serverAddress, MethodGet, "/test/simple/1",
|
|
"")
|
|
# Handler returned good response.
|
|
let res2 = await httpClient(serverAddress, MethodGet, "/test/simple/2",
|
|
"")
|
|
# Handler returned via RestApiResponse.
|
|
let res3 = await httpClient(serverAddress, MethodGet, "/test/simple/3",
|
|
"")
|
|
# Exception generated by handler.
|
|
let res4 = await httpClient(serverAddress, MethodGet, "/test/simple/4",
|
|
"")
|
|
# Missing handler response
|
|
let res5 = await httpClient(serverAddress, MethodGet, "/test/simple/5",
|
|
"")
|
|
# URI with more than 64 segments response
|
|
let res6 = await httpClient(serverAddress, MethodGet,
|
|
"//////////////////////////////////////////" &
|
|
"//////////////////////////test", "")
|
|
check:
|
|
res1 == ClientResponse(status: 410)
|
|
res2 == ClientResponse(status: 200, data: "ok-1")
|
|
res3.status == 505
|
|
res4 == ClientResponse(status: 503)
|
|
res5 == ClientResponse(status: 404)
|
|
res6 == ClientResponse(status: 400)
|
|
finally:
|
|
await server.closeWait()
|
|
|
|
asyncTest "Requests [path] arguments test":
|
|
var router = RestRouter.init(testValidate)
|
|
router.api(MethodGet, "/test/{smp1}") do (
|
|
smp1: int) -> RestApiResponse:
|
|
if smp1.isErr():
|
|
return RestApiResponse.error(Http411, $smp1.error())
|
|
return RestApiResponse.response($smp1.get())
|
|
|
|
router.api(MethodGet, "/test/{smp1}/{smp2}") do (
|
|
smp1: int, smp2: string) -> RestApiResponse:
|
|
if smp1.isErr():
|
|
return RestApiResponse.error(Http411, $smp1.error())
|
|
if smp2.isErr():
|
|
return RestApiResponse.error(Http412, $smp2.error())
|
|
return RestApiResponse.response($smp1.get() & ":" &
|
|
smp2.get())
|
|
|
|
router.api(MethodGet, "/test/{smp1}/{smp2}/{smp3}") do (
|
|
smp1: int, smp2: string, smp3: seq[byte]) -> RestApiResponse:
|
|
if smp1.isErr():
|
|
return RestApiResponse.error(Http411, $smp1.error())
|
|
if smp2.isErr():
|
|
return RestApiResponse.error(Http412, $smp2.error())
|
|
if smp3.isErr():
|
|
return RestApiResponse.error(Http413, $smp3.error())
|
|
return RestApiResponse.response($smp1.get() & ":" & smp2.get() & ":" &
|
|
toHex(smp3.get()))
|
|
|
|
const TestVectors = [
|
|
("/test/1234", ClientResponse(status: 200, data: "1234")),
|
|
("/test/12345678", ClientResponse(status: 200, data: "12345678")),
|
|
("/test/00000001", ClientResponse(status: 200, data: "1")),
|
|
("/test/0000000", ClientResponse(status: 200, data: "0")),
|
|
("/test/99999999999999999999999", ClientResponse(status: 411)),
|
|
("/test/nondec", ClientResponse(status: 404)),
|
|
|
|
("/test/1234/text1", ClientResponse(status: 200, data: "1234:text1")),
|
|
("/test/12345678/texttext2",
|
|
ClientResponse(status: 200, data: "12345678:texttext2")),
|
|
("/test/00000001/texttexttext3",
|
|
ClientResponse(status: 200, data: "1:texttexttext3")),
|
|
("/test/0000000/texttexttexttext4",
|
|
ClientResponse(status: 200, data: "0:texttexttexttext4")),
|
|
("/test/nondec/texttexttexttexttext5", ClientResponse(status: 404)),
|
|
("/test/99999999999999999999999/texttexttexttexttext5",
|
|
ClientResponse(status: 411)),
|
|
|
|
("/test/1234/text1/0xCAFE",
|
|
ClientResponse(status: 200, data: "1234:text1:cafe")),
|
|
("/test/12345678/text2text2/0xdeadbeaf",
|
|
ClientResponse(status: 200, data: "12345678:text2text2:deadbeaf")),
|
|
("/test/00000001/text3text3text3/0xabcdef012345",
|
|
ClientResponse(status: 200, data: "1:text3text3text3:abcdef012345")),
|
|
("/test/00000000/text4text4text4text4/0xaa",
|
|
ClientResponse(status: 200, data: "0:text4text4text4text4:aa")),
|
|
("/test/nondec/text5/0xbb", ClientResponse(status: 404)),
|
|
("/test/99999999999999999999999/text6/0xcc", ClientResponse(status: 411)),
|
|
("/test/1234/text7/0xxx", ClientResponse(status: 413))
|
|
]
|
|
|
|
var sres = RestServerRef.new(router, serverAddress)
|
|
let server = sres.get()
|
|
server.start()
|
|
try:
|
|
for item in TestVectors:
|
|
let res = await httpClient(serverAddress, MethodGet,
|
|
item[0], "")
|
|
check res.status == item[1].status
|
|
if len(item[1].data) > 0:
|
|
check res.data == item[1].data
|
|
finally:
|
|
await server.closeWait()
|
|
|
|
asyncTest "Requests [path + query] arguments test":
|
|
var router = RestRouter.init(testValidate)
|
|
router.api(MethodGet, "/test/{smp1}/{smp2}/{smp3}") do (
|
|
smp1: int, smp2: string, smp3: seq[byte],
|
|
opt1: Option[int], opt2: Option[string], opt3: Option[seq[byte]],
|
|
opt4: seq[int], opt5: seq[string],
|
|
opt6: seq[seq[byte]]) -> RestApiResponse:
|
|
|
|
if smp1.isErr():
|
|
return RestApiResponse.error(Http411, $smp1.error())
|
|
if smp2.isErr():
|
|
return RestApiResponse.error(Http412, $smp2.error())
|
|
if smp3.isErr():
|
|
return RestApiResponse.error(Http413, $smp3.error())
|
|
|
|
let o1 =
|
|
if opt1.isSome():
|
|
let res = opt1.get()
|
|
if res.isErr():
|
|
return RestApiResponse.error(Http414, $res.error())
|
|
$res.get()
|
|
else:
|
|
""
|
|
let o2 =
|
|
if opt2.isSome():
|
|
let res = opt2.get()
|
|
if res.isErr():
|
|
return RestApiResponse.error(Http415, $res.error())
|
|
res.get()
|
|
else:
|
|
""
|
|
let o3 =
|
|
if opt3.isSome():
|
|
let res = opt3.get()
|
|
if res.isErr():
|
|
return RestApiResponse.error(Http416, $res.error())
|
|
toHex(res.get())
|
|
else:
|
|
""
|
|
let o4 =
|
|
if opt4.isErr():
|
|
return RestApiResponse.error(Http417, $opt4.error())
|
|
else:
|
|
opt4.get().join(",")
|
|
let o5 =
|
|
if opt5.isErr():
|
|
return RestApiResponse.error(Http418, $opt5.error())
|
|
else:
|
|
opt5.get().join(",")
|
|
let o6 =
|
|
if opt6.isErr():
|
|
return RestApiResponse.error(Http421, $opt6.error())
|
|
else:
|
|
let binres = opt6.get()
|
|
var res = newSeq[string]()
|
|
for item in binres:
|
|
res.add(toHex(item))
|
|
res.join(",")
|
|
|
|
let body = $smp1.get() & ":" & smp2.get() & ":" & toHex(smp3.get()) &
|
|
":" & o1 & ":" & o2 & ":" & o3 &
|
|
":" & o4 & ":" & o5 & ":" & o6
|
|
return RestApiResponse.response(body)
|
|
|
|
const TestVectors = [
|
|
("/test/1/2/0xaa?opt1=1&opt2=2&opt3=0xbb&opt4=2&opt4=3&opt4=4&opt5=t&" &
|
|
"opt5=e&opt5=s&opt5=t&opt6=0xCA&opt6=0xFE",
|
|
ClientResponse(status: 200, data: "1:2:aa:1:2:bb:2,3,4:t,e,s,t:ca,fe")),
|
|
# Optional argument will not pass decoding procedure `opt1=a`.
|
|
("/test/1/2/0xaa?opt1=a&opt2=2&opt3=0xbb&opt4=2&opt4=3&opt4=4&opt5=t&" &
|
|
"opt5=e&opt5=s&opt5=t&opt6=0xCA&opt6=0xFE",
|
|
ClientResponse(status: 414)),
|
|
# Sequence argument will not pass decoding procedure `opt4=a`.
|
|
("/test/1/2/0xaa?opt1=1&opt2=2&opt3=0xbb&opt4=2&opt4=3&opt4=a&opt5=t&" &
|
|
"opt5=e&opt5=s&opt5=t&opt6=0xCA&opt6=0xFE",
|
|
ClientResponse(status: 417)),
|
|
# Optional argument will not pass decoding procedure `opt3=0xxx`.
|
|
("/test/1/2/0xaa?opt1=1&opt2=2&opt3=0xxx&opt4=2&opt4=3&opt4=4&opt5=t&" &
|
|
"opt5=e&opt5=s&opt5=t&opt6=0xCA&opt6=0xFE",
|
|
ClientResponse(status: 416)),
|
|
# Sequence argument will not pass decoding procedure `opt6=0xxx`.
|
|
("/test/1/2/0xaa?opt1=1&opt2=2&opt3=0xbb&opt4=2&opt4=3&opt4=5&opt5=t&" &
|
|
"opt5=e&opt5=s&opt5=t&opt6=0xCA&opt6=0xxx",
|
|
ClientResponse(status: 421)),
|
|
# All optional arguments are missing
|
|
("/test/1/2/0xaa", ClientResponse(status: 200, data: "1:2:aa::::::"))
|
|
]
|
|
|
|
var sres = RestServerRef.new(router, serverAddress)
|
|
let server = sres.get()
|
|
server.start()
|
|
try:
|
|
for item in TestVectors:
|
|
let res = await httpClient(serverAddress, MethodGet,
|
|
item[0], "")
|
|
check res.status == item[1].status
|
|
if len(item[1].data) > 0:
|
|
check res.data == item[1].data
|
|
finally:
|
|
await server.closeWait()
|
|
|
|
asyncTest "Requests [path + query + request body] test":
|
|
var router = RestRouter.init(testValidate)
|
|
router.api(MethodPost, "/test/{smp1}/{smp2}/{smp3}") do (
|
|
smp1: int, smp2: string, smp3: seq[byte],
|
|
opt1: Option[int], opt2: Option[string], opt3: Option[seq[byte]],
|
|
opt4: seq[int], opt5: seq[string],
|
|
opt6: seq[seq[byte]],
|
|
contentBody: Option[ContentBody]) -> RestApiResponse:
|
|
|
|
if smp1.isErr():
|
|
return RestApiResponse.error(Http411, $smp1.error())
|
|
if smp2.isErr():
|
|
return RestApiResponse.error(Http412, $smp2.error())
|
|
if smp3.isErr():
|
|
return RestApiResponse.error(Http413, $smp3.error())
|
|
|
|
let o1 =
|
|
if opt1.isSome():
|
|
let res = opt1.get()
|
|
if res.isErr():
|
|
return RestApiResponse.error(Http414, $res.error())
|
|
$res.get()
|
|
else:
|
|
""
|
|
let o2 =
|
|
if opt2.isSome():
|
|
let res = opt2.get()
|
|
if res.isErr():
|
|
return RestApiResponse.error(Http415, $res.error())
|
|
res.get()
|
|
else:
|
|
""
|
|
let o3 =
|
|
if opt3.isSome():
|
|
let res = opt3.get()
|
|
if res.isErr():
|
|
return RestApiResponse.error(Http416, $res.error())
|
|
toHex(res.get())
|
|
else:
|
|
""
|
|
let o4 =
|
|
if opt4.isErr():
|
|
return RestApiResponse.error(Http417, $opt4.error())
|
|
else:
|
|
opt4.get().join(",")
|
|
let o5 =
|
|
if opt5.isErr():
|
|
return RestApiResponse.error(Http418, $opt5.error())
|
|
else:
|
|
opt5.get().join(",")
|
|
let o6 =
|
|
if opt6.isErr():
|
|
return RestApiResponse.error(Http421, $opt6.error())
|
|
else:
|
|
let binres = opt6.get()
|
|
var res = newSeq[string]()
|
|
for item in binres:
|
|
res.add(toHex(item))
|
|
res.join(",")
|
|
|
|
let obody =
|
|
if contentBody.isSome():
|
|
let body = contentBody.get()
|
|
body.contentType & "," & bytesToString(body.data)
|
|
else:
|
|
"nobody"
|
|
|
|
let body = $smp1.get() & ":" & smp2.get() & ":" & toHex(smp3.get()) &
|
|
":" & o1 & ":" & o2 & ":" & o3 &
|
|
":" & o4 & ":" & o5 & ":" & o6 &
|
|
":" & obody
|
|
|
|
return RestApiResponse.response(body)
|
|
|
|
const PostVectors = [
|
|
(
|
|
("/test/1/2/0xaa", "text/text", "textbody"),
|
|
ClientResponse(status: 200,
|
|
data: "1:2:aa:::::::text/text,textbody")
|
|
),
|
|
(
|
|
("/test/1/2/0xaa", "", ""),
|
|
ClientResponse(status: 400)
|
|
),
|
|
(
|
|
("/test/1/2/0xaa", "text/text", ""),
|
|
ClientResponse(status: 200,
|
|
data: "1:2:aa:::::::text/text,")
|
|
),
|
|
(
|
|
("/test/1/2/0xaa?opt1=1&opt2=2&opt3=0xbb&opt4=2&opt4=3&opt4=4&opt5=t&" &
|
|
"opt5=e&opt5=s&opt5=t&opt6=0xCA&opt6=0xFE", "text/text", "textbody"),
|
|
ClientResponse(status: 200, data:
|
|
"1:2:aa:1:2:bb:2,3,4:t,e,s,t:ca,fe:text/text,textbody")
|
|
)
|
|
]
|
|
|
|
var sres = RestServerRef.new(router, serverAddress)
|
|
let server = sres.get()
|
|
server.start()
|
|
try:
|
|
for item in PostVectors:
|
|
let req = item[0]
|
|
let res = await httpClient(serverAddress, MethodPost,
|
|
req[0], req[2], req[1])
|
|
check res.status == item[1].status
|
|
if len(item[1].data) > 0:
|
|
check res.data == item[1].data
|
|
|
|
finally:
|
|
await server.closeWait()
|
|
|
|
asyncTest "Direct response manipulation test":
|
|
var router = RestRouter.init(testValidate)
|
|
router.api(MethodGet, "/test/{smp1}") do (
|
|
smp1: int, opt1: Option[int], opt4: seq[int],
|
|
resp: HttpResponseRef) -> RestApiResponse:
|
|
|
|
if smp1.isErr():
|
|
return RestApiResponse.error(Http411, $smp1.error())
|
|
|
|
let o1 =
|
|
if opt1.isSome():
|
|
let res = opt1.get()
|
|
if res.isErr():
|
|
return RestApiResponse.error(Http414, $res.error())
|
|
$res.get()
|
|
else:
|
|
""
|
|
let o4 =
|
|
if opt4.isErr():
|
|
return RestApiResponse.error(Http417, $opt4.error())
|
|
else:
|
|
opt4.get().join(",")
|
|
|
|
let path = smp1.get()
|
|
let restResp = $smp1.get() & ":" & o1 & ":" & o4
|
|
case path
|
|
of 1:
|
|
await resp.sendBody(restResp)
|
|
of 2:
|
|
await resp.sendBody(restResp)
|
|
return RestApiResponse.response("")
|
|
of 3:
|
|
await resp.sendBody(restResp)
|
|
return RestApiResponse.error(Http422, "error")
|
|
else:
|
|
return RestApiResponse.error(Http426, "error")
|
|
|
|
router.api(MethodPost, "/test/{smp1}") do (
|
|
smp1: int, opt1: Option[int], opt4: seq[int],
|
|
body: Option[ContentBody], resp: HttpResponseRef) -> RestApiResponse:
|
|
|
|
if smp1.isErr():
|
|
return RestApiResponse.error(Http411, $smp1.error())
|
|
let o1 =
|
|
if opt1.isSome():
|
|
let res = opt1.get()
|
|
if res.isErr():
|
|
return RestApiResponse.error(Http414, $res.error())
|
|
$res.get()
|
|
else:
|
|
""
|
|
let o4 =
|
|
if opt4.isErr():
|
|
return RestApiResponse.error(Http417, $opt4.error())
|
|
else:
|
|
opt4.get().join(",")
|
|
|
|
let obody =
|
|
if body.isSome():
|
|
let b = body.get()
|
|
b.contentType & "," & bytesToString(b.data)
|
|
else:
|
|
"nobody"
|
|
|
|
let path = smp1.get()
|
|
let restResp = $smp1.get() & ":" & o1 & ":" & o4 & ":" & obody
|
|
|
|
case path
|
|
of 1:
|
|
await resp.sendBody(restResp)
|
|
of 2:
|
|
await resp.sendBody(restResp)
|
|
return RestApiResponse.response("some result")
|
|
of 3:
|
|
await resp.sendBody(restResp)
|
|
return RestApiResponse.error(Http422, "error")
|
|
else:
|
|
return RestApiResponse.error(Http426, "error")
|
|
|
|
const PostVectors = [
|
|
(
|
|
# Empty result with response sent via `resp`.
|
|
("/test/1?opt1=2345&opt4=3456&opt4=4567&opt4=5678&opt4=6789",
|
|
"text/text", "somebody"),
|
|
ClientResponse(status: 200,
|
|
data: "1:2345:3456,4567,5678,6789:text/text,somebody")
|
|
),
|
|
(
|
|
# Result with response sent via `resp`.
|
|
("/test/2?opt1=2345&opt4=3456&opt4=4567&opt4=5678&opt4=6789",
|
|
"text/text", "somebody"),
|
|
ClientResponse(status: 200,
|
|
data: "2:2345:3456,4567,5678,6789:text/text,somebody")
|
|
),
|
|
(
|
|
# Error with response sent via `resp`.
|
|
("/test/3?opt1=2345&opt4=3456&opt4=4567&opt4=5678&opt4=6789",
|
|
"text/text", "somebody"),
|
|
ClientResponse(status: 200,
|
|
data: "3:2345:3456,4567,5678,6789:text/text,somebody")
|
|
)
|
|
]
|
|
|
|
const GetVectors = [
|
|
(
|
|
# Empty result with response sent via `resp`.
|
|
"/test/1?opt1=2345&opt4=3456&opt4=4567&opt4=5678&opt4=6789",
|
|
ClientResponse(status: 200, data: "1:2345:3456,4567,5678,6789")
|
|
),
|
|
(
|
|
# Result with response sent via `resp`.
|
|
"/test/2?opt1=2345&opt4=3456&opt4=4567&opt4=5678&opt4=6789",
|
|
ClientResponse(status: 200, data: "2:2345:3456,4567,5678,6789")
|
|
),
|
|
(
|
|
# Error with response sent via `resp`.
|
|
"/test/3?opt1=2345&opt4=3456&opt4=4567&opt4=5678&opt4=6789",
|
|
ClientResponse(status: 200, data: "3:2345:3456,4567,5678,6789")
|
|
)
|
|
]
|
|
|
|
var sres = RestServerRef.new(router, serverAddress)
|
|
let server = sres.get()
|
|
server.start()
|
|
try:
|
|
for item in GetVectors:
|
|
let res = await httpClient(serverAddress, MethodGet, item[0], "")
|
|
check res.status == item[1].status
|
|
if len(item[1].data) > 0:
|
|
check res.data == item[1].data
|
|
|
|
for item in PostVectors:
|
|
let req = item[0]
|
|
let res = await httpClient(serverAddress, MethodPost,
|
|
req[0], req[2], req[1])
|
|
check res.status == item[1].status
|
|
if len(item[1].data) > 0:
|
|
check res.data == item[1].data
|
|
|
|
finally:
|
|
await server.closeWait()
|
|
|
|
asyncTest "preferredContentType() test":
|
|
const PostVectors = [
|
|
(
|
|
("/test/post", "somebody0908", "text/html",
|
|
"app/type1;q=0.9,app/type2;q=0.8"),
|
|
ClientResponse(status: 200, data: "type1[text/html,somebody0908]")
|
|
),
|
|
(
|
|
("/test/post", "somebody0908", "text/html",
|
|
"app/type2;q=0.8,app/type1;q=0.9"),
|
|
ClientResponse(status: 200, data: "type1[text/html,somebody0908]")
|
|
),
|
|
(
|
|
("/test/post", "somebody09", "text/html",
|
|
"app/type2,app/type1;q=0.9"),
|
|
ClientResponse(status: 200, data: "type2[text/html,somebody09]")
|
|
),
|
|
(
|
|
("/test/post", "somebody09", "text/html", "app/type1;q=0.9,app/type2"),
|
|
ClientResponse(status: 200, data: "type2[text/html,somebody09]")
|
|
),
|
|
(
|
|
("/test/post", "somebody", "text/html", "*/*"),
|
|
ClientResponse(status: 200, data: "type1[text/html,somebody]")
|
|
),
|
|
(
|
|
("/test/post", "somebody", "text/html", ""),
|
|
ClientResponse(status: 200, data: "type1[text/html,somebody]")
|
|
),
|
|
(
|
|
("/test/post", "somebody", "text/html", "app/type2"),
|
|
ClientResponse(status: 200, data: "type2[text/html,somebody]")
|
|
),
|
|
(
|
|
("/test/post", "somebody", "text/html", "app/type3"),
|
|
ClientResponse(status: 406, data: "")
|
|
)
|
|
]
|
|
var router = RestRouter.init(testValidate)
|
|
router.api(MethodPost, "/test/post") do (
|
|
body: Option[ContentBody], resp: HttpResponseRef) -> RestApiResponse:
|
|
let obody =
|
|
if body.isSome():
|
|
let b = body.get()
|
|
b.contentType & "," & bytesToString(b.data)
|
|
else:
|
|
"nobody"
|
|
|
|
let preferred = preferredContentType(testMediaType1, testMediaType2)
|
|
return
|
|
if preferred.isOk():
|
|
if preferred.get() == testMediaType1:
|
|
RestApiResponse.response("type1[" & obody & "]")
|
|
elif preferred.get() == testMediaType2:
|
|
RestApiResponse.response("type2[" & obody & "]")
|
|
else:
|
|
# This MUST not be happened.
|
|
RestApiResponse.error(Http407, "")
|
|
else:
|
|
RestApiResponse.error(Http406, "")
|
|
|
|
var sres = RestServerRef.new(router, serverAddress)
|
|
let server = sres.get()
|
|
server.start()
|
|
try:
|
|
for item in PostVectors:
|
|
let res = await httpClient(serverAddress, MethodPost, item[0][0],
|
|
item[0][1], item[0][2], item[0][3])
|
|
check:
|
|
res.status == item[1].status
|
|
res.data == item[1].data
|
|
finally:
|
|
await server.closeWait()
|
|
|
|
asyncTest "Handle raw requests inside api handler test":
|
|
var router = RestRouter.init(testValidate)
|
|
router.rawApi(MethodPost, "/test/post") do () -> RestApiResponse:
|
|
let contentType = request.headers.getString(ContentTypeHeader)
|
|
let acceptType = request.headers.getString(AcceptHeaderName)
|
|
let body = await request.getBody()
|
|
return
|
|
RestApiResponse.response(
|
|
"type[" & contentType & ":" & body.toHex() & "]")
|
|
|
|
var sres = RestServerRef.new(router, serverAddress)
|
|
let server = sres.get()
|
|
server.start()
|
|
try:
|
|
let res = await httpClient(serverAddress, MethodPost, "/test/post",
|
|
"0123456789", "application/octet-stream")
|
|
check:
|
|
res.status == 200
|
|
res.data == "type[application/octet-stream:30313233343536373839]"
|
|
finally:
|
|
await server.closeWait()
|
|
|
|
test "Leaks test":
|
|
check:
|
|
getTracker("async.stream.reader").isLeaked() == false
|
|
getTracker("async.stream.writer").isLeaked() == false
|
|
getTracker("stream.server").isLeaked() == false
|
|
getTracker("stream.transport").isLeaked() == false
|