Trying to create a c++ PUT request with cURL with an object - c++

Recently I want to PUT an object with c++ curl.
Terminal command like this:
PUT /ObjectName HTTP/1.1
Content-Length:ContentLength
Content-Type: ContentType
Host: BucketName.oss-cn-hangzhou.aliyuncs.com
Date: GMT Date
Authorization: SignatureValue
My code:
curl_easy_setopt(curl, CURLOPT_UPLOAD, 1L);
curl_easy_setopt(curl, CURLOPT_URL, "https://tva******.oss*****.aliyuncs.com");
curl_easy_setopt(curl, CURLOPT_READDATA, hd_src);
curl_easy_setopt(curl, CURLOPT_INFILESIZE_LARGE, (curl_off_t)file_info.st_size);
auto size = to_string(file_info.st_size);
curl_slist* headerList = NULL;
headerList = curl_slist_append(headerList, ("Authorization: " + Authorization).c_str());
headerList = curl_slist_append(headerList, ("Date: " + finalTime).c_str());
headerList = curl_slist_append(headerList, ("Content-Type: application/octet-stream"));
headerList = curl_slist_append(headerList, ("Content-Length: " + size).c_str());
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headerList);
res = curl_easy_perform(curl);
But its effect is PUT HTTP/1.1 not PUT /ObjectName HTTP/1.1
I want to put an object ,but there is no object, so it puts a bucket.
How to make a request like PUT /ObjectName HTTP/1.1.

Related

Creating a shared link for a Dropbox file using curl & C++

I want to create a shared link for a dropbox file using curl & C++ on a windows 10 desktop.
I've already manage to upload the file to a dropbox folder using curl & C++.
When I try to create the link with command line it works with
curl -X POST https://api.dropboxapi.com/2/sharing/create_shared_link_with_settings --header "Authorization: Bearer <TOKEN>" --header "Content-Type: application/json" --data "{\"path\":\"path_of_the_file\"}"
but when I use this code to do the same in C++ it hangs at < HTTP/1.1 100 Continue
Here is my code :
CURL *curl;
CURLcode res;
curl = curl_easy_init();
if (curl) {
string readBuffer;
printf("Running curl test get shared link.\n");
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, FALSE); //no ssl
struct curl_slist *headers = NULL; // init to NULL is important
headers = curl_slist_append(headers, "Authorization: Bearer <TOKEN>");
headers = curl_slist_append(headers, "Content-Type: ");
headers = curl_slist_append(headers, "Dropbox-API-Arg: {\"path\":\"path_of_file\"}");
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
curl_easy_setopt(curl, CURLOPT_POST, true);
curl_easy_setopt(curl, CURLOPT_VERBOSE, true);
curl_easy_setopt(curl, CURLOPT_URL, "https://api.dropboxapi.com/2/sharing/create_shared_link_with_settings");
// Perform the request, res will get the return code
res = curl_easy_perform(curl);
// Check for errors
if (res != CURLE_OK)
fprintf(stderr, "curl_easy_perform() failed: %s\n",
curl_easy_strerror(res));
// always cleanup
curl_easy_cleanup(curl);
cout << readBuffer << endl;
printf("\nFinished curl test.\n");
}
curl_global_cleanup();
printf("Done get shared link!\n");
I've tried with content-type : application/json and adding fields but I can't reproduce what I'm doing with the command line
There are errors in the code, causing undefined behaviour.
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, FALSE);
curl_easy_setopt(curl, CURLOPT_POST, true);
curl_easy_setopt(curl, CURLOPT_VERBOSE, true);
cUrl has a C API, C does not have overloads. Thus curl_easy_setopt is a multi-arg function, and the third argument type depends on the second argument value. CURLOPT_SSL_VERIFYPEER and CURLOPT_VERBOSE require long values, you pass the values as int. The size of the third argument is important exactly like this is in *printf functions. The proper calls must be
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);
curl_easy_setopt(curl, CURLOPT_POST, 1L);
curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);
The second. 100 Continue means you have not passed the data for the POST request. The server received request and waits for further data. See
libcurl example - http-post.c.
I can't reproduce what I'm doing with the command line
Add the --libcurl to the command line for getting a C code performing the same actions as in the command line.
Thank you S.M. Here is the code that works
CURL *curl;
CURLcode res;
curl = curl_easy_init();
if (curl) {
string readBuffer;
printf("Running curl test get shared link.\n");
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L); //no ssl
struct curl_slist *headers = NULL; // init to NULL is important
headers = curl_slist_append(headers, "Authorization: Bearer <TOKEN>");
headers = curl_slist_append(headers, "Content-Type: application/json");
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
curl_easy_setopt(curl, CURLOPT_POST, 1L);
curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, "{\"path\":\"path_to_the_file"}");
curl_easy_setopt(curl, CURLOPT_URL, "https://api.dropboxapi.com/2/sharing/create_shared_link_with_settings");
// Perform the request, res will get the return code
res = curl_easy_perform(curl);
// Check for errors
if (res != CURLE_OK)
fprintf(stderr, "curl_easy_perform() failed: %s\n",
curl_easy_strerror(res));
// always cleanup
curl_easy_cleanup(curl);
cout << readBuffer << endl;
printf("\nFinished curl test.\n");
}
curl_global_cleanup();
printf("Done get shared link!\n");

I cant get the bittrex v3 api in C++ working

For the life of me I cannot get this to work. I have not been able to find example code for v3 of the Bittrex API so I have patched together what I've found for v1.1 and v3 in other programming languages.
I am using curl and openssl libraries.
I am getting a "URL using bad/illegal format or missing URL" error.
#include "../curl/curl.h"
#include <sha512.hh>
#include "hmac.h"
#include "sha.h"
string bittKey, bittSecret;
string timeStamp, hTTPMethod, uRI, requestBody, contentHash;
CURL *curl;
CURLcode res;
curl = curl_easy_init();
bittKey = "...";
bittSecret = "...";
timeStamp = std::to_string(time(nullptr));
uRI = "https://api.bittrex.com/v3/balances";
hTTPMethod = "GET";
requestBody = "";
contentHash = sw::sha512::calculate(requestBody);
string preSign = timeStamp + uRI + hTTPMethod + contentHash;
string apiSign = hmac_sha512(preSign, bittSecret);
struct curl_slist* headerList = NULL;
headerList = curl_slist_append(headerList, "Accept: application/json");
headerList = curl_slist_append(headerList, "Content-Type: application/json");
headerList = curl_slist_append(headerList, ("Api-Key: " + bittKey).c_str());
headerList = curl_slist_append(headerList, ("Api - Signature: " + apiSign).c_str());
headerList = curl_slist_append(headerList, ("Api-Timestamp: " + timeStamp).c_str());
headerList = curl_slist_append(headerList, ("Api-Content-Hash: " + contentHash).c_str());
curl_easy_setopt(curl, CURLOPT_URL, uRI);
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headerList);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &readBuffer);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallback);
res = curl_easy_perform(curl);
if (res != CURLE_OK)
fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(res));
curl_slist_free_all(headerList);
curl_easy_cleanup(curl);
After quite a long time of searching and debugging through the curl libraries the solution was quite simple.
curl_easy_setopt(curl, CURLOPT_URL, uRI.c_str());
Oh and the timestamp doesn't work the way I have it above. It works as follows:
using namespace std::chrono;
milliseconds ms = duration_cast<milliseconds>(
system_clock::now().time_since_epoch()
);
timeStamp = std::to_string(ms.count());
The API is working now.

Poloniex API "Invalid command" c++ libcurl

I'm trying to solve it for many hours but nothing going better...
int main() {
CURL *curl_handle = curl_easy_init();
if(curl_handle) {
string post_data="";
struct curl_slist *headers=NULL;
string command = "command=returnBalances&nonce=" + to_string(time(0));
cout<<command<<endl;
string Secret = "mySecretCode";
string Sign = "Sign: "+ hmac::get_hmac(Secret, command, hmac::TypeHash::SHA512);
cout<<Sign<<endl;
post_data += command;
headers = curl_slist_append(headers, "Content-Type: application/x-www-form-urlencoded");
headers = curl_slist_append(headers, "Key: myKey");
headers = curl_slist_append(headers, Sign.c_str());
curl_easy_setopt(curl_handle, CURLOPT_URL, "https://poloniex.com/tradingApi");
curl_easy_setopt(curl_handle, CURLOPT_POSTFIELDSIZE, post_data.length()+1);
curl_easy_setopt(curl_handle, CURLOPT_POSTFIELDS, post_data.c_str());
curl_easy_setopt(curl_handle, CURLOPT_HTTPHEADER, headers);
curl_easy_setopt(curl_handle, CURLOPT_SSL_VERIFYPEER, false);
curl_easy_setopt(curl_handle, CURLOPT_VERBOSE, 1L);
}
curl_easy_perform(curl_handle);
curl_easy_cleanup(curl_handle);
return 0;
}
This returns to me
{"error":"Invalid command."}
I checked hmac function result threw website and they are equal.
Some people said that adding
"Content-Type: application/x-www-form-urlencoded"
can solve this, but not at this time.
Console output:
> POST /tradingApi HTTP/2
Host: poloniex.com
accept: */*
content-type: application/x-www-form-urlencoded
key: myKey
sign: resultOfHmacFunc
content-length: 40
Solution was to change from CURLOPT_POSTFIELDS to CURLOPT_COPYPOSTFIELDS

error when creating folder on dropbox via libcurl

I am trying to make a c++ application that uses Dropbox. When I am trying to create a new folder I take the following error: {"error": "Not Found"} and "HTTP/1.1 404 Not Found".
I have followed the instruction of Dropbox's REST Api, so I have used the POST method. (I am not sure if I can use PUT, instead).
Here is my code:
void createDirectory(const char *new_Directory_Path)
{
string create_Directory_Url = "https://api.dropbox.com/1/fileops/create_folder/sandbox/test_folder";
CURL* curl = curl_easy_init();
if(!curl)
{
CURLcode res;
struct curl_slist *headers = NULL;
string my_header = "Authorization: OAuth oauth_version=\"1.0\", oauth_signature_method=\"PLAINTEXT\",
oauth_consumer_key=\""
+ m_consumer_key + "\", oauth_token=\"" + m_accessKey + "\", oauth_signature=\""
+ m_consumer_secret + "&" + m_accessSecret + "\"";
headers = curl_slist_append(headers, my_header.c_str());
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L);
curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);
curl_easy_setopt(curl, CURLOPT_POST, 1L);
curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 0);
curl_easy_setopt(curl, CURLOPT_URL, create_Directory_Url.c_str());
res = curl_easy_perform(curl);
curl_slist_free_all(headers);
curl_easy_cleanup(curl);
}
}
Please, does anyone have an idea about what am I doing wrong?
Looking at the documentation I belive you want to leave sandbox/test_folder off of the url and use root=sandbox & path=test_folder as form values.
Here is an example of submitting form parameters: http://curl.haxx.se/libcurl/c/postit2.html
EDIT:
I found another example, here: https://github.com/geersch/DropboxRESTApi/blob/master/src/part-3/README.md which seems to show the parameters being added to the url's query string rather than as form values. The doc page isn't clear. It just shows them as parameters but doesn't specify which kind.

curl: using multipart with post params

If I do
curl_easy_setopt(curl, CURLOPT_HTTPPOST, formpost);
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, post_params);
the server will do not see multipart, but if I coment the second line
curl_easy_setopt(curl, CURLOPT_HTTPPOST, formpost);
//curl_easy_setopt(curl, CURLOPT_POSTFIELDS, post_params);
it'll do.
What's wrong here?
UPD: So, now the question is, whether it's possible to put value to a param, so that that value was in POST parameters array on server-side? I'm trying
headers = curl_slist_append(headers, "Content-Disposition: form-data");
//action=upload
curl_formadd(&formpost,
&lastptr,
CURLFORM_COPYNAME, "action",
CURLFORM_COPYCONTENTS, "upload",
CURLFORM_CONTENTHEADER, headers,
CURLFORM_CONTENTTYPE, "Content-Type: multipart/form-data",
CURLFORM_END);
But that's not working!
Thank you in advance!
I ended up mostly following the example code here: http://curl.haxx.se/libcurl/c/multi-post.html
Here's a sample of the code that ended up working for me based on the curl example link:
...
CURL *curl;
curl_mime *form;
curl = curl_easy_init();
/* Set the headers for the request. */
scoped_curl_slist headers;
headers.list = NULL;
string session_header = "Authorization: Bearer " + token;
headers.list = curl_slist_append(headers.list, session_header.c_str());
headers.list = curl_slist_append(headers.list, "cache-control: no-cache");
headers.list = curl_slist_append(headers.list, "Content-Type: multipart/form-data");
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers.list);
curl_easy_setopt(curl, CURLOPT_URL, "your_url.com");
/* Create the form */
form = curl_mime_init(curl);
/* Fill in the file upload field */
curl_mimepart *field = curl_mime_addpart(form);
curl_mime_name(field, "upload");
curl_mime_filedata(field, "C:/file_name.txt");
/* Fill in the filename field */
field = curl_mime_addpart(form);
curl_mime_name(field, "name");
curl_mime_data(field, "file_name.txt", CURL_ZERO_TERMINATED);
curl_easy_setopt(curl, CURLOPT_MIMEPOST, form);
CURLcode result = curl_easy_perform(curl);
...
curl_mime_free(form);
curl_easy_cleanup(curl);
curl_slist_free_all(headers);