I would like to do the request below in an async manner. From looking at the docs I cant manage to make it work. Would appreciate if someone could point me in the right direction. thanks
Something goes wrong here:
proc asyncProc(): Future[string] {.async.} =
var client = newAsyncHttpClient()
client.headers = newHttpHeaders({"Content-Type":"application/json",})
let body = %*{"id":obj.system_id,
"system":obj.system }
return await client.post(obj.login_url, $body)
echo waitFor asyncProc()
ERRORS
Error: type mismatch: got <Future[system.string], AsyncResponse>
but expected one of:
proc complete[T](future: Future[T]; val: T)
first type mError: type mismatch: got <Future[system.string], AsyncResponse>
but expected one of:
proc complete[T](future: Future[T]; val: T)
first type mismatch at position: 2
required type for val: T
but expression '
var internalTmpFuture`gensym16: FutureBase = post(client, obj.login_url, $body,
nil)
yield internalTmpFuture`gensym16
read(cast[typeof(post(client, obj.login_url, $body, nil))](internalTmpFuture`gensym16))' is of type: AsyncResponse
4 other mismatching symbols have been suppressed; compile with --showAllMismatches:on to see them
expression: complete(retFuture_2197815595) do:
var internalTmpFuture`gensym16: FutureBase = post(client, obj.login_url,
$body, nil)
yield internalTmpFuture`gensym16
read(cast[typeof(post(client, obj.login_url, $body, nil))](internalTmpFuture`gensym16))
ismatch at position: 2
required type for val: T
but expression '
var internalTmpFuture`gensym16: FutureBase = post(client, obj.login_url, $body,
nil)
yield internalTmpFuture`gensym16
read(cast[typeof(post(client, obj.login_url, $body, nil))](internalTmpFuture`gensym16))' is of type: AsyncResponse
4 other mismatching symbols have been suppressed; compile with --showAllMismatches:on to see them
expression: complete(retFuture_2197815595) do:
var internalTmpFuture`gensym16: FutureBase = post(client, obj.login_url,
$body, nil)
yield internalTmpFuture`gensym16
read(cast[typeof(post(client, obj.login_url, $body, nil))](internalTmpFuture`gensym16))
Working request I would like to turn in to async.
let client = newHttpClient()
client.headers = newHttpHeaders({"Content-Type":"application/json",})
let body = %*{"id":obj.system_id,
"system":obj.system}
let response = client.request(obj.login_url, httpMethod = HttpPost, body = $body)
echo(response.status)
Async errors are quite noisy but the answer is on the first line: Error: type mismatch: got <Future[system.string], AsyncResponse>
Your procedure returns Future[string] but post returns Future[AsyncResponse]
You probably want the body field of asyncresponse
What I have below works now but I'm struggeling with the nim syntax. I found out that there is a proc that would be more perfect ->
proc withTimeoutT: owned(Future[bool]) here https://nim-lang.org/docs/httpclient.html#post%2CAsyncHttpClient%2C%2Cstring%2CMultipartData
but I syntaxwize can not understand how to implement it. Would appreciate some advice here. Thanks
proc asyncProc(): Future[AsyncResponse] {.async.} =
var client = newAsyncHttpClient()
client.headers = newHttpHeaders({"Content-Type":"application/json",})
let body = %*{"id":obj.system_id,
"system":obj.system,
"user":obj.user,
"password":obj.password,
"lang":"sv" }
let con = await client.post(obj.login_url, body = $body)
return con
echo waitFor asyncProc()
The problem I have is that I'm trying to do an API post login using the httpclient. Sometimes something is wrong on the other end and the call will not get a proper response back. If that happens I need to act on it and cancel the request and move on to the next one in the loop. This is where I find no solution in nim. I have tried using the timeout param in the httpclient but it does not work. I've tried using the AsyncHttpClient, Found an example using chronos but it does not work (or maybe imports are needed that I'm am not aware of).
Any advice appreciated here I just want to:
1. Send off my post request 2.Poll it to see if it is stuck and never resolved and if so kill it
This is, how I'm doing async POST request + custom headers possible, with JSON to httpbin and some debugging too:
import std/[httpclient, asyncdispatch,json]
const Url = "http://httpbin.org/post"
proc asyncTask(): Future[AsyncResponse] {.async.} =
let client = newAsyncHttpClient()
client.headers = newHttpHeaders()
add(client.headers, key = "Content-Type", value="application/json")
# JSON body
let body = %*{
"key":"value"
}
return await client.request(url, httpMethod = HttpPost, body = $body)
let response = waitFor asyncTask()
if response.status == "200 OK":
let resHeaders = response.headers
let resBody = response.body()
echo resHeaders
echo resBody.read()
else:
echo "Request failed with status ", response.status
Did you test your call with the curl? e.g.
curl -X POST http://httpbin.org/post -H 'Content-Type: application/json' -d '{"key":"value"}'
Is still stuck, I guess it could be an issue with the backend?
Unfortunately, timeouts will work only for newHttpClient
https://nim-lang.org/docs/httpclient.html#timeouts
Maybe looks very silly, but you can use synchronous post request instead of async, but execute the post request in a thread (spawn from threadpool)?