I built an Akka-Http Client inside a Server, which gets a GET request by a browser and then uses it’s one parameter to make a POST request to Twitter. Then, the server makes a JSON string out of the Twitter’s response and gives it back to the browser.
So, my code works. It does. The problem is it works only once. If I call GET /StepOne for a second time, it fails.
val route = cors(settings){
path("StepOne"){
get {
parameters('callback.as[String])(cb => {
val callback = this.encodeUriComp(cb)
val url = "https://api.twitter.com/oauth/request_token"
var response: String = null
this.oauth_timestamp = this.createTimestamp()
this.oauth_nonce = this.randomString(32)
val authorization = headers.RawHeader("Authorization",
"""OAuth oauth_callback="""" + callback +
"""", oauth_consumer_key="""" + this.consumerKey +
"""", oauth_nonce="""" + this.oauth_nonce +
"""", oauth_signature="""" + this.encodeUriComp(this.createSignature()) +
"""", oauth_signature_method="HMAC-SHA1", oauth_timestamp="""" + this.oauth_timestamp +
"""", oauth_version="1.0"""")
val params = ByteString(callback)
var jsonRSP = "null string"
val responseFuture: Future[HttpResponse] = Http().singleRequest(HttpRequest(HttpMethods.POST, url,
headers = List(authorization),
entity = HttpEntity(ContentTypes.`text/plain(UTF-8)`, params)))
responseFuture
.onComplete {
case Success(res) => {
val response = res._3.dataBytes.map(_.utf8String).runForeach(body => {
/* We postedit the string to make it JSON Parsable */
jsonRSP = "{" + body.replaceAll("=", ":")
.replaceAll("&", ",")
.replaceAll("([\w-]+)", ""$1"") + "}"
// jsonRSP = postBody
println(jsonRSP)
})
}
case Failure(_) => sys.error("Couldn't get into api.twitter")
}
implicit val timeout = Timeout(5, TimeUnit.SECONDS)
Await.result(responseFuture, timeout.duration)
println(jsonRSP)
complete(HttpEntity(ContentTypes.`application/json`, jsonRSP))
})
}
}
}
So as you can see, I declare a var called JsonRSP which initially prints “null string”. After that I make the POST call and I edit the JsonRSP with the information given by Twitter. The second time I call this StepOne API, the JsonRSP string isn’t edited and it prints the “null string” over again. This happens despite the fact that Twitter gives me the right information every time.
So, for example, the first time I get:
{"oauth_token":"mytoken","oauth_token_secret":"mysecrettoken","oauth_callback_confirmed":"true"}
But the second time I call my API it returns:
“Null String”
Any ideas? I’m well known for making obvious mistakes so please help me !
________ EDIT ______
I’ve edited the code to get rid of an aux variable that wasn’t needed at all.
So the main thing here is that if I print jsonRSP inside de runForeach it prints the correct JSON. But when I print it before doing the complete it prints “null string” all over again. To make it weirder, it still completes the right json the first time, but “null string” the second time. So I don’t have a clue why is this happening. If my code shoudln’t work, it shouldn’t work everytime, so why does it work the first time?
2
Answers
Finally I chose what is cleaner. Thanks to @tea-adict 's response I came up with this code.
It doesn't complete a JSON string. Instead, it sends the same plain-text gotten from Twitter back to the front-end app. Then, I will simply take that response in my front-end and transform it to a JSON string to parse it and work with it.
It's much cleaner this way.
I think your problem is related with
Future
, because you don’t wait for response actually,complete(HttpEntity(ContentTypes.'application/json', jsonRSP))
, you always returnjsonRSP
. You should wait forFuture
computation and then return it.