Unexpected PHP/jQuery/JSON interaction differences
Question: ## Background:

So, I have the following PHP snippet written to help me debug a much larger
problem, but now I'm even more confused as to how jQuery and PHP expect JSON
to be sent/received, as this code does not seem to be doing what I expect:

I want to be able to _receive_ data as either `application/x-www-form-
urlencoded` **_or_** as `application/json`, while responding only with
`application/json` (for now).

**`test.php`:**

    
    
    <?php
    
    $content_type = $_SERVER['CONTENT_TYPE'];
    
    switch ($_SERVER['REQUEST_METHOD']) {
        case 'GET':
            echo <<< _EOF
    <html>
    <body>
    <div id="content"></div>
    <script type="text/javascript" src="/jquery-1.10.2.min.js"></script>
    </body>
    </html>
    _EOF;
            break;
        case 'POST':
            header('Content-type: application/json');
            if ($content_type == 'application/x-www-form-urlencoded') {
    
                $_POST['message'] = 'debugged';
                echo json_encode($_POST);
    
            # Otherwise, get raw body data.
            } else {
                $data = file_get_contents('php://input');
                if ($data == null) {
                    $data = file_get_contents('php://stdin');
                }
    
                $object = json_decode($data, true);
                $object['message'] = 'debugged';
    
                echo json_encode($object);
            }
            break;
        default:
            echo "These aren't the droids you're looking for. Move along.<br />";
            break;
    }
    

## Testing:

I've been testing this code using both the [Python Requests
Library](http://docs.python-requests.org/en/latest/index.html) and [jQuery's
Ajax method](http://api.jquery.com/jQuery.ajax/).

In Python, data can be sent as either `application/x-www-form-urlencoded` or
as raw body data attached to the request, depending on the type of the `data`
argument you supply to the `post()` method (see [here](http://docs.python-
requests.org/en/latest/user/quickstart/#more-complicated-post-requests) for
more information).

## All going well so far...

Using Requests, I get exactly what I expect.

When the `data` parameter of the `post()` method is a **Python dictionary
object,** the data is sent form-encoded:

    
    
    >>> import requests
    >>> r = requests.post('http://example.com/test.php', data={"name": "tester", "message": "bug"})
    >>> print r.text
    {"message": "debugged", "name": "tester"}
    

When the `data` parameter is a **literal string (note the single-quotes!)**
the data is sent as the body of the request, and may (or may not) be
interpreted as JSON at the endpoint (I do interpret it as JSON in the sample
PHP code above, and it's guaranteed it will only ever be JSON):

    
    
    >>> r = requests.post('http://example.com/test.php', data='{"name": "tester", "message": "bug"}')
    >>> print r.text
    {"message": "debugged", "name": "tester"}
    

Both of these results are what I expect.

## Here's the weird part...

I seem to be getting different responses from this code, not depending on
**_how_** I send the data, but **_what I use to send it_** (i.e. Requests, or
jQuery). There must be something different between the two that I'm completely
missing.

If I point my browser (Chrome) at <http://example.com/test.php>, triggering
the GET request handler to serve me the tiny HTML page contained in the PHP
code above, and then fire the following jQuery code in the JavaScript console,
this is what I get back as a result:

    
    
    > var output = null;
    > $.ajax({
          type: 'POST',
          url: 'http://example.com/test.php',
          data: {
              name: 'tester',
              message: 'bug'
          },
          dataType: 'json',
          beforeSend: function(x) {
              if (x && x.overrideMimeType) {
                  x.overrideMimeType('application/json; charset=UTF-8');
              }
          },
          success: function(d) {
              $output = d;
          }
      });
    > output
    Object {message: "debugged"}
    

By now I'm thinking, **_where the heck did the 'name' entry go?_**

As it turns out, only the things that I **_explicitly set_** from within the
PHP handler seem to be accessible as output to jQuery. But sometimes I want to
use data from a user's input, modify it, and then return it as output. But
with jQuery acting like this, (or PHP... I'm not exactly sure in which bit of
code my error lies) I'm unable to do what I want.

## Weirder still!

The next thing I did was to change the output message to be "debugged (form-
data)" or "debugged (body-data)" depending on whether the if-statement in the
POST handler was entered or "elsed", and was surprised to find that **jQuery
is sending the data as body data, but is setting the`application/x-www-form-
urlencoded` header.** This is completely not what I expected. I feel like
either one of jQuery (1.10.2) or Python Requests is misbehaving due to this
discrepancy, but I'm not sure which. (Or is sending form-encoded data really
this ad-hoc?)

Any thoughts or insight on what's going on here, what I'm missing, what I
SHOULD be expecting if my expectations or wrong, or even links to relevant
documentation I've managed to overlook while researching this would be greatly
appreciated.


Answer: Have you tried putting the identifier "name" in quotes. It's a reserved word
and some parsers don't handle it not being in quotes well. I ran into a
similar problem a couple of years back.

