Jump to content

[TOPIC: topicViewTemplate]
[GLOBAL: userSmallPhoto]
Photo

[RESOLVED - Yay] I can't get a super basic HTTP POST network request to work
Started by Naomi Aug 06 2012 10:20 AM

- - - - -
47 replies to this topic
[TOPIC CONTROLS]
Page 2 of 2 1 2
This topic has been archived. This means that you cannot reply to this topic.
[/TOPIC CONTROLS]
[modOptionsDropdown]
[/modOptionsDropdown]
[reputationFilter]
[TOPIC: post.html]
#26

xnailbender

[GLOBAL: userInfoPane.html]
xnailbender
  • Contributor

  • 360 posts
  • Corona SDK

Hey there, I'll break it out. Going to take me some time though.

I haven't tried adding params to the line, maybe it would accept it, along with the body table.

Nail
uid: 106779 topic_id: 29545 reply_id: 118801


[TOPIC: post.html]
#27

xnailbender

[GLOBAL: userInfoPane.html]
xnailbender
  • Contributor

  • 360 posts
  • Corona SDK

Hey there, here's the code.
This is from Satheesh's validate IAP receipt and PHP...

lua
local function start(params)
	
	local listener = params.listener or function(event) end 
	local testing = params.testing
	local link = testing and "https://sandbox.itunes.apple.com/verifyReceipt" 
								or "https://buy.itunes.apple.com/verifyReceipt"
	
	local receipt = params.receipt or "<>"
	local password = params.password or nil
	local serverValidation = params.serverValidation
	local serverLink = params.serverLink
	
	local postData
	
	if serverValidation then 
		postData = preparePostData(receipt,{serverValidation = true})
		postData = "receipt="..postData.."&testing="..(testing and 1 or 0)
		link = serverLink
	else 
		postData = preparePostData(receipt,{password = password})
	end
		
	local function localListener(event)
		local  response = event.response
		local decoded = json.decode(response)
		print("localListener FLAG after json.decode")
		print("decoded == ", decoded ) 
		print("after if decoded then FLAG1")
		if type(decoded) == "table" then 			
			
			event.iTunes_StatusCode = decoded.status 
			print("decoded.status from validate.lua == ", decoded.status )
			event.iTunes_Response = decoded
			event.iTunes_StatusCodeDescription = errorMap[tostring(event.iTunes_StatusCode)]
		end        	
		
		listener(event)
	end 

	network.request(link,"POST",localListener,{body=postData})

end 

PHP
<?php

$hex = $_POST['receipt'];
$testing = $_POST['testing'];
$password = "SecretPasswordHere";

if ($testing == 1)
	$url = 'https://sandbox.itunes.apple.com/verifyReceipt';
else 
	$url = 'https://buy.itunes.apple.com/verifyReceipt';
	
$postData = json_encode
(
array(
	'receipt-data' => $hex,
	'password' => $password,
	)
);

function do_post_request($url, $data, $optional_headers = null)
{
  $params = array('http' => array(
              'method' => 'POST',
              'content' => $data
            ));
  if ($optional_headers !== null) {
    $params['http']['header'] = $optional_headers;
  }
  $ctx = stream_context_create($params);
  $fp = @fopen($url, 'rb', false, $ctx);
  if (!$fp) {
    throw new Exception("Problem with $url, $php_errormsg");
  }
  $response = @stream_get_contents($fp);
  if ($response === false) {
    throw new Exception("Problem reading data from $url, $php_errormsg");
  }
  return $response;
}

$response = do_post_request($url, $postData);
echo $response;
?>

It works. I should have studied it more today while fumbling around, but my App went LIVE in the App Store this afternoon. :) Problem was the IAP did NOT work!!! OMG!!!

As this is my first app, I had no idea what was wrong. I figured it must the PHP above was using the Sandbox URL, so I commented out the "if" and Sandbox URL and it WORKED!!!

Do I have to learn something EVERY minute while doing this??!!??

GL
Nail
uid: 106779 topic_id: 29545 reply_id: 118803


[TOPIC: post.html]
#28

budershank

[GLOBAL: userInfoPane.html]
budershank
  • Contributor

  • 358 posts
  • Corona SDK

@Naomi, I played around with it a bit this morning and figured some things out. Most likely the issue is that your data is making it to the web server but then the webserver/php/your webpage is having issues reading the body data properly. What ends up happening is your post data essentially gets dumped. Try this:

Your PHP File:

echo var_dump(getallheaders());
echo var_dump($_REQUEST);
//echo var_dump($HTTP_RAW_POST_DATA);
echo "Thats all folks"
?>


Basically the first thing dumps out all the header information. This was key as i was able to see that the Content_Length was actually correct so I knew my data was getting there. The HTTP_RAW line is commented out. From here I could actually see the body data coming in even though PHP ended up dumping it. The reason why it is commented out is you would need to enable "always_populate_raw_post_data" in your php.ini. Since you are probably using a shared host I'm not sure how you do that.

And here is the corona code, slightly different because I'm not bothering with JSON atm.

local URL = "http://mywebsite.com/myphp.php"local function networkListener( event )        if ( event.isError ) then                print( "Network error!")        else                print ( "RESPONSE: " .. event.response )        endend local function sendRequest(set_email, set_user)    local postdata = {}    local param = {}    param.username = set_user    param.email = set_email    postdata.body = "email="..set_email.."&user="..set_user    network.request( URL, "POST", networkListener, postdata)end sendRequest("myemail@myweb.com", "mynickname")


Main different as you can see is 1. I am not defining a header and 2. I'm not using json. Essentially those two things are the root cause of your issue. Somewhere along the line the PHP is trying to parse out your data from JSON format and it is unable to, hence no data being available. I figure at this point you can probably dig into it. I would compare the JSON data on the Corona side to a known working example of JSON php can handle properly. If you really can't find the solution you could forego using JSON and just building your body in the format I used, which is "email=bob@bob.com&user=bobby".

Unfortunately I am currently on a windows machine and you apparently can't copy from the command window in Windows, so I can't give an example of the output without a bunch of typing that I am sure I would mess up.
uid: 147305 topic_id: 29545 reply_id: 118877


[TOPIC: post.html]
#29

Naomi

[GLOBAL: userInfoPane.html]
Naomi
  • Corona Geek

  • 2,303 posts
  • Corona SDK

Nail@xnailbender, thank you for posting the content of postData. I do plan on learning how Satheesh's validate IAP receipt work (and use it too) at some point. I really appreciate it.

And @budershank, OMG, it sounds like you figured this out! I will look into how I may enable "always_populate_raw_post_data" in the php.ini. And yes, I'm using a shared host. I'll post back with result. Thank you so much for investigating this far. I really appreciate it!

Naomi
uid: 67217 topic_id: 29545 reply_id: 118883


[TOPIC: post.html]
#30

xnailbender

[GLOBAL: userInfoPane.html]
xnailbender
  • Contributor

  • 360 posts
  • Corona SDK

Naomi wrote: I do plan on learning how Satheesh's validate IAP receipt work (and use it too) at some point
----------------------------

When I first tried to use Satheesh's IAP, it did not work. I didn't even know what "echo" did at that time and was when I first explored PHP.

As I was debugging why it didn't work, I concluded the problem must be in the PHP, and it was.

Towards the top of the IAP PHP code there is a line of PHP code that causes the glitch.

echo $hex , I believe is what it is. When I commented out the line, the PHP worked.

As I stated above, when my app went live yesterday, the IAP didn't work. The code was still passing the testing URL. Haven't figured out why yet, but when I removed it from the PHP, my IAP's started working. I'm so happy I was able to fix, or at least, patch the problem by altering my PHP and didn't require another app submission immediately. :)

You'll want to keep both these issues in mind when you integrate the IAP verification.

Regarding POST, I think budershank is right. Our PHP is not parsing the header and body correctly. I needed the header info in my other PHP scripts and didn't need to parse the body. I would like to be able to include both the header and body in the param though. There is some tricky PHP that will be required to do this I'm afraid. It seems I can get either the header, or I can get the body out of the param, but not both yet.

Integrating PHP into the app has so many uses, I amazed how little it's been discussed here at Corona.

Nail
uid: 106779 topic_id: 29545 reply_id: 118892


[TOPIC: post.html]
#31

Naomi

[GLOBAL: userInfoPane.html]
Naomi
  • Corona Geek

  • 2,303 posts
  • Corona SDK

Nail @xnailbender, thank you for the heads up on what to look out for with the IAP validation code.

As per @budershank's discovery (thank you so much for it), I'm working on getting PHP side to cooperate so that it can receive simple POST from Corona app. With my shared host, I need to create php.ini file before I can change the setting.

But, geez, how do people go about creating php.ini file? I looked for example php.ini, and this one frightens me (a pure fear of unknown & unfamiliar.) Also, it says here that:

To protect the php.ini file, you can add these lines to your .htaccess file:
< Files php.ini >
order allow,deny
deny from all
< /Files >

So, I looked for .htaccess file example and this one also frightens me. Ugh.

Does anyone have a very basic php.ini file and .htaccess file that I may tweak? I really don't want to change anything except for enabling the "always_populate_raw_post_data" and making sure that the php.ini that I add to my site will be protected.

Naomi
uid: 67217 topic_id: 29545 reply_id: 118898


[TOPIC: post.html]
#32

budershank

[GLOBAL: userInfoPane.html]
budershank
  • Contributor

  • 358 posts
  • Corona SDK

You can probably just upload the php.ini without editing the htaccess(though im not 100 percent certain on that). Here is the ini i used. For the most part it's default values except for the raw thing(and i think global variables are turned on). You could also just install the same version of PHP that your server uses. It will create an ini file that you can then edit and upload.

http://www.neverrecycle.com/share/php.zip
uid: 147305 topic_id: 29545 reply_id: 118904


[TOPIC: post.html]
#33

Naomi

[GLOBAL: userInfoPane.html]
Naomi
  • Corona Geek

  • 2,303 posts
  • Corona SDK

Thank you, @budershank! I'll use the php.ini file you posted. (I've also asked my hosting provider if they could create one for me that duplicates their default setting.) I'm not sure about the htaccess file, so for now I won't include it (but maybe down the road once I become a little more acquainted with it and feel a little more comfortable with it.)

Thanks again.

Naomi

Edit: @budershank, I uploaded the php.ini file, and did the very basic version you posted on #27 above, and I get an error like this on terminal (see below). Maybe the php.ini file you sent me isn't compatible with my setup. Dunno. I'll look into the error doc. (I'll also post back if/when I get the hosting provider send me their default php.ini file.) Anyhow, at least it's no longer a blank response -- so I'm getting somewhere.

[text]
RESPONSE: "http://www.w3.org/TR/html4/strict.dtd">




500 – Internal Server Error


500 – Internal Server Error


The page you requested is currently unavailable. Please try again later.


If you are the website owner, please see
http://docs...#error-500-internal-server-error
documentation for more information and possible steps to resolve the problem.




[/text]
uid: 67217 topic_id: 29545 reply_id: 118913


[TOPIC: post.html]
#34

budershank

[GLOBAL: userInfoPane.html]
budershank
  • Contributor

  • 358 posts
  • Corona SDK

Do you know which version of PHP is being used?
uid: 147305 topic_id: 29545 reply_id: 118923


[TOPIC: post.html]
#35

Naomi

[GLOBAL: userInfoPane.html]
Naomi
  • Corona Geek

  • 2,303 posts
  • Corona SDK

Hey @budershank, it's using PHP 5.4 version. And the error log says:

[text]
[Wed Aug 08 19:20:11 2012] [warn] [client xx.xxx.xxx.x] Not GET request: 2.
[Wed Aug 08 19:20:11 2012] [warn] [client xx.xxx.xxx.x] Not GET request: 2.
[Wed Aug 08 19:20:11 2012] [error] [client xx.xxx.xxx.x] Premature end of script headers: php54.cgi
[/text]

Does this mean anything to you? Also, does it also sound like as if PHP side really wants GET to you?

Naomi
uid: 67217 topic_id: 29545 reply_id: 118925


[TOPIC: post.html]
#36

budershank

[GLOBAL: userInfoPane.html]
budershank
  • Contributor

  • 358 posts
  • Corona SDK

Ah, well my ini is from 5.1. I would disregard the errors for now as it most likely is an issue between ini files. If you can't find a php.ini for 5.4 itself you can just install php on your own system real quick and then take that one. Seems like a round about way but it works.
uid: 147305 topic_id: 29545 reply_id: 118931


[TOPIC: post.html]
#37

Naomi

[GLOBAL: userInfoPane.html]
Naomi
  • Corona Geek

  • 2,303 posts
  • Corona SDK

OMG! @budershank, out of desperation (since my hosting service hasn't gotten back to me and I was feeling rather experimental), I did this (thinking it couldn't hurt) and it worked!!!!

1) Open a new text file (just a plain simple text file with nothing in it.)

2) Add this single line to the text file: always_populate_raw_post_data = 1

3) Save this single line text file as php.ini

4) Upload the file to root-level of my server account (where I would upload my php file)

After I did this simplest thing of all, it returned the following to my simulator terminal:
[text]
RESPONSE: array(2) {
["email"]=>
string(17) "myemail@myweb.com"
["user"]=>
string(10) "mynickname"
}
[/text]

This is all it needed. Wowowow. (Spending hours on something so simple is what happens when I've got no basic knowledge of anything PHP or server setup.) Now I can forge ahead. A bit of struggling was a good thing. I feel less frightened and more in control. All is well.

Thank you all for all your help.

Cheers,
Naomi
uid: 67217 topic_id: 29545 reply_id: 118956


[TOPIC: post.html]
#38

Naomi

[GLOBAL: userInfoPane.html]
Naomi
  • Corona Geek

  • 2,303 posts
  • Corona SDK

And here's the very simple version that works for me (see below). Cheers!

Naomi

-- LUA side
local mime = require("mime")
local json = require("json")
local URL = "http://mywebsite.com/myphp.php"
local function networkListener( event )
        if ( event.isError ) then
                print( "Network error!")
        else
                print ( "RESPONSE: " .. event.response )
        end
end
local function sendRequest(set_email, set_user)
    local postdata = {}
    set_email = mime.b64(set_email)
    set_user = mime.b64(set_user)
    postdata.body = "email="..set_email.."&user="..set_user
    network.request( URL, "POST", networkListener, postdata)
end
sendRequest("myemail@myweb.com", "mynickname")

-- PHP side
<?php
    $email = base64_decode($_REQUEST['email']);
    $username = base64_decode($_REQUEST['username']);
    $result = array();
    $result["result"] = 'Received';
    $result["message"] = 'The email address we received is ' . $email . ' and username received is ' . $username;
    echo json_encode($result);
?>

-- php.ini file with single line of text
always_populate_raw_post_data = 1

-- terminal output:
RESPONSE: {"result":"Received","message":"The email address we received is myemail@myweb.com and username received is mynickname"}
uid: 67217 topic_id: 29545 reply_id: 118963


[TOPIC: post.html]
#39

Omnigeek Media

[GLOBAL: userInfoPane.html]
Omnigeek Media
  • Corona Geek

  • 2,975 posts
  • Corona SDK

I wish I had seen this post earlier.

The basic problem that you're running into (which your solution works for) is that PHP is expecting a mime type to be set in the POST headers. Corona SDK does not set that variable and many webhosts end up returning empty data to $_POST[].

Basically you need to add a field to your headers that get sent that works out to be:

headers = {}

headers["Content-Type"] = "application/x-www-form-urlencoded"
headers["Accept-Language"] = "en-US"

body = "Your Post data"

local params = {}
params.headers = headers
params.body = body

network.request( "https://yourwebsite.com/yourPHPscript.php", "POST", networkListener,  params)

And that should work without having to change your PHP.ini settings.
uid: 19626 topic_id: 29545 reply_id: 118964


[TOPIC: post.html]
#40

Naomi

[GLOBAL: userInfoPane.html]
Naomi
  • Corona Geek

  • 2,303 posts
  • Corona SDK

OMG, Rob @robmiracle, you are right. I have tried so many different headers, body and etc., etc., with no luck -- and it turns out it was only because of the json-encoded params table bringing everything down, or so it seems.

This now works without php.ini file on root-level, with the exact same PHP script I posted on #37 above:
-- LUA side
local mime = require("mime")
local json = require("json")
local URL = "http://mywebsite.com/myphp.php"
local function networkListener( event )
        if ( event.isError ) then
                print( "Network error!")
        else
                print ( "RESPONSE: " .. event.response )
        end
end
local function sendRequest(set_email, set_user)
    local postdata = {}
    set_email = mime.b64(set_email)
    set_user = mime.b64(set_user)
    local headers = {}
    headers["Content-Type"] = "application/x-www-form-urlencoded"
    headers["Accept-Language"] = "en-US"
    local postdata = {}
    postdata.headers = headers
    postdata.body = "email="..set_email.."&username="..set_user
    network.request(URL, "POST", networkListener, postdata)
end
sendRequest("myemail@myweb.com", "mynickname")

uid: 67217 topic_id: 29545 reply_id: 118970


[TOPIC: post.html]
#41

budershank

[GLOBAL: userInfoPane.html]
budershank
  • Contributor

  • 358 posts
  • Corona SDK

@Naomi, yay!

@rob, i wish you had seen this post earlier too. I hesitated to jumping in because I figured you would of shown up with better answers :)

I will say though, I tried setting the headers(and so did naomi) without any love. I can't remember the few I tried aside from the application/json but i tried one just as text. Despite doing that, when I inspected the headers on the response it came in as the content type you gave. Maybe if I had explictly set it to application/x-www-form-urlencoded it would have made a difference. Anyways, I don't need to do anything with it so I guess i'm not that interested in checking it out :)
uid: 147305 topic_id: 29545 reply_id: 118972


[TOPIC: post.html]
#42

Naomi

[GLOBAL: userInfoPane.html]
Naomi
  • Corona Geek

  • 2,303 posts
  • Corona SDK

BTW, Rob @robmiracle, do you know how I may send json encoded data via HTTP POST to web-server? I will eventually need to send a big lua table (which is basically a game variable table) that I want to send back & forth, but it doesn't seem like I can do this if I json.encode the lua table and send it as param.body via HTTP POST method.

Or, am I missing something super simple still?

Naomi
uid: 67217 topic_id: 29545 reply_id: 118973


[TOPIC: post.html]
#43

Naomi

[GLOBAL: userInfoPane.html]
Naomi
  • Corona Geek

  • 2,303 posts
  • Corona SDK

So, when I json.encode the postdata.body, the var_dump($_REQUEST) returns:

[text]
RESPONSE: array(2) {
[""email"]=>
string(24) "bXllbWFpbEBteXdlYi5jb20="
["username"]=>
string(17) "bXluaWNrbmFtZQ==""
}
[/text]

I'll eventually have to learn how to parse this array properly so that I can use the data properly -- but for now (unless someone knowledgeable would jump in and let me know how to parse this), I'll focus on email validation, existing username check, etc., etc. Got to forge ahead one step at a time. There's still a lot to do and learn after all.

Cheers,
Naomi
uid: 67217 topic_id: 29545 reply_id: 118976


[TOPIC: post.html]
#44

Omnigeek Media

[GLOBAL: userInfoPane.html]
Omnigeek Media
  • Corona Geek

  • 2,975 posts
  • Corona SDK

I'm guessing that data is base64 encoded (and if you followed my blog post on using REST api services, it probably is...)

You simply need to decode the data.

local mime = require("mime")

local username = mime.unb64(response.username)
local email = mime.unb64(response.email)

uid: 19626 topic_id: 29545 reply_id: 118982


[TOPIC: post.html]
#45

Naomi

[GLOBAL: userInfoPane.html]
Naomi
  • Corona Geek

  • 2,303 posts
  • Corona SDK

Thank you, Rob @robmiracle! Yes, I did follow your blog on REST api services. It's a great tutorial. Super helpful.

About decoding, I'm wondering how I may decode the $_REQUEST that PHP side receives.
-- for example, when I encode postdata.body like this in Corona/LUA side
postdata.body = json.encode("email="..set_email.."&username="..set_user)

-- and when my PHP side looks like this
<?php
   echo var_dump($_REQUEST);
?>

-- it returns the following on simulator terminal
RESPONSE: array(2) {
  [""email"]=>
  string(24) "bXllbWFpbEBteXdlYi5jb20="
  ["username"]=>
  string(17) "bXluaWNrbmFtZQ==""
}

What I would like to know is how I may parse the email and username on PHP side so that I may handle it (such as checking to see if the username is already taken, or it's okay to be inserted into the database, etc). When I don't json-encode the postdata.body, I can get what I need and handle the data accordingly, because all I need to do then is
<?php
$email = base64_decode($_REQUEST['email']);
$username = base64_decode($_REQUEST['username']);
?>
But I don't know how I may pull out what I need from $_REQUEST when the json-encoded postdata arrives to PHP. I know I have still much to learn. I'd be grateful if you could show me how I may do this anyhow.

Thanks again.

Naomi
uid: 67217 topic_id: 29545 reply_id: 118984


[TOPIC: post.html]
#46

Omnigeek Media

[GLOBAL: userInfoPane.html]
Omnigeek Media
  • Corona Geek

  • 2,975 posts
  • Corona SDK

You don't want to json encode the data you send, specially when its this simple:

postBody="email="..set_email.."&username="..set_user

Is all you need.

Webservers expect Key Value pairs. For GET requests, they are on the URL and start after the question mark like:

http://someserver.com/somescript.php?key1=value1&key2=value2&key3=value3

Each Key-Value pair is separated by an &.

For POST requests, the data is part of the post body:

postBody = "key1=value1&key2=value2&key3=value3"

Then in PHP, you would use the $_POST[] array:

echo($_POST["key1"]);
echo($_POST["key2"]);
echo($_POST["key3"]);

Now if you have to send some really complex data, like tables inside of tables, you might want to json.encode that table and then it would be something like:

in your app:

postBody = "data=" .. mime.b64(json.encode(someTableofData))

make your request.

Then in your PHP script:

$data = json_decode(base64_decode($_POST["data"]));

Now in your PHP script you would have an associative array (the same thing as a Lua table) that matches key for key, value for value what you started with in your app.

But if you're just passing in a couple of variables, no need to add the JSON complexity.
uid: 19626 topic_id: 29545 reply_id: 118987


[TOPIC: post.html]
#47

Naomi

[GLOBAL: userInfoPane.html]
Naomi
  • Corona Geek

  • 2,303 posts
  • Corona SDK

Hey, Rob @robmiracle, thank you so much for the detailed explanation!!

Yes, I want to be able to send a lua table off to PHP. The reason why I tried to json.encode the simple data (just a couple of simple string variables) was because I always feel it's important for me to understand the mechanics of things at the most basic level before tackling something more complex.

I'll examine what you posted above when I do work on seinding a lua table (with lots of variables with additional tables nested inside them).

Thanks again! I so appreciate all your help.

Naomi
uid: 67217 topic_id: 29545 reply_id: 118989


[TOPIC: post.html]
#48

BeyondtheTech

[GLOBAL: userInfoPane.html]
BeyondtheTech
  • Contributor

  • 477 posts
  • Corona SDK

Nice, I hope this thread gets simplified and turned into a Corona Tutorial. My head is spinning and I know it's something good to share.
uid: 6084 topic_id: 29545 reply_id: 120254



[topic_controls]
Page 2 of 2 1 2
 
[/topic_controls]