ncrocfer
ncrocfer

Reputation: 2570

get a PUT request with Codeigniter

I have a problem right now with CodeIgniter : I use the REST Controller library (which is really awesome) to create an API but I can not get PUT requests...

This is my code :

function user_put() {
    $user_id = $this->get("id");
    echo $user_id;
    $username = $this->put("username");
    echo $username;
}

I use curl to make the request :

curl -i -X PUT -d "username=test" http://[...]/user/id/1

The user_id is full but the username variable is empty. Yet it works with the verbs POST and GET. Have you any idea please?

Thank you !

Upvotes: 9

Views: 32275

Answers (7)

justnajm
justnajm

Reputation: 4534

Codeigniter put_stream has provided no help, instead I had to use php input stream as following method can be added to helpers, from there you can parse put request in any of the controllers:

function parsePutRequest()
{
    // Fetch content and determine boundary
    $raw_data = file_get_contents('php://input');
    $boundary = substr($raw_data, 0, strpos($raw_data, "\r\n"));

// Fetch each part
$parts = array_slice(explode($boundary, $raw_data), 1);
$data = array();

foreach ($parts as $part) {
    // If this is the last part, break
    if ($part == "--\r\n") break; 

    // Separate content from headers
    $part = ltrim($part, "\r\n");
    list($raw_headers, $body) = explode("\r\n\r\n", $part, 2);

    // Parse the headers list
    $raw_headers = explode("\r\n", $raw_headers);
    $headers = array();
    foreach ($raw_headers as $header) {
        list($name, $value) = explode(':', $header);
        $headers[strtolower($name)] = ltrim($value, ' '); 
    } 

    // Parse the Content-Disposition to get the field name, etc.
    if (isset($headers['content-disposition'])) {
        $filename = null;
        preg_match(
            '/^(.+); *name="([^"]+)"(; *filename="([^"]+)")?/', 
            $headers['content-disposition'], 
            $matches
        );
        list(, $type, $name) = $matches;
        isset($matches[4]) and $filename = $matches[4]; 

        // handle your fields here
        switch ($name) {
            // this is a file upload
            case 'userfile':
                file_put_contents($filename, $body);
                break;

            // default for all other files is to populate $data
            default: 
                $data[$name] = substr($body, 0, strlen($body) - 2);
                break;
        } 
    }

}
return $data;

}

Upvotes: 2

Sabeer
Sabeer

Reputation: 4110

In CodeIgniter 4 use getRawInput which will retrieve data and convert it to an array.

$data = $request->getRawInput();

Upvotes: 3

francis94c
francis94c

Reputation: 84

Checkout this link in the official Code Igniter Docs Using the Input Stream for Custom Request Methods

This is the Code Igniter way to do it.

Just call the below if the body of the request is form-urlencoded

$var1 = $this->input->input_stream('var_key')
// Or 
$var1 = $this->security->xss_clean($this->input->input_stream('var_key'));

Upvotes: 1

Hamid Zandi
Hamid Zandi

Reputation: 2902

look this issue in github

PUT parameters only work in JSON format

https://github.com/chriskacerguis/codeigniter-restserver/issues/362

Upvotes: 2

Johnny2k
Johnny2k

Reputation: 163

You can try to detect the method type first and seperate the different cases. If your controller only handles REST functions it could be helpful to put get the required information in the constructor.

switch($_SERVER['REQUEST_METHOD']){
   case 'GET':
      $var_array=$this->input->get();
      ...
      break;
   case 'POST':
      $var_array=$this->input->post();
      ...
      break;
   case 'PUT':
   case 'DELETE':
      parse_str(file_get_contents("php://input"),$var_array);
      ...
      break;
   default:
      echo "I don't know how to handle this request.";
}

Upvotes: 6

jcolebrand
jcolebrand

Reputation: 16025

According to: http://net.tutsplus.com/tutorials/php/working-with-restful-services-in-codeigniter-2/ we should consult https://github.com/philsturgeon/codeigniter-restserver/blob/master/application/libraries/REST_Controller.php#L544 to see that this method:

/**
 * Detect method
 *
 * Detect which method (POST, PUT, GET, DELETE) is being used
 * 
 * @return string 
 */
protected function _detect_method() {
  $method = strtolower($this->input->server('REQUEST_METHOD'));

  if ($this->config->item('enable_emulate_request')) {
    if ($this->input->post('_method')) {
      $method = strtolower($this->input->post('_method'));
    } else if ($this->input->server('HTTP_X_HTTP_METHOD_OVERRIDE')) {
      $method = strtolower($this->input->server('HTTP_X_HTTP_METHOD_OVERRIDE'));
    }      
  }

  if (in_array($method, array('get', 'delete', 'post', 'put'))) {
    return $method;
  }

  return 'get';
}

looks to see if we've defined the HTTP header HTTP_X_HTTP_METHOD_OVERRIDE and it uses that in favor of the actual verb we've implemented on the web. To use this in a request you would specify the header X-HTTP-Method-Override: method (so X-HTTP-Method-Override: put) to generate a custom method override. Sometimes the framework expects X-HTTP-Method instead of X-HTTP-Method-Override so this varies by framework.

If you were doing such a request via jQuery, you would integrate this chunk into your ajax request:

beforeSend: function (XMLHttpRequest) {
   //Specify the HTTP method DELETE to perform a delete operation.
   XMLHttpRequest.setRequestHeader("X-HTTP-Method-Override", "DELETE");
}

Upvotes: 10

fire
fire

Reputation: 21531

CodeIgniter doesn't support reading incoming PUT requests and if it's not essential I would stick to GET/POST for your API as its probably not necessary.

If you do need to read PUT requests take a look at Accessing Incoming PUT Data from PHP.

Upvotes: -3

Related Questions