title: 400 bad request despite correct request handling
body: <p>I am having trouble getting an AJAX request to work. From this earlier thread it appears the request handler and hooks to register the handler are not the issue: <a href="https://stackoverflow.com/questions/55975499/wordpress-ajax-request-logs-400-bad-request-to-console/55979756?noredirect=1#comment98610957_55979756">Wordpress: Ajax request logs 400 Bad Request to console</a></p>
  
  <p>The framework (wordpress) does send ajax requests (to the same target) with a "heartbeat" k/v pair every minute or so. I've copied my bad request and one of these good requests from the core below. What sticks out is the response header of text/html in my one. Could that cause a bad <strong>REQUEST</strong> ? If not what else might cause it?</p>
  
  <hr>
  
  <h2>Request Headers</h2>
  
  <pre><code>// my bad request. Error code 400 "BAD REQUEST"
  Request URL:http://localhost/wptest2/wp-admin/admin-ajax.php
  Request method:POST
  Remote address:127.0.0.1:80
  Status code: 400
  Version:HTTP/1.1
  
  Response headers (177 B)    
  Raw headers
  Connection  close
  Content-Length  165
  Content-Type    text/html; charset=UTF-8
  Date    Sun, 05 May 2019 04:58:48 GMT
  Server  Apache/2.4.29 (Ubuntu)
  
  Request headers (1.030 KB)  
  Raw headers
  Accept    application/json, text/javascript, */*; q=0.01
  Accept-Encoding gzip, deflate
  Accept-Language  en-US,en;q=0.5
  Connection  keep-alive
  Content-Length  30
  Content-Type    application/json
  Cookie    wordpress_69cb7e12fdbb27dfb560…2-1ebb-4ab4-ba67-14f7be9e4c98
  Host    localhost
  Referer http://localhost/wptest2/wp-ad…-general.php?page=fvc-settings
  User-Agent  Mozilla/5.0 (X11; Ubuntu; Linu…) Gecko/20100101 Firefox/66.0
  X-Requested-With    XMLHttpRequest
  
  
  // A working request done automatically every minute or two by wordpress core
  Request URL:http://localhost/wptest2/wp-admin/admin-ajax.php
  Request method:POST
  Remote address:127.0.0.1:80
  Status code: 200
  Version:HTTP/1.1
  
  Response headers (605 B)    
  Raw headers
  Cache-Control     no-cache, must-revalidate, max-age=0
  Connection  Keep-Alive
  Content-Length   423
  Content-Type     application/json; charset=UTF-8
  Date    Sun, 05 May 2019 04:59:46 GMT
  Expires Wed, 11 Jan 1984 05:00:00 GMT
  Keep-Alive    timeout=5, max=100
  Referrer-Policy strict-origin-when-cross-origin
  Server  Apache/2.4.29 (Ubuntu)
  X-Content-Type-Options  nosniff
  X-Frame-Options SAMEORIGIN
  X-QM-overview-memory    7,444 kB
  X-QM-overview-memory_usage  5.7% of 131,072 kB limit
  X-QM-overview-time_taken    0.5868
  X-QM-overview-time_usage    2.0% of 30s limit
  X-Robots-Tag    noindex
  
  Request headers (1.062 KB)  
  Raw headers
  Accept    application/json, text/javascript, */*; q=0.01
  Accept-Encoding gzip, deflate
  Accept-Language en-US,en;q=0.5
  Connection  keep-alive
  Content-Length  99
  Content-Type    application/x-www-form-urlencoded; charset=UTF-8
  Cookie    wordpress_69cb7e12fdbb27dfb560…2-1ebb-4ab4-ba67-14f7be9e4c98
  Host    localhost
  Referer http://localhost/wptest2/wp-ad…-general.php?page=fvc-settings
  User-Agent  Mozilla/5.0 (X11; Ubuntu; Linu…) Gecko/20100101 Firefox/66.0
  X-Requested-With    XMLHttpRequest
  </code></pre>
  
  <hr>
  
  <h2>Ajax Calls</h2>
  
  <p>Of course I only test one at a time.</p>
  
  <pre><code>jQuery(document).ready(function() {
        jQuery('#previousButton').click(function() {
          jQuery.ajax({
            type: "POST",
            url: ajaxurl,
            headers : {
              'Content-Type' : 'application/json'
            },
            dataType: "json",
            action: "selectTargetsWithOffset",
            data: {
              action: "selectTargetsWithOffset",
            },
            success: function() {
              console.log(response, `=====response from $.ajax}=====`);
            }
          });
  
        });
  </code></pre>