Solicitud PHP CURL DELETE

100

Estoy tratando de hacer una solicitud http DELETE usando PHP y cURL.

He leído cómo hacerlo en muchos lugares, pero nada parece funcionar para mí.

Así es como lo hago:

public function curl_req($path,$json,$req)
{
    $ch = curl_init($this->__url.$path);
    $data = json_encode($json);
    curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $req);
    curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: application/json','Content-Length: ' . strlen($data)));
    $result = curl_exec($ch);
    $result = json_decode($result);
    return $result;
}

Luego sigo adelante y uso mi función:

public function deleteUser($extid)
{
    $path = "/rest/user/".$extid."/;token=".$this->__token;
    $result = $this->curl_req($path,"","DELETE");
    return $result;

}

Esto me da un ERROR de servidor interno HTTP. En mis otras funciones usando el mismo método curl_req con GET y POST, todo va bien.

Entonces, ¿qué estoy haciendo mal?

Bolli
fuente
3
El error interno del servidor significa que hubo un problema con el script que recibió su solicitud.
Brad
Gracias Brad. Lo sé, supongo que es porque no se envía como solicitud DELETE. Si utilizo un complemento de cliente REST para Firefox y envío exactamente la misma solicitud con DELETE, funciona bien. Entonces parece que cURL no está enviando la solicitud como DELETE.
Bolli
Gracias Marc, pero parece que está haciendo lo mismo que yo. ¿Es imposible enviar solicitudes DELETE con PHP? Si hay otra forma sin cURL, estoy dispuesto a usarla también.
Bolli

Respuestas:

216

Finalmente resolví esto yo mismo. Si alguien más tiene este problema, aquí está mi solución:

Creé un nuevo método:

public function curl_del($path)
{
    $url = $this->__url.$path;
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "DELETE");
    $result = curl_exec($ch);
    $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
    curl_close($ch);

    return $result;
}

Actualización 2

Dado que esto parece ayudar a algunas personas, aquí está mi método final curl DELETE, que devuelve la respuesta HTTP en el objeto decodificado JSON:

  /**
 * @desc    Do a DELETE request with cURL
 *
 * @param   string $path   path that goes after the URL fx. "/user/login"
 * @param   array  $json   If you need to send some json with your request.
 *                         For me delete requests are always blank
 * @return  Obj    $result HTTP response from REST interface in JSON decoded.
 */
public function curl_del($path, $json = '')
{
    $url = $this->__url.$path;
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "DELETE");
    curl_setopt($ch, CURLOPT_POSTFIELDS, $json);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    $result = curl_exec($ch);
    $result = json_decode($result);
    curl_close($ch);

    return $result;
}
Bolli
fuente
¿Puede decirme cómo hacemos una llamada ajax al php (método: eliminar) que contiene este código curl de eliminación y pasarle el valor de ajax?
user1788736
@ user1788736 No soy bueno en Ajax, pero supongo que podrías crear un archivo PHP que ejecute este método, y con Ajax enviar tus datos usando POST a ese archivo PHP. Si cree que el método anterior es confuso, vuelva a mirar. $ url es simplemente el servidor con el que necesita hablar ( someserver.com ) y $ path es lo que sigue a la URL (/ algo /). La única razón por la que los divido es porque necesito enviar al mismo servidor todo el tiempo, pero con rutas dinámicas. Espero que tenga sentido.
Bolli
¿No necesita encabezado?
er.irfankhan11
Estoy usando el mismo código, y Paypal devuelve el código http: 204 significa eliminarlo correctamente. pero he recibido 400 todo el tiempo.
er.irfankhan11
1
@kuttoozz que es una variable privada en mi clase. Es simplemente la URL a la que necesita realizar solicitudes. Podría ser algo como api.someurl.com y $ path es lo que va después de esa URL (/ something /). Simplemente puede cambiar ese valor a su URL o eliminarlo e incluir la URL completa en la variable $ path. ¿Tiene sentido?
Bolli
19

Para llamar a GET, POST, DELETE, PUT Todo tipo de solicitud, he creado una función común

function CallAPI($method, $api, $data) {
    $url = "http://localhost:82/slimdemo/RESTAPI/" . $api;
    $curl = curl_init($url);
    curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);

    switch ($method) {
        case "GET":
            curl_setopt($curl, CURLOPT_POSTFIELDS, json_encode($data));
            curl_setopt($curl, CURLOPT_CUSTOMREQUEST, "GET");
            break;
        case "POST":
            curl_setopt($curl, CURLOPT_POSTFIELDS, json_encode($data));
            curl_setopt($curl, CURLOPT_CUSTOMREQUEST, "POST");
            break;
        case "PUT":
            curl_setopt($curl, CURLOPT_POSTFIELDS, json_encode($data));
            curl_setopt($curl, CURLOPT_CUSTOMREQUEST, "PUT");
            break;
        case "DELETE":
            curl_setopt($curl, CURLOPT_CUSTOMREQUEST, "DELETE"); 
            curl_setopt($curl, CURLOPT_POSTFIELDS, json_encode($data));
            break;
    }
    $response = curl_exec($curl);
    $data = json_decode($response);

    /* Check for 404 (file not found). */
    $httpCode = curl_getinfo($curl, CURLINFO_HTTP_CODE);
    // Check the HTTP Status code
    switch ($httpCode) {
        case 200:
            $error_status = "200: Success";
            return ($data);
            break;
        case 404:
            $error_status = "404: API Not found";
            break;
        case 500:
            $error_status = "500: servers replied with an error.";
            break;
        case 502:
            $error_status = "502: servers may be down or being upgraded. Hopefully they'll be OK soon!";
            break;
        case 503:
            $error_status = "503: service unavailable. Hopefully they'll be OK soon!";
            break;
        default:
            $error_status = "Undocumented error: " . $httpCode . " : " . curl_error($curl);
            break;
    }
    curl_close($curl);
    echo $error_status;
    die;
}

Método de eliminación de LLAMADA

$data = array('id'=>$_GET['did']);
$result = CallAPI('DELETE', "DeleteCategory", $data);

Método de publicación CALL

$data = array('title'=>$_POST['txtcategory'],'description'=>$_POST['txtdesc']);
$result = CallAPI('POST', "InsertCategory", $data);

LLAME Obtener método

$data = array('id'=>$_GET['eid']);
$result = CallAPI('GET', "GetCategoryById", $data);

CALL Método Put

$data = array('id'=>$_REQUEST['eid'],m'title'=>$_REQUEST['txtcategory'],'description'=>$_REQUEST['txtdesc']);
$result = CallAPI('POST', "UpdateCategory", $data);
Juned Ansari
fuente
bien hecho. Solo una nota: el código de respuesta http para eliminar es 204. Creo que debería considerar todos los códigos 20x como una buena respuesta :)
ryuujin
0

Mi propia solicitud de clase con autenticación wsse

class Request {

    protected $_url;
    protected $_username;
    protected $_apiKey;

    public function __construct($url, $username, $apiUserKey) {
        $this->_url = $url;     
        $this->_username = $username;
        $this->_apiKey = $apiUserKey;
    }

    public function getHeader() {
        $nonce = uniqid();
        $created = date('c');
        $digest = base64_encode(sha1(base64_decode($nonce) . $created . $this->_apiKey, true));

        $wsseHeader = "Authorization: WSSE profile=\"UsernameToken\"\n";
        $wsseHeader .= sprintf(
            'X-WSSE: UsernameToken Username="%s", PasswordDigest="%s", Nonce="%s", Created="%s"', $this->_username, $digest, $nonce, $created
        );

        return $wsseHeader;
    }

    public function curl_req($path, $verb=NULL, $data=array()) {                    

        $wsseHeader[] = "Accept: application/vnd.api+json";
        $wsseHeader[] = $this->getHeader();

        $options = array(
            CURLOPT_URL => $this->_url . $path,
            CURLOPT_HTTPHEADER => $wsseHeader,
            CURLOPT_RETURNTRANSFER => true, 
            CURLOPT_HEADER => false             
        );                  

        if( !empty($data) ) {
            $options += array(
                CURLOPT_POSTFIELDS => $data,
                CURLOPT_SAFE_UPLOAD => true
            );                          
        }

        if( isset($verb) ) {
            $options += array(CURLOPT_CUSTOMREQUEST => $verb);                          
        }

        $ch = curl_init();
        curl_setopt_array($ch, $options);
        $result = curl_exec($ch);                   

        if(false === $result ) {
            echo curl_error($ch);
        }
        curl_close($ch);

        return $result; 
    }
}
Adriwan Kenoby
fuente
use + = instaead de array_merge
Adriwan Kenoby
Probablemente funcione, pero es una solución innecesariamente compleja al problema.
Samuel Lindblom
0

switch ($ método) {case "GET": curl_setopt ($ curl, CURLOPT_CUSTOMREQUEST, "GET"); descanso; case "POST": curl_setopt ($ curl, CURLOPT_CUSTOMREQUEST, "POST"); descanso; case "PUT": curl_setopt ($ curl, CURLOPT_CUSTOMREQUEST, "PUT"); descanso; case "DELETE": curl_setopt ($ curl, CURLOPT_CUSTOMREQUEST, "DELETE"); descanso; }

Peter Ahumuza
fuente
-19
    $json empty

public function deleteUser($extid)
{
    $path = "/rest/user/".$extid."/;token=".$this->__token;
    $result = $this->curl_req($path,"**$json**","DELETE");
    return $result;

}
GRUPO UZSTYLE
fuente
Gracias. En esta llamada REST en particular, la parte JSON debe estar vacía, por lo que esto no es un problema. Pero gracias de todos modos
Bolli
¿Qué $json emptysignifica aquí? De todos modos, no está dentro del alcance dentro de esta función, por lo que el uso de $jsonno hará nada.
halfer
He pedido que se elimine esta respuesta, pero un moderador ha dicho que no. El cartel de esta respuesta no se ha registrado desde 2014 de todos modos.
halfer