nil result from network.request()

There is a problem when you attempt to return a value from a function that requires a response from network.request(). The problem is that the result returned will be nil. Only after some time has passed will the result from the network.request() be available. You can use the network listener to wait for the response, but there is no obvious way to return that response to a calling function. I am submitting this as a bug because the same problem does not occur when using Lua sockets. I am including sample code for each (network.request() and http.request()) situation so you can see the difference.

network.request() sample code:

local myText = display.newText("(Waiting for response)", 0, 0, native.systemFont, 16)  
myText.x = display.contentCenterX  
myText.y = 120  
local result = ""  
local function getHTML()  
 local function networkListener( event )  
 if ( event.isError ) then  
 myText.text = "Network error!"  
 else  
 myText.text = "See Corona Terminal for response"  
 print ( "RESPONSE: " .. event.response )  
 return event.response  
 end  
 end  
 network.request( "http://www.brainjar.com/java/host/test.html", "GET", networkListener )  
end  
result = getHTML()  
print ("result: "..result)  

lua sockets sample code:

local http = require("socket.http") local ltn12 = require("ltn12") local myText = display.newText("(Waiting for response)", 0, 0, native.systemFont, 16) myText.x = display.contentCenterX myText.y = 120 local results = "" local function getHTML() local r,c,h local response = {} -- Request remote file and save data to local file r,c,h = http.request{ url = "http://www.brainjar.com/java/host/test.html", sink = ltn12.sink.table(response), } myText.text = "See Corona Terminal for response" return table.concat(response,"") end result = getHTML() print("result: "..result) [import]uid: 104085 topic_id: 34371 reply_id: 334371[/import]

This is expected behavior. network.request() is different from http.request in that network.request is an asynchronous call, that is it fires off in the background returning immediately to your program so your app doesn’t stop and wait on the download to finish. http.request is the opposite. It’s going to block until it’s finished and your app freezes while that’s going on. At the point network.request() is called, there is no data to return, so it doesn’t return anything. When your networkListener gets called, you are no longer in the flow of your game and the return statement has no where to return the data too. You just have to pick up and resume your app’s processing inside that networkListener function and manage the data there.
[import]uid: 199310 topic_id: 34371 reply_id: 136599[/import]

Hey Rob,
I was hoping you would respond. I’ve been using your advice on REST for sample code I’m working on for Dropbox. I have no doubt that things are working as planned, but I have a problem that I could use another perspective on.

I adapted the Corona Twitter sample code (REST based) to access Dropbox. I want to use HTTPS so I can use the PLAINTEXT signature method (which Dropbox allows and encourages). So, I had to swap out the lua sockets in the oAuth.lua file that came with the Twitter sample (and can be found in the community code area) with a network.request() that allows HTTPS. After doing this, the rawGetRequest() now returns the result too late to be passed back to the calling function in my Dropbox.lua code.

If I take your advice, I would have to embed my Dropbox code in the oAuth.lua file- or at least that’s all I can think of. My workaround is to use a global variable and a bunch of buttons so that the user dictates the pace of getting through all of the Dropbox API functions (request token, authorize, access token and GET account info).

If you’d like to see my code, it’s all posted at github and you can get to it through this page:
http://developer.coronalabs.com/code/dropbox-rest-sample-code

I’ve spent weeks trying to get this to work and I would much prefer it if there was a way that didn’t involve so much user interaction. [import]uid: 104085 topic_id: 34371 reply_id: 136608[/import]

I’ll have to look at the oAuth code. But I’m thinking that whatever function you call to start the auth process, you pass in a function reference that can then be called back to when network.request is done. But that oAuth code has a bunch of stuff going on and it’s going to take me some time to figure it out.
[import]uid: 199310 topic_id: 34371 reply_id: 136614[/import]

All of the network access takes place in rawGetRequest() and rawPostRequest() in oAuth.lua. If you look through my Dropbox.lua sample code, I walk through the Dropbox API (and therefore oAuth) sequence. I created buttons that take you through each step and all of the buttons are in order:

request token
authorize
access token
GET account info

Also, if you run the code, it does walk you through the process (the buttons are numbered 1-5). However, you do need to watch the results on a device connected by USB with a terminal window and the command:
adb logcat Corona:V *:S

Thanks for your help! [import]uid: 104085 topic_id: 34371 reply_id: 136617[/import]

I think I know what you mean about a callback to the original function. The Twitter sample code demonstrates the concept

Original function (main.lua):

[lua]local TwitterManager = require(“Twitter”)
local callback = {}
– Callback
function callback.twitterSuccess()
print( “Twitter Success” )
statusMessage.textObject.text = “Twitter Success”
end
TwitterManager.tweet(callback, “hello”)[/lua]

Called function (Twitter.lua):

[lua]local function tweet(delegate, msg)
request_response = oAuth.makeRequest(“http://api.twitter.com/1/statuses/update.json”,
params, consumer_key, access_token, consumer_secret, access_token_secret, “POST”)

delegate.twitterSuccess()
end[/lua]

I’m still not entirely sure how to make this work in oAuth.lua, but it is something I hadn’t given consideration to. [import]uid: 104085 topic_id: 34371 reply_id: 136619[/import]

This is expected behavior. network.request() is different from http.request in that network.request is an asynchronous call, that is it fires off in the background returning immediately to your program so your app doesn’t stop and wait on the download to finish. http.request is the opposite. It’s going to block until it’s finished and your app freezes while that’s going on. At the point network.request() is called, there is no data to return, so it doesn’t return anything. When your networkListener gets called, you are no longer in the flow of your game and the return statement has no where to return the data too. You just have to pick up and resume your app’s processing inside that networkListener function and manage the data there.
[import]uid: 199310 topic_id: 34371 reply_id: 136599[/import]

Hey Rob,
I was hoping you would respond. I’ve been using your advice on REST for sample code I’m working on for Dropbox. I have no doubt that things are working as planned, but I have a problem that I could use another perspective on.

I adapted the Corona Twitter sample code (REST based) to access Dropbox. I want to use HTTPS so I can use the PLAINTEXT signature method (which Dropbox allows and encourages). So, I had to swap out the lua sockets in the oAuth.lua file that came with the Twitter sample (and can be found in the community code area) with a network.request() that allows HTTPS. After doing this, the rawGetRequest() now returns the result too late to be passed back to the calling function in my Dropbox.lua code.

If I take your advice, I would have to embed my Dropbox code in the oAuth.lua file- or at least that’s all I can think of. My workaround is to use a global variable and a bunch of buttons so that the user dictates the pace of getting through all of the Dropbox API functions (request token, authorize, access token and GET account info).

If you’d like to see my code, it’s all posted at github and you can get to it through this page:
http://developer.coronalabs.com/code/dropbox-rest-sample-code

I’ve spent weeks trying to get this to work and I would much prefer it if there was a way that didn’t involve so much user interaction. [import]uid: 104085 topic_id: 34371 reply_id: 136608[/import]

I’ll have to look at the oAuth code. But I’m thinking that whatever function you call to start the auth process, you pass in a function reference that can then be called back to when network.request is done. But that oAuth code has a bunch of stuff going on and it’s going to take me some time to figure it out.
[import]uid: 199310 topic_id: 34371 reply_id: 136614[/import]

All of the network access takes place in rawGetRequest() and rawPostRequest() in oAuth.lua. If you look through my Dropbox.lua sample code, I walk through the Dropbox API (and therefore oAuth) sequence. I created buttons that take you through each step and all of the buttons are in order:

request token
authorize
access token
GET account info

Also, if you run the code, it does walk you through the process (the buttons are numbered 1-5). However, you do need to watch the results on a device connected by USB with a terminal window and the command:
adb logcat Corona:V *:S

Thanks for your help! [import]uid: 104085 topic_id: 34371 reply_id: 136617[/import]

I think I know what you mean about a callback to the original function. The Twitter sample code demonstrates the concept

Original function (main.lua):

[lua]local TwitterManager = require(“Twitter”)
local callback = {}
– Callback
function callback.twitterSuccess()
print( “Twitter Success” )
statusMessage.textObject.text = “Twitter Success”
end
TwitterManager.tweet(callback, “hello”)[/lua]

Called function (Twitter.lua):

[lua]local function tweet(delegate, msg)
request_response = oAuth.makeRequest(“http://api.twitter.com/1/statuses/update.json”,
params, consumer_key, access_token, consumer_secret, access_token_secret, “POST”)

delegate.twitterSuccess()
end[/lua]

I’m still not entirely sure how to make this work in oAuth.lua, but it is something I hadn’t given consideration to. [import]uid: 104085 topic_id: 34371 reply_id: 136619[/import]

The delegate thing is a little different than how I would have expected this to happen, but it does work. It’s more of an object oriented approach. Basically “delegate” is a big table that holds three different call back functions to handle twitterSuccess, twitterFailue and one other. For your purpose, you can communicate back with your calling function however works for you. [import]uid: 199310 topic_id: 34371 reply_id: 138522[/import]

The delegate thing is a little different than how I would have expected this to happen, but it does work. It’s more of an object oriented approach. Basically “delegate” is a big table that holds three different call back functions to handle twitterSuccess, twitterFailue and one other. For your purpose, you can communicate back with your calling function however works for you. [import]uid: 199310 topic_id: 34371 reply_id: 138522[/import]