Problems processing HTTP POST - php

I've worked with PHP for many years and have setup many HTML forms which are then processed by another php page to insert a record into a database setting the POST parameters into individual fields.
I'm now working with a new webservice that is POSTing data to one of our PHP pages and we've been unable to parse out the POST parameters. I setup a test html form to mimic the POST and that works successfully.
I've been going through the IIS logs (Server is Windows Server 2008 R2 Standard Edition running IIS 7.5 and PHP 5.3.8) and have installed Microsoft Network Monitor to capture details about the POST data. Here's an excerpt showing the payload details for the Webservice and my HTML form:
Webservice:
- client in IIS Log appears as: Apache-HttpClient/4.0.1+(java+1.5)
payload: HttpContentType = NetmonNull
HTTPPayloadLine: inReplyToId=MG1133&to=61477751386&body=Test&from=61477751386&messageId=166652576&rateCode=
My HTML Form:
payload: HttpContentType = application/x-www-form-urlencoded
inReplyToId: MG1133
to: 61477751386
body: Test
from: 61477751386
messageId: 166594397
In the PHP page we're using a series of:
if(isset($_POST['inReplyToId']) && $_POST['inReplyToId'] !== '' ) {
$request->setField('ReplyToID', $_POST['inReplyToId']);
}
to grab the POST values and set them into fields as part of creating the new record in the database. When the Webservice does a POST none of the POST values are being set into the fields - the record is created but with empty field values.
When we perform complete the html form everything comes through as expected.
I'm not sure where to go next with troubleshooting this - I can see the different HttpContentType and the different structure to the payload but not sure whether this is the issue and what action I need to take.

Using file_get_contents('php://input') finally allowed me to see the POST data. I could then use parse_str() to generate variables from the string:
$postText = file_get_contents('php://input');
parse_str($postText);
if(isset($inReplyToId) && $inReplyToId !== '' ) {
$request->setField('_kf_GatewayMessageID', $inReplyToId);
}
and so on.

Related

CakePHP 4 - setting request data

We have a CakePHP 3.x app which we've updated to the latest CakePHP 4.x. As part of this work we've also changed from PHP 7 to PHP 8.
Whilst testing the app we noticed a feature that had stopped working.
The app is a searchable database and is integrated with Redis for caching. One of the features means that the users search is retained between page reloads. This works by writing serialized form data to Redis, and then re-populating that back into the input fields in the template. This means the user sees the search criteria they entered; they do not need to re-enter their search criteria when the page is refreshed.
The code in the CakePHP 3.x app which re-populated the input form fields looked like this:
$form_fields = ['f1', 'f2', 'f3'];
The $form_fields array contains the names of the form input's in the template. As an example:
<input type="text" name="f1">
The next part of the code re-populates the form. In this case $user_search is an array of data that has been obtained and unserialized from Redis. As an example we might have $user_search['f1'] and $user_search['f3'] containing Redis data; f2 is unpopulated because the user didn't search using that field.
foreach ($form_fields as $form_field) {
$this->request->getData()[$form_field] = (isset($user_search[$form_field])) ? $user_search[$form_field] : '';
}
In the Cake 3.x app the above works fine. When the page is reloaded the form fields are set due to setting the request data, e.g. in the loop above, it evalulates to:
$this->request->getData()['f1'] = 'foo';
$this->request->getData()['f3'] = 'bar';
This means the request data has "foo" as f1 and "bar" as f3. There is nothing in f2 so it gets set to an empty string as per the : ''; condition.
In the CakePHP 4.x app this does not work; all form fields are unpopulated on page reload. I've confirmed that they are not being set to empty strings by modifying the : ''; condition mentioned above to : 'test'; and ensured the string "test" is not being shown in the fields.
The data exists in Redis and I've confirmed that $user_search contains what's shown above - in other words the data is not missing so we've ruled that out.
When I read over https://book.cakephp.org/4/en/controllers/request-response.html I can't see an example of setting request data. There is a method getData() which does what you'd expect - it reads the request data.
Is there a way to set the request data in Cake 4.x such that the above code would work?
In vanilla PHP what we're doing is equivalent to
$_POST['f1'] = 'foo';
$_POST['f2'] = ''; // empty string as no value set by user
$_POST['f3'] = 'bar';
AFAIK this was - and still is - valid in PHP; you can set/overwrite request data with anything in your code. If this is wrong please advise what I should be doing instead.
For clarity the reason we are setting request data in this manner is because the search for works via an ajax call. When the user enters their search criteria initially, the page has not been reloaded so the form fields appear to be populated correctly. This issue occurs on page reload. In that instance we want to repopulate the form with the values they entered prior to the page being reloaded.
The function you're looking for is withData. Remember that the request object is immutable, so you need to assign the result of that function call back into the request object, e.g. with $this->setRequest($this->getRequest()->withData('f1', 'foo')->withData('f3', 'bar')).

Get values through post method from URL

I am trying some code to get value from URL through post method and search database table for that value and get info from the database and encode it into JSON response.
Here is my code :
<?php
//open connection to mysql db
$connection = mysqli_connect("localhost","root","","json") or die("Error " . mysqli_error($connection));
if (isset($_POST['empid'])) {
$k = $_POST['empid'];
//fetch table rows from mysql db
$sql = "select `salary` from tbl_employee where `employee_id` = $k ";
} else {
//fetch table rows from mysql db
$sql = "select `salary` from tbl_employee";
}
//fetch table rows from mysql db
$result = mysqli_query($connection, $sql) or die("Error in Selecting " . mysqli_error($connection));
//create an array
$emparray = array();
while($row =mysqli_fetch_assoc($result))
{
$emparray[] = $row;
}
echo json_encode($emparray);
//close the db connection
mysqli_close($connection);
?>
I used Postman extension on Chrome and pass the values but it is not returning. Instead it is returning the else part.
Postman Screenshot
Looking at your screen shot, you have not passed body key values, instead you passed params.
Click on Body Tab and then pass key & value pair.
As per your screenshot you are sending your empid through query parameter so you need to access that as follows
<?php
if (isset($_GET['empid'])) {
echo $_GET['empid'];
}else{
// else part
}
also for that you need to Request Url in Postman using GET method.
But as you have stated that you want to send empid through POST in postman, you have to send it through form-data in Postman and access it as $_POST["empid"];. following is the screenshot for your reference
else there is another option where you can send the POST data through body as row json and access it as
$rawPostData = file_get_contents('php://input');
$jsonData = json_decode($rawPostData);
and $post will contain the raw data. And you can send it through postman as in following screenshot.
You have to set the Body to "x-www-form-urlencoded" and adding the variables to be posted
Or try this SO question, its already been answered
I replicated the code and db on my system to figure out the problem. I also added some lines of code before if (isset($_POST['empid'])) { for diagnostics sake:
$method = $_SERVER['REQUEST_METHOD'];
echo $method."<br/>";
The application file is index.php deployed in json directory inside webroot.
When I send any request to http://localhost/json directory (either POST/GET), Apache redirects the request as a GET request to index.php (as configured in my Apache config file). I assume this is what you're experiencing.
But when I send the request to http://localhost/json/index.php, the request is accurately received and processed.
Therefore, I would say the solution is that you need to specify the php file and also set the empid parameter as part of the body in Postman (not as part of the url).
I think you should also check the post if emptyif (isset($_POST['empid']) AND ($_POST['empid']) != ""). to allow php to execute the line before else.Sometimes programming becomes unpredictable.
use if(isset($_REQUEST['empid'])) to test in POSTMAN...
Then use if(isset($_POST['empid'])) to test directly from app...
have a look Issue in POSTMAN https://github.com/postmanlabs/postman-app-support/issues/391
To get the value of a variable from the URL(query string), you need to use either $_GET or $_REQUEST.$_POST represents data that is sent to the script via the HTTP POST method.
So, in your code you just need to do this :
$_REQUEST['empid'] instead of $_POST['empid']
In POST method the data is sent to the server as a package in a separate communication with the processing script. Data sent through POST method will not visible in the URL.
Confirm that in postman Content-Type should be application/x-www-form-urlencoded in request header.
Postman reference doc : https://www.getpostman.com/docs/requests
Hey it sounds like you are just needing to do a GET request to your DB.
You are more than welcome to send in variables via a GET request as well.
GET http://localhost/json?empid=3
You can then get data from your GET request like so $_GET['empid']
I suggest a GET request because I see your not actually posting any data to your server, your just handing in a variable in which you want to use to query with.
I do understand that GET requests are less secure, but in your scenario your POST just doesn't seem to want to work. So a different tack might do you justice.
If you want a value from the URL, you need to use $_GET["empid"] instead $_POST["empid"]
Submitting a form through POST method
By post method of form submission, we can send number or length of data. Sensitive information like password does not get exposed in URL by POST method, so our login forms we should use POST method to submit data. This is how we collect data submitted by POST method in PHP
$id=$_POST['id'];
$password=$_POST['password'];
Collecting data submitted by either GET or POST method
If a page is receiving a data which can come in any one of the method GET or POST then how to collect it ? Here we are not sure how to collect the data. So we will use like this.
$id=$_REQUEST['id'];
$password=$_REQUEST['password'];
Looking at the URL you are requesting, you are sending a GET value within your POST request.
http://localhost/json?empid=3
As you can see here, the url holds the empid variable and so the is send to the server as beeing a GET variable ($_GET)
Use $_GET['empid'] to access this variable, while using $_POST to access the other variables.
You could also use $_REQUEST to access both GET and POST data by the same global.

Database Post to another Database

I'm currently a front end developer for a website which lets users sign up and then make purchasing of items.For transactions, I'm using an API which the payment gateway company provided but when passing data via AJAX certain sensitive data are exposed for the users to see. I was wondering if there is a way that I can pass my parameters to a database (which I'm going to create), and then let the database do the AJAX posting so sensitive parameters can be hidden from the users. Also the database will store the response from the callback.
The ajax doesn't have to post to a database unless you want it to, but even then the database would not be what posts the data to a remote api. It's up to your backend php to do that.
Using jquery for the ajax call you would use something like:
$.getJSON("your_backend.php", function(result){
//whatever you want to do with the json returned from the remote site.
}
In your_backend.php:
<?php
$user = "user name";
$key = "key"
$headers = array(
'http'=>(
'method'=>'GET',
'header'=>'Content: type=application/json \r\n'.
'user:$user \r\n'.
'key:$key'
)
)
$context = stream_context_create($headers)
$url_returns = file_get_contents($api_url, false, $context);
echo $url_returns
?>
I haven't debugged this, so it won't work until you go through it, but it should give you an idea about how to proceed. Depending on how complex the connection is with the remote api you may need to use the cURL library for php instead of the file_get_contents.
If you want to save the information in your database you would write an insert statement from the backend php.

NetSuite - Accept webhook POST data to create record using ASP.NET or PHP

We have a lead generation form at Unbounce.com that is capturing lead data. They have a webhook that can transmit the data via POST to any URL that can accept it and process it. We would like to build a page that accepts this data and processes it in NetSuite (probably via the SuiteScript API's, but not sure). http://www.netsuite.com/portal/developers/resources/APIs/Dynamic%20HTML/SuiteScriptAPI/MS_SuiteScriptAPI_WebWorks.1.1.html
Variables To Get From POST
The following variables will be passed from the form in this order to the NetSuite processing page:
prog
first_name
last_name
email
parents_email
i_am_a_
phone_number
parents_phone_number
comment
Additional Page Variables To Attempt To Grab
Reading the example code below it looks like we can grab and store a few additional items. If so it would be good to store them in the CRM in the visitors profile for future reference:
page_id
page_url
variant
REQUEST FOR SAMPLE CODE
Since our preferred development enviornment is ASP.NET, can you provide sample code that can accept POST data from a webhook and create a new CRM record within our NetSuite account?
SAMPLE PHP CODE TO GET DATA FROM POST
Example code can be found at http://support.unbounce.com/entries/307685-how-does-the-form-webhook-work
If this were a PHP page you would grab the variables in the following fashion:
// This is a sample PHP script that demonstrates accepting a POST from the
// Unbounce form submission webhook, and then sending an email notification.
function stripslashes_deep($value) {
$value = is_array($value) ?
array_map('stripslashes_deep', $value) :
stripslashes($value);
return $value;
}
// First, grab the form data. Some things to note:
// 1. PHP replaces the '.' in 'data.json' with an underscore.
// 2. Your fields names will appear in the JSON data in all lower-case,
// with underscores for spaces.
// 3. We need to handle the case where PHP's 'magic_quotes_gpc' option
// is enabled and automatically escapes quotation marks.
if (get_magic_quotes_gpc()) {
$unescaped_post_data = stripslashes_deep($_POST);
} else {
$unescaped_post_data = $_POST;
}
$form_data = json_decode($unescaped_post_data['data_json']);
// If your form data has an 'Email Address' field, here's how you extract it:
$email_address = $form_data->email_address[0];
// Grab the remaining page data...
$page_id = $_POST['page_id'];
$page_url = $_POST['page_url'];
$variant = $_POST['variant'];
However I don't know the code to use to get it into NetSuite. After reviewing the SuiteScript API from NetSuite it looks like we should be using nlobjRequest or nlapiRequestURL, but I have zero knowledge on how to integrate this with the sample PHP page above.
Thanks for all your help for a NetSuite noob.
You would need to create a RESTlet in NetSuite. You can find the documentation on NetSuite's Help Guide. RESTlets are part of NetSuite's SuiteScript API. They are written as JavaScript (of course, using the APIs provided by NetSuite).
When you create a RESTlet, you will be given a URL. Which you should use for your Unbounce web hook. Your RESTlet should parse the JSON data being passed by Unbounce.com.

asp.net form submission problem

I need to accomplish the following and need help with #2 below
My site has a page with form and the submitted form data needs to be written to a database on my site.
After it is written to the database, the same data submitted on the form needs to be sent to a page that processes it on another site so as if the form submission came from a page on that other site. The page that processes it on the other site is a php page.
It's a bit unclear, but my guess is that you're trying to do a 'form post' to the other .php page after your data is written to the database.
You can more information from this wonderful Scott Hanselman article, but here is the summary:
public static string HttpPost(string URI, string Parameters)
{
System.Net.WebRequest req = System.Net.WebRequest.Create(URI);
req.Proxy = new System.Net.WebProxy(ProxyString, true);
//Add these, as we're doing a POST
req.ContentType = "application/x-www-form-urlencoded";
req.Method = "POST";
//We need to count how many bytes we're sending. Post'ed Faked Forms should be name=value&
byte [] bytes = System.Text.Encoding.ASCII.GetBytes(Parameters);
req.ContentLength = bytes.Length;
System.IO.Stream os = req.GetRequestStream ();
os.Write (bytes, 0, bytes.Length); //Push it out there
os.Close ();
System.Net.WebResponse resp = req.GetResponse();
if (resp== null) return null;
System.IO.StreamReader sr = new System.IO.StreamReader(resp.GetResponseStream());
return sr.ReadToEnd().Trim();
}
The ideal solution to your problem is that you create a web service on the php site and your asp.net code calls the web service. http://en.wikipedia.org/wiki/Web_service
Creating a web service in PHP: http://www.xml.com/pub/a/ws/2004/03/24/phpws.html
Calling a web service in ASP.Net: http://www.codeproject.com/KB/webservices/WebServiceConsumer.aspx
Alternatively you could create a http request from your asp.net to the php site posting all the form elements to the php site.
Here is an example: http://www.netomatix.com/httppostdata.aspx
NB: You are almost guaranteed to run into problems with the second approach in the medium to long term, I don't recommend it unless you don't have control over the php site.

Categories