title: PHP POST to RESTful API implemented with apache mod_rewrite
body: <p>I created a PHP RESTful API following <a href="http://coreymaynard.com/blog/creating-a-restful-api-with-php/" rel="nofollow">this example</a> (code at the bottom). From what I understand, the API converts non-existing URI components to GET parameters in the address via the <code>.htaccess</code> file like this:</p>
  
  <pre><code>&lt;IfModule mod_rewrite.c&gt;
  RewriteEngine On
  RewriteCond %{REQUEST_FILENAME} !-f
  RewriteCond %{REQUEST_FILENAME} !-d
  RewriteRule api/v1/(.*)$ api/v1/api.php?request=$1 [QSA,NC,L]
  &lt;/IfModule&gt;
  </code></pre>
  
  <p>So if I do, e.g.:</p>
  
  <pre><code>http://mysite/api/v1/endpoint1/param1
  </code></pre>
  
  <p><code>endpoint1/param1</code> can be parsed in the API implementation to call a PHP function <code>endpoint1(param1)</code>.</p>
  
  <p>Now my issue is, param1 is really long, and I want use AJAX to <code>POST</code> <code>param1</code>, but the POST doesn't go through</p>
  
  <p>For example, for the RESTful API:</p>
  
  <pre><code>http://mysite/api/v1/endpoint1
  </code></pre>
  
  <p>I POSTed <code>data</code> using AJAX as follows:</p>
  
  <pre><code>$.post('http://mysite/api/v1/endpoint1/',data,callback,'json');
  </code></pre>
  
  <p>In <code>API.class.php</code>, <code>$_SERVER['REQEUEST_METHOD']</code> is <code>'POST'</code>, but <code>$_POST</code> is empty array.</p>
  
  <p>My questions are:</p>
  
  <p>What is actually happening when I <code>POST</code> to a virtual URL to be handled by <code>mod_rewrite</code>. Is the end result a <code>GET</code> request by <code>mode_rewrite</code> or a <code>POST</code> request by my AJAX call?</p>
  
  <p>How can I modify the code to get the <code>POST</code>ed data through? (Is it possible to ask mod_rewrite to use the POST method instead?)</p>
  
  <p>I am confused here, any pointers are appreciated.</p>
  
  <hr>
  
  <p>The interface for the relevant REST api is (<code>API.class.php</code>, please see <a href="http://coreymaynard.com/blog/creating-a-restful-api-with-php/" rel="nofollow">the example</a> for complete code):</p>
  
  <pre><code>&lt;?php
  abstract class API
  {
      protected $method = '';
      protected $endpoint = '';
      protected $args = Array();
      protected $file = Null;
      public function __construct($request) {
          header("Access-Control-Allow-Orgin: *");
          header("Access-Control-Allow-Methods: *");
          header("Content-Type: application/json");
          $this-&gt;args = explode('/', rtrim($request, '/'));
          $this-&gt;endpoint = array_shift($this-&gt;args);
          $this-&gt;method = $_SERVER['REQUEST_METHOD'];
          if ($this-&gt;method == 'POST' &amp;&amp; array_key_exists('HTTP_X_HTTP_METHOD', $_SERVER)) {
              if ($_SERVER['HTTP_X_HTTP_METHOD'] == 'DELETE') {
                  $this-&gt;method = 'DELETE';
              } else if ($_SERVER['HTTP_X_HTTP_METHOD'] == 'PUT') {
                  $this-&gt;method = 'PUT';
              } else {
                  throw new Exception("Unexpected Header");
              }
          }
          switch($this-&gt;method) {
          case 'DELETE':
          case 'POST':
              $this-&gt;request = $this-&gt;_cleanInputs($_POST);
              $this-&gt;args[] = ???; //Problem line: how do I add post to the args 
              break;
          case 'GET':
              $this-&gt;request = $this-&gt;_cleanInputs($_GET);
              break;
          case 'PUT':
              $this-&gt;request = $this-&gt;_cleanInputs($_GET);
              $this-&gt;file = file_get_contents("php://input");
              break;
          default:
              $this-&gt;_response('Invalid Method', 405);
              break;
          }
      }
      public function processAPI() {
          if ((int)method_exists($this, $this-&gt;endpoint) &gt; 0) {
              return $this-&gt;_response($this-&gt;{$this-&gt;endpoint}($this-&gt;args));
          }
          return $this-&gt;_response("No Endpoint: $this-&gt;endpoint", 404);
      }
      private function _response($data, $status = 200) {
          header("HTTP/1.1 " . $status . " " . $this-&gt;_requestStatus($status));
          return json_encode($data);
      }
      private function _cleanInputs($data) {
          $clean_input = Array();
          if (is_array($data)) {
              foreach ($data as $k =&gt; $v) {
                  $clean_input[$k] = $this-&gt;_cleanInputs($v);
              }
          } else {
              $clean_input = trim(strip_tags($data));
          }
          return $clean_input;
      }
      private function _requestStatus($code) {
          $status = array(  
              200 =&gt; 'OK',
              404 =&gt; 'Not Found',   
              405 =&gt; 'Method Not Allowed',
              500 =&gt; 'Internal Server Error',
          ); 
          return ($status[$code])?$status[$code]:$status[500]; 
      }
  } 
  ?&gt;
  </code></pre>