PHP HTTP Post Server - can't get post requests - php

So I'm working on a group project for school, and we're working with a client who wants a companion app of sorts to go with his companies device. We provide the device a host IP or domain and it sends HTTP Post requests in the form of XML every 5 seconds or so. The problem we're having is we have NO idea how to capture the data being sent on our server. Simply trying to grab and dump all $_POST data yields an empty array, and our attempts to use a socket have produced similar results.
We've tried pointing the device to http://posttestserver.com/ - and it gets the data perfectly, though there is no source code available to see how the site operates. Admittedly our knowledge of server side scripting is limited at best as we've only been working with PHP for a couple months, and this isn't something that has been covered.
The above mentioned post server produces the following output ( with some omitted data for privacy ). Any help in reproducing this or simply assistance in getting the data on our server would be greatly appreciated!
Time: Sun, 09 Nov 14 14:20:26 -0800
Source ip: ######
Headers (Some may be inserted by server)
HTTP_CONNECTION = close
REQUEST_URI = /post.php
QUERY_STRING =
REQUEST_METHOD = POST
GATEWAY_INTERFACE = CGI/1.1
REMOTE_PORT = ######
REMOTE_ADDR = ######
CONTENT_LENGTH = 488
CONTENT_TYPE = application/xml
HTTP_USER_AGENT = Raven Uploader/v1
HTTP_FROM = ######
HTTP_ACCEPT = */*
HTTP_HOST = posttestserver.com
HTTPS = on
UNIQUE_ID = VF-oqtBx6hIAACKZ7j0AAAAH
REQUEST_TIME_FLOAT = 1415571626.7993
REQUEST_TIME = 1415571626
No Post Params.
== Begin post body ==
<?xml version="1.0"?><clientcompany macId="######" version="1.1" timestamp="1415571625s">
<PriceCluster>
<DeviceMacId>######</DeviceMacId>
<MeterMacId>######</MeterMacId>
<TimeStamp>0x1bf2a52d</TimeStamp>
<Price>0x00000467</Price>
<Currency>0x007c</Currency>
<TrailingDigits>0x04</TrailingDigits>
<Tier>0x01</Tier>
<StartTime>0x1bf2a52d</StartTime>
<Duration>0xffff</Duration>
<RateLabel>Block 2</RateLabel>
</PriceCluster>
</clientcompany>
== End post body ==
Upload contains PUT data:
<?xml version="1.0"?><clientcompany macId="0xd8d5b90016d1" version="1.1" timestamp="1415571625s">
<PriceCluster>
<DeviceMacId>######</DeviceMacId>
<MeterMacId>######</MeterMacId>
<TimeStamp>0x1bf2a52d</TimeStamp>
<Price>0x00000467</Price>
<Currency>0x007c</Currency>
<TrailingDigits>0x04</TrailingDigits>
<Tier>0x01</Tier>
<StartTime>0x1bf2a52d</StartTime>
<Duration>0xffff</Duration>
<RateLabel>Block 2</RateLabel>
</PriceCluster>
</clientcompany>

You need to capture the raw input stream:
//$data = $_POST; <-- will be empty unless you are sending a key value pair(s)
$data = file_get_contents('php://input'); //<-- will capture all posted data
echo '== Begin post body ==';
echo $data;
echo '== End post body ==';
If you need to see headers as well you can use getallheaders function: http://php.net/manual/en/function.getallheaders.php

instead of $_POST check $HTTP_RAW_POST_DATA var

Related

Storing post content to variable

http request code
POST /parse.php HTTP/1.1
Host: mysite.com
Connection: Keep-Alive
Content-Length: 26
Content-Type: application/x-www-urlencoded
lt=12.123123&ln=123.123123
php code
//connect to database codes here
$database = "update name_tbl set lat='".$_GET['lt']."', lng='".$_GET['ln']."' where id=1";
mysqli_query($conn, $database)
So my problem I think is in the php part when I enter mysite.com/parse.php?lt=12.123123&ln=123.123123 to test if it's working and it does but when I the http request code on HttpRequest it but the send value is both 0.000000.
If you aren't sure whether the request has come to you via a GET or a POST method, you could try something like this
$lt = isset($_GET['lt']) ? $_GET['lt'] : (isset($_POST['lt']) ? $_POST['lt'] : null);
$ln = isset($_GET['ln']) ? $_GET['ln'] : (isset($_POST['ln']) ? $_POST['ln'] : null);
There might be another option called $_REQUEST which encompasses both $_GET and $_POST but has it own quirks too. Please have a read on the following link to get a better idea:
Among $_REQUEST, $_GET and $_POST which one is the fastest?

PHP script to use for HTTP post request

Hope someone could spare time to help a rookie. I have to set up my server and then provide a supplier with the URL of the page which has to be able to receive a HTTP-Post request like the following - For each post received, your page will have to answer with a "+OK", in order to confirm the correct delivery of the notification.
POST /yourpage.php HTTP/1.1
Host: www.yoursite.com
Content-Length: 215
Connection: Keep-Alive
Content-type: application/x-www-form-urlencoded
Accept-Language: it
Cache-Control: no-cache
destination=%2B40757732753&text=sms+test+example&originator=%2B391234567890&date_time=20160606074445
What would be the best way to go about this instruction? I have some basic knowledge of PHP (still learning), so we can use PHP.
Thanks in advance
Marinda
You need learn about global variables in PHP, php has $_POST able to get content sended on body of post and do something with it.
<?php
// this will create a variable with data of destination sent
$destination = $_POST['destination']
...
// just print +OK
echo "+OK"
But if you want send SMS to Mobile, you need use services to send for you, in general has a cost for this and able to send a limited number of SMSs depend your plan.
I hope it help you
Check $_POST variable. It's a kind of special variable for this language. Then, you can:
<?php
$isOK = true;
// Check if POST parameter destination is set and it is not blank, you
// can repeat this validation with all your parameters, changing
// destination by its name.
if (!isset($_POST['destination']) || trim($_POST['destination']) == '') {
$isOK = false;
}
if ($isOK) {
echo "+OK";
}

php://input contains data for a GET request

I am running Apache2 and PHP 5 on Linux, and I'm getting some strange behavior with the php://input stream.
For some GET requests the stream is not empty like it should be. Instead, the php://input stream contains the entire GET request. I have worked around the issue but I would like to know if I should file a bug about this, or if it is "desired but undocumented" behavior.
Details
Early in the request processing, I call:
$in = file_get_contents('php://input');
if ( !empty($in) )
$post_data = json_decode($in);
if ( !empty($in) && is_null($post_data) ) {
// output some error info and exit
}
Usually when a request does not have a body then $in is empty and all is right with the world. But sometimes a GET request will have a body, and that body will be the entire request. Of course you can't json-decode that data, and the error condition gets hit.
This only happens with some requests. For example, this request does not exhibit the error:
GET /os/invitations/kkkkkk HTTP/1.1
Host: our.machine.com
Content-Type: application/json
Authorization: Basic aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa==
But this request, which is routed through some proxies and VPNs, does trigger the error.
GET http://some.proxy.at.some.big.company.com:7080/cvp-out/cmmproxy/os/invitations/d66065566dba541c8ba6a70329684645 HTTP/1.1
Content-Type: application/json
Authorization: Basic aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa==
Clientid: abc
User-Agent: Java/1.6.0
Host: some.proxy.at.some.big.company.com:7080
Accept: text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2
Connection: keep-alive
X-Remote-Addr: 53.231.244.171
X-Remote-Host: 53.231.244.171
X-Server-Name: some.proxy.at.some.big.company.com
X-Server-Port: 7080
X-Scheme: http
I spent hours treating this like a routing/dispatch problem, but it turned out to be our code. The fix was, of course, to only read from the input stream when you are expecting data:
if ( in_array( $_SERVER['REQUEST_METHOD'], array('PUT', 'POST') )) {
$in = file_get_contents('php://input');
if ( !empty($in) )
$post_data = json_decode($in);
}
Is this a known issue? Does it happen unpredictably? Should I file a bug?
As far as i know, that's not an error. We understand that a GET request shouldnt have a body, but in the docs of php:// they say nothing about wich types of requests will generate an input, so it could be any method. And for sure it is not limited to POST, since the mention at least PUT and PROPFIND.
So at any rate, your solution is a must.

Is there any way to configure php to always set $_SERVER['CONTENT_LENGTH']?

I'm working on carddav client. As server i use davical v. 0.9.9.6. I don't understand why i'm getting invalid content-type error when http headers contains correct value. I look into source code and found this condition:
if ( isset($_SERVER['CONTENT_LENGTH']) && $_SERVER['CONTENT_LENGTH'] > 7) {...
After little research I found php set $_SERVER['CONTENT_LENGTH'] only with POST method and uploading file. Is there any way to configure php to always set $_SERVER['CONTENT_LENGTH']?
I'm asking generally, not only for this case...
//EDIT
I'm doing HTTP PUT request to davical server (using php curl).
PUT /caldav.php/testuser/contacts/newc.vcf HTTP/1.1
Host: davical
Content-Type: text/vcard;
BEGIN:VCARD
VERSION:3.0
FN:ME
...
On davical side is condition testing CONTENT_LENGTH which is not set. So it's a davical bug?
//EDIT 2
Finally I figure it out!
PUT request with calback readfunc requires set INFILE_SIZE via curl_setopt(...)
There is none auto value and put Content-Length field manualy into header is also wrong.
Example (incorrect):
// PUT REQUEST
curl_setopt($ch,CURLOPT_HTTPHEADER,"Content-Length: $length"); //mistake
curl_setopt($ch,CURLOPT_PUT,true);
curl_setopt($ch,CURLOPT_READFUNCTION,array($this,'readfunc'));
....
--------------------------------------------------------------
// WIRESHARK TCP STREAM DUMP
PUT /caldav.php/testuser/contacts/novy.vcf HTTP/1.1
Authorization: Basic xxxxxxxxxxxxxxx
Host: davical
Accept: */*
Content-Type: text/vcard
Content-Length: xxx
Expect: 100-continue
HTTP/1.1 100 Continue
155
BEGIN:VCARD
VERSION:3.0
...
END:VCARD
0
HTTP/1.1 200 OK
----------------------------------------------------------------
// On server side
isset($_SERVER['CONTENT_LENGTH'])==false
Second (correct) example
// PUT REQUEST
curl_setopt($ch,CURLOPT_INFILESIZE,$length);
curl_setopt($ch,CURLOPT_PUT,true);
curl_setopt($ch,CURLOPT_READFUNCTION,array($this,'readfunc'));
....
--------------------------------------------------------------
// WIRESHARK TCP STREAM DUMP
PUT /caldav.php/testuser/contacts/novy.vcf HTTP/1.1
Authorization: Basic xxxxxxxxxxxxxxx
Host: davical
Accept: */*
Content-Type: text/vcard
Content-Length: xxx
Expect: 100-continue
HTTP/1.1 100 Continue
BEGIN:VCARD
VERSION:3.0
...
END:VCARD
HTTP/1.1 200 OK
----------------------------------------------------------------
// On server side
isset($_SERVER['CONTENT_LENGTH'])==true
Although i have never used CONTENT_LENGHT i can tell you why this is probably happening:
In a request, you don't have to set the Content-Lenght header... IT IS NOT MANDATORY. Except for specific situations. If your POSTed content is of type "multipart/form-data" it becomes necessary to use content-lenght for each part because each part is seperated by a boundary and each part will have its own headers...
For example:
Content-Type: MultiPart/Form-Data
Boundary: #FGJ4823024562DGGRT3455
MyData=1&Username=Blabla&Password=Blue
#FGJ4823024562DGGRT3455==
Content-Type: image/jpef:base64
Content-Lenght: 256
HNSIFRTGNOHVDFNSIAH$5346twSADVni56hntgsIGHFNR$Iasdf==
So here this is a crude example of what a multi part request works, you see that the second part has a content-lenght. This is why sometimes the content-lenght is set and sometimes not, because you need to read X bytes before finding another boundary and extract the correct data.
It doesn't mean your server will never send it in in other cases, but my 2 cents are this is the case right now. Its because you are not in POST, but in some other modes.
Only requests that have a request body have a content length request header (or at least only then it makes sense) and so therefore the $_SERVER variable is set.
If you need it to be always set (which I think is bogus), you can do this yourself on the very beginning of your script:
isset($_SERVER['CONTENT_LENGTH']) && $_SERVER['CONTENT_LENGTH'] = 0;
Assuming that if it is not set, it's of zero length. See as well Improved handling of HTTP requests in PHP.
You could probably set them by yourself. Why do you need that this values are set? And what should they set to?
Maybe you're missing information on $_SERVER['CONTENT_TYPE'] or
$_SERVER['CONTENT_LENGTH'] as I did. On POST-requests these are
available in addition to those listed above.
-> http://www.php.net/manual/en/reserved.variables.server.php#86495

PHP returning content-length of 0 to python's urllib

My code fetches CSV data from a PHP page using httplib. When I open the page in Firefox or Chrome, the data displays just fine. However, when I try to fetch it with my python code, I get a header with content-length: 0 and no data. This page is the only one that does this - in another page in the same directory, the python httplib fetching works just fine. Can someone tell me what I'm doing wrong?
code:
FILE_LOC = '/core/csv.php'
argstr = '?type=' + self.type + '&id=' + self.id
conn = httplib.HTTPConnection(SERVER_ADDRESS)
conn.request('GET', FILE_LOC + argstr)
resp = conn.getresponse()
csvstr = resp.read()
The response headers:
[('content-length', '0'), ('x-powered-by', 'PHP/5.1.6'),
('server', 'Apache/2.2.3 (CentOS)'), ('connection', 'close'),
('date', 'Thu, 19 Aug 2010 21:39:44 GMT'), ('content-type', 'text/html; charset=UTF-8')]
Perhaps the PHP script expects to see some HTTP header or headers that the httplib module isn't sending. For example, httplib does not seem to send Accept, Accept-Language, or User-Agent headers by default. You may need to add one or more of those to the request() call. It does seem to send a proper Host header, though, which was my first guess.
Probably filtering on User-Agent header -- try spoofing e.g. your Firefox.
Failing that you could use Firefox to connect to a local Python server to see exactly what headers it is sending, and then replicate those.

Categories