Pedido PHP CURL DELETE

100

Estou tentando fazer uma solicitação DELETE http usando PHP e cURL.

Eu li como fazer isso em muitos lugares, mas nada parece funcionar para mim.

É assim que eu faço:

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;
}

Eu então sigo em frente e uso minha função:

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

}

Isso me dá um erro de servidor interno HTTP. Em minhas outras funções usando o mesmo método curl_req com GET e POST, tudo vai bem.

Então, o que estou fazendo de errado?

Bolli
fonte
3
O erro interno do servidor significa que houve um problema com o script que recebeu sua solicitação.
Brad
Obrigado Brad - Eu sei, acho que é porque não é enviado como pedido DELETE. Se eu usar um plugin de cliente REST para Firefox e enviar exatamente a mesma solicitação com DELETE, ele funciona bem. Portanto, parece que cURL não está enviando a solicitação como DELETE.
Bolli
Obrigado Marc, mas parece que ele está fazendo a mesma coisa que eu? É impossível enviar solicitações DELETE com PHP? Se houver outra maneira sem cURL, estou aberto para usá-la também.
Bolli

Respostas:

216

Eu finalmente resolvi isso sozinho. Se alguém mais está tendo esse problema, aqui está minha solução:

Eu criei um novo 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;
}

Atualização 2

Como isso parece ajudar algumas pessoas, aqui está meu método curl DELETE final, que retorna a resposta HTTP no objeto decodificado em 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
fonte
você pode me dizer como fazemos a chamada ajax para o php (método: delete) que contém este código delete curl e passa o valor de ajax?
user1788736
@ user1788736 Não sou bom em Ajax, mas acho que você poderia criar um arquivo PHP que execute esse método e, com Ajax, enviar seus dados usando POST para esse arquivo PHP. Se você acha que o método acima é confuso, olhe novamente. $ url é simplesmente o servidor com o qual você precisa falar ( someserver.com ) e $ path é o material após a URL (/ something /). O único motivo pelo qual divido isso, é porque preciso enviar para o mesmo servidor o tempo todo, mas com caminhos dinâmicos. Espero que isso faça sentido.
Bolli
Não precisa de cabeçalho?
er.irfankhan11
Estou usando o mesmo código, e o código HTTP de retorno do Paypal: 204 significa excluir com sucesso. mas recebi 400 o tempo todo.
er.irfankhan11,
1
@kuttoozz que é uma variável privada na minha classe. É simplesmente o URL para o qual você precisa fazer solicitações. Pode ser algo como api.someurl.com e $ path é o que vem depois desse url (/ something /). Você pode simplesmente alterar esse valor para o seu URL ou removê-lo e incluir o URL completo na variável $ path. Isso faz sentido?
Bolli
19

Para chamar GET, POST, DELETE, PUT, todo tipo de solicitação, criei uma função comum

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 exclusão CALL

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

Método de postagem CALL

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

CALL Get Method

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

Método CALL Put

$data = array('id'=>$_REQUEST['eid'],m'title'=>$_REQUEST['txtcategory'],'description'=>$_REQUEST['txtdesc']);
$result = CallAPI('POST', "UpdateCategory", $data);
Juned Ansari
fonte
bem feito. Apenas uma observação: o código de resposta http para exclusão é 204. Acho que você deve considerar todos os códigos 20x como uma boa resposta :)
ryuujin
0

Minha própria solicitação de classe com autenticação 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
fonte
use + = instaead de array_merge
Adriwan Kenoby
Isso provavelmente funciona, mas é uma solução desnecessariamente complexa para o problema.
Samuel Lindblom
0

switch ($ method) {case "GET": curl_setopt ($ curl, CURLOPT_CUSTOMREQUEST, "GET"); pausa; case "POST": curl_setopt ($ curl, CURLOPT_CUSTOMREQUEST, "POST"); pausa; case "PUT": curl_setopt ($ curl, CURLOPT_CUSTOMREQUEST, "PUT"); pausa; case "DELETE": curl_setopt ($ curl, CURLOPT_CUSTOMREQUEST, "DELETE"); pausa; }

Peter Ahumuza
fonte
-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
fonte
Obrigado. Nesta chamada REST específica, a parte JSON precisa estar vazia, então isso não é problema. Mas obrigado de qualquer maneira
Bolli
O que $json emptysignifica aqui? Não está no escopo desta função de qualquer maneira, então o uso de $jsonnão fará nada.
Halfer de
Eu pedi que esta resposta fosse excluída, mas um moderador disse que não. O autor desta resposta não faz login desde 2014 de qualquer maneira.
Halfer de