Is it possible to send data in the body and in the url using the PUT and libcurl method?

Asked

Viewed 260 times

0

I’m trying to send the data both in the URL and in the body using PUT the idea was to make it work exactly like the POST method, but being the PUT method.

This is because I see many requests where the url would be for example /book/ and in the body would have a JSON (with the data used to update the element of that id).

I’m trying to do this using libcurl in C++, but despite the REQUEST_METHOD come PUT i do not receive the data. The implementation of POST, GET and DELETE send the data. I am having problems exclusively with PUT at first.

// Code in C++

I9CorpResponse * I9CorpRequest::request(int method, const char *url, const char *body, I9CorpRequestOptions * options) {
    I9CorpResponse * response = nullptr;
    long statusCode;
    CURLcode res;
    CURL *curl;
    char mBufferHeader[I9CORP_BUFFER_MESSAGE];
    char mTmp[I9CORP_BUFFER_MESSAGE];
    std::map<std::string, char *> mHeaders;
    struct curl_slist *chunk = nullptr;
    char *mBufferParam = nullptr;

    std::string content;

    curl = curl_easy_init();
    if (curl == NULL) {
        return nullptr;
    }

    curl_easy_setopt(curl, CURLOPT_URL, url);
    /* example.com is redirected, so we tell libcurl to follow redirection */
    curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);

    if (options != nullptr) {
        std::map<std::string, char *>::iterator it;
        mHeaders = options->getHeaders();
        it = mHeaders.begin();
        for (it = mHeaders.begin(); it != mHeaders.end(); ++it) {
            snprintf(mBufferHeader, I9CORP_BUFFER_MESSAGE, "%s: %s\0"
                    , it->first.c_str()
                    , it->second);
            chunk = curl_slist_append(chunk, mBufferHeader);
        }
        if (chunk != nullptr) {
            res = curl_easy_setopt(curl, CURLOPT_HTTPHEADER, chunk);
        }
        if (body == nullptr) {
            mBufferParam = options->createQueryParams();
        }
    }

    switch (method) {
        case METHOD_GET:
            snprintf(mTmp, I9CORP_BUFFER_MESSAGE, "%s?%s\0", url, mBufferParam);
            curl_easy_setopt(curl, CURLOPT_URL, mTmp);
            curl_easy_setopt(curl, CURLOPT_HTTPGET, 1L);
            break;
        case METHOD_POST:
            curl_easy_setopt(curl, CURLOPT_POST, 1L);
            if (body != nullptr) {
                curl_easy_setopt(curl, CURLOPT_POSTFIELDS, body);
            } else if (mBufferParam != nullptr) {
                curl_easy_setopt(curl, CURLOPT_POSTFIELDS, mBufferParam);
            }
            break;
        case METHOD_PUT:            
            curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "PUT");
            if (body != nullptr) {
                curl_easy_setopt(curl, CURLOPT_POSTFIELDS, body);
            } else if (mBufferParam != nullptr) {
                curl_easy_setopt(curl, CURLOPT_POSTFIELDS, mBufferParam);
            }
            break;
        case METHOD_DELETE:
            curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "DELETE");
            snprintf(mTmp, I9CORP_BUFFER_MESSAGE, "%s?%s\0", url, mBufferParam);
            curl_easy_setopt(curl, CURLOPT_URL, mTmp);
            break;
    }

    curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, I9CorpRequest::callbackDataWrite);
    curl_easy_setopt(curl, CURLOPT_WRITEDATA, &content);

    /* Perform the request, res will get the return code */
    res = curl_easy_perform(curl);
    if (mBufferParam != nullptr) {
        free(mBufferParam);
    }

    /* Check for errors */
    if (res == CURLE_HTTP_RETURNED_ERROR) {
        response = new I9CorpResponse();
        curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &statusCode);
        response->setStatusCode(statusCode);
    } else if (res != CURLE_OK) {
        fprintf(stderr, "curl_easy_perform() failed: %s\n",
                curl_easy_strerror(res));
    } else {
        response = new I9CorpResponse();
        curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &statusCode);
        response->setStatusCode(statusCode);
        response->setContent(content.c_str());
    }

    /* free the custom headers */
    if (chunk != nullptr) {
        curl_slist_free_all(chunk);
    }

    /* always cleanup */
    curl_easy_cleanup(curl);
    return response;
}

In the examples I’m doing the body is nullptr and mBufferParam has content

"lastname=Brito&name=Sileno&username=test"

To test I wrote the following code in PHP, but I can’t read the values, as they don’t arrive in php.

<?php

var_export(
    array(
        'server'=> $_SERVER,
        'get'=> $_GET,
        'post'=> $_POST,
        'request'=> $_REQUEST
    )

);

1 answer

0

I’ll put as an answer because the comment area is limited.

First, test with Curl in the command line. If it works on the command line then it will work with lib.

Second, if you are wanting to send Forms via PUT instead of POST, I do not know if it will work, I think only the web people could say something, my guess is it will give problems.

Thirdly, it is possible to upload data via PUT, I have already done this.
But the way to specify the method I used was different, it was not CUSTOMREQUEST. Below:

// avisa ao curl que vai ser feito um upload (vai ser usado o metodo PUT)

static int setupUploadMethod(CURL* curl)
{
   if (CURLcode cc = curl_easy_setopt(curl, CURLOPT_UPLOAD, 1))
   {
      int err = int(cc);
      log("...", err);
      return err;
   }

   return OK;
}

Browser other questions tagged

You are not signed in. Login or sign up in order to post.