2

I'm trying to retrieve data from a third party provider. They send us the data in a request with Content-Type: application/x-www-form-urlencoded. On our end, we parse the data in both the $_POST and $_GET variables like this:

print_r($_POST);
print_r($_GET);

The arrays are empty:

Array
(
)

Array
(
)

I also tried getting the data with file_get_contents('php://input'), but it prints an empty string.

Checking the $_SERVER variable, we notice that the content-type is indeed application/x-www-form-urlencoded and that the REQUEST_METHOD is indeed POST.

Does anyone have any pointers to where we can access the data sent?

(We made sure the problem is on our-hand by changing our URL with an URL from RequestBin and seeing the data there.)

EDIT

The response we get when we switch our URL with a http://requestb.in:

amount: 2200
pay_from_email: [REDACTED]
lma_transaction_id: [REDACTED]
md5sig: [REDACTED]
transaction_id: 761
merchant_fields: cart_id
lma_amount: 2200
status: 2
pay_to_email: [REDACTED]
cart_id: 11242
merchant_id: [REDACTED]

The headers of the request are:

X-Request-Id: [REDACTED]
User-Agent: [REDACTED]
Connection: close
Content-Type: application/x-www-form-urlencoded
Host: requestb.in
Content-Length: 326

EDIT
var_dump(getallheaders()); prints:

[User-Agent] => [REDACTED] (Name of the third-party provider)
[Content-Type] => application/x-www-form-urlencoded
[Host] => [REDACTED]

EDIT apache_request_headers() prints:

[Host] => [REDACTED]
[DNT] => 1
[Cookie] => [REDACTED]
[Connection] => keep-alive
[Accept] => text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
[User-Agent] => Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_2) AppleWebKit/537.74.9 (KHTML, like Gecko) Version/7.0.2 Safari/537.74.9
[Accept-Language] => fr-fr
[Accept-Encoding] => gzip, deflate
[Cache-Control] => max-age=0
Aliou
  • 1,065
  • 11
  • 17
  • Check this http://stackoverflow.com/questions/989967/best-way-to-log-post-data-in-apache – hek2mgl Mar 12 '14 at 10:19
  • @hek2mgl I don't want the data in the Apache log, I want to parse it and then use it. – Aliou Mar 12 '14 at 10:22
  • any .htaccess files in use, that could be a redirection issue i guess? do you get any data sent to $_GET ? – Taher Mar 25 '14 at 22:50
  • Yes, an .hataccess file is used we know the file is accessed because we write information in a log file. The `$_GET` variable is empty. – Aliou Mar 25 '14 at 22:59
  • Could you please show us the output of `apache_request_headers()` on your own server? Just to make sure. – Mehran Mar 29 '14 at 07:54
  • what do you get when you **do a request with curl/wget** from your server to the third party url? Sounds to me like you have something in the middle that avoid your direct access? proxy? – jerik Apr 01 '14 at 22:01
  • @jerik the `curl` request is successful when I do it from my server. – Aliou Apr 02 '14 at 08:17
  • Do you use plain php or do you use a php-framework? If framework, then perhaps there happens something strange inside... Whats does the $_REQUEST array contain? – jerik Apr 03 '14 at 09:26

2 Answers2

0

Make sure that, in php.ini:

  • track_vars (it's only available on very old PHP versions) is set to On
  • variables_order contains the letter P
  • post_max_size is set to a reasonable value (e.g. 8 MB)
  • if using suhosin patch: suhosin.post.max_vars and suhosin.request.max_vars are large enough
  • Try to prepend "www." to the URL that is being posted to.
silkfire
  • 24,585
  • 15
  • 82
  • 105
  • Everything in the `php.ini` file is correct. The `www` is already in the URL. We tried with and without it. – Aliou Mar 26 '14 at 09:05
  • @Aliou How large is the data being posted? Is it a file being uploaded to the server? – silkfire Mar 26 '14 at 09:30
  • The raw body of the request is less than 350 characters. It is comprised of 12 pairs. I'll put a sample response in the original question. – Aliou Mar 26 '14 at 09:48
  • I also added the headers of the request. – Aliou Mar 26 '14 at 09:51
  • Okay, so your request is actually very small. What happens if you just append query strings to the URL of your site? Like this: `?test=something`, can you see anything then. Also, how does this 3rd party send the data? With cURL? – silkfire Mar 26 '14 at 10:28
  • Running cURL with `-X POST -d` and the query string works. Unfortunately, I don't know how the third party sends its data. – Aliou Mar 26 '14 at 10:37
  • Is it a mix of $_GET and $_POST? Why, if that's the case? – silkfire Mar 26 '14 at 10:40
  • No, it's only `$_POST` data. – Aliou Mar 26 '14 at 10:41
  • Can you edit your post and tell me what headers you're getting with the 3rd party request? Like this: `var_dump(getallheaders());` – silkfire Mar 26 '14 at 10:43
  • In your php.ini, what's the value of the `enable_post_data_reading` directive? – silkfire Mar 26 '14 at 10:48
  • In php.ini, the line setting `enable_post_data_reading` is commented. However, in the comments above it is said that it is enabled by default. Should I uncomment it ? – Aliou Mar 26 '14 at 10:50
  • Nah, just let it be as it is. It should be indeed `On` by default unless altered. – silkfire Mar 26 '14 at 10:54
  • I can see the headers you posted now. I've been through something similar, and a site I posted to always returned an empty page. I finally found the culprit and that was because my cURL needed explicitly the `Accept-Language` header. But I'm not certain that will help you in this case. – silkfire Mar 26 '14 at 10:55
  • Could you let some other party or create your own POST request to your site and see if that works? – silkfire Mar 26 '14 at 11:06
  • Unfortunately, the other party is a payment provider and we must pass by them for this particular request. – Aliou Mar 26 '14 at 11:10
  • Yeah I see, but this was just mostly to see if your site is able to receive any POST requests at all? I assume 3rd party = payment provider? – silkfire Mar 26 '14 at 11:13
  • When I send a manual POST request using `cURL` or a regular HTML form, I receive the POST request. (Indeed, it is a payment provider, and our partnership hasn't been made public yet hence my redacted comments.) – Aliou Mar 26 '14 at 11:18
  • @Aliou Could you try this code: `$_POST = json_decode(file_get_contents('php://input'), true);` Then see what `$_POST` contains. – silkfire Mar 26 '14 at 12:00
  • `$_POST` is still empty. – Aliou Mar 26 '14 at 12:38
  • Yeah, that's really strange... Is the 3rd party site and your site URLs both HTTPS (secure)? – silkfire Mar 26 '14 at 13:32
0

My answer is not a solution but a pointer as you've asked.

These are the facts you've mentioned:

  1. You have made sure the request is in POST by checking $_SERVER['REQUEST_METHOD'].
  2. Your script works fine when an ordinary POST form is submitted by a browser.
  3. There's a Content-Length header when the request is sent to requestb.in.
  4. The same Content-Length header can not be found when the request is sent by 3rd party.

Unfortunately I couldn't send a POST request without a Content-Length present, so I have no idea if this is actually the root of your problem. It totally depends on Apache+PHP how to react if this header is not available and I couldn't find anywhere saying what would happen if a POST request does not come with it. It's possible that PHP can not construct the $_POST array without it but that's just a guess.

Regardless, the fact that this header is sent to requestb.in but not your script is all that we need to focus on. I'll update my answer when I've got something new to say, but for now this is all.

[UPDATE]

Using NetTool I managed to test different combinations of headers and the only case in which PHP couldn't populate $_POST array was when the request did have the Content-Type header. Even then the file_get_contents('php://input') would show the raw incoming post data.

Getting back to Content-Length, NetTool let me omit this header and not send it but regardless of it being sent, the PHP script shows the presence of this header in request! I'm not sure if it's actually not sent in which case Apache is filling the gap before it gets to PHP, or NetTool is sending it without telling me.

Only possible way left that you can debug your problem is using mod_dumpio to dump all the incoming post data before they get to PHP. That way you can make sure if the incoming request actually contains any data or it's empty.

[UPDATE]

Finally I managed use the NetTool's tunnel feature to monitor the actual headers sent with the request. Unfortunately even though I tell NetTool not to send Content-Length it sends anyway. It seems to me it's inevitable. In which case it could be the cause of your problem too. I mean if this header is not present then there's a possibility that PHP can not construct the $_POST array.

Mehran
  • 15,593
  • 27
  • 122
  • 221