How to send JSON data to a REST API? - c++

I'm sending data to a Wordpress site with the WooCommerce plugin installed using libcurl in C++ and the WooCommerce REST API. The data seems to get sent but the expected result is not shown on the website. The purpose of it is to update (modify) the product. My code is based on the WooCommerce documentation, found here.
I have managed to get the CURLOPT_VERBOSE text from the program in a separate txt file.
Here is my C++ code using cURL :
std::string URL = main_domain + "wp-json/wc/v3/products/" + product_id + "?consumer_key=" + consumer_key + "&consumer_secret=" + consumer_secret;
curl_slist* headers = NULL;
headers = curl_slist_append(headers, "Transfer-Encoding: chunked");
headers = curl_slist_append(headers, "Accept:application/json");
headers = curl_slist_append(headers, "Content-Type:application/json");
headers = curl_slist_append(headers, "charsets: utf-8");
// log file
FILE* filep = fopen("logfichier.txt", "w");
std::string toUpdate = "{\"id\":\"" + product_id + ",\"name\":\"" + product_name + "\",\"description\":\"" + product_description + "\",\"price\":\"" + product_price + "\"}";
curl_global_init(CURL_GLOBAL_ALL);
curl = curl_easy_init();
if (curl) {
readBuffer = "";
curl_easy_setopt(curl, CURLOPT_URL, URL.c_str());
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "PUT");
curl_easy_setopt(curl, CURLOPT_POST, 1);
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, toUpdate.c_str());
curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, toUpdate.length());
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallback);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &readBuffer);
curl_easy_setopt(curl, CURLOPT_VERBOSE, true);
curl_easy_setopt(curl, CURLOPT_STDERR, filep);
res = curl_easy_perform(curl);
// Check for errors
if (res != CURLE_OK) {
// error handling and cleanup
}
else {
// code and cleanup
}
}
else {
// error handling and cleanup
}
I've literally put every header found on the internet that seemed relevant to what i'm trying to acomplish in my code.
Here is the returned debug text :
* STATE: INIT => CONNECT handle 0x10870278; line 1428 (connection #-5000)
* Added connection 0. The cache now contains 1 members
* STATE: CONNECT => WAITRESOLVE handle 0x10870278; line 1464 (connection #0)
* Trying 192.XX.XX.XX...
* TCP_NODELAY set
* STATE: WAITRESOLVE => WAITCONNECT handle 0x10870278; line 1545 (connection #0)
* Connected to mywebsite.com (192.XX.XX.XX) port 443 (#0)
* STATE: WAITCONNECT => SENDPROTOCONNECT handle 0x10870278; line 1599 (connection #0)
* Marked for [keep alive]: HTTP default
* schannel: SSL/TLS connection with mywebsite.com port 443 (step 1/3)
* schannel: checking server certificate revocation
* schannel: sending initial handshake data: sending 176 bytes...
// (here was just a bunch of connexion attemps log text...)
* schannel: SSL/TLS handshake complete
* schannel: SSL/TLS connection with mywebsite.com port 443 (step 3/3)
* schannel: stored credential handle in session cache
* STATE: PROTOCONNECT => DO handle 0x10870278; line 1634 (connection #0)
> PUT /wp-json/wc/v3/products/111867?consumer_key=(the actual key)&consumer_secret=(the actual secret) HTTP/1.1
Host: mywebsite.com
Transfer-Encoding: chunked
Accept:application/json
Content-Type:application/json
charsets: utf-8
4b
* upload completely sent off: 82 out of 75 bytes
* STATE: DO => DO_DONE handle 0x10870278; line 1696 (connection #0)
* STATE: DO_DONE => WAITPERFORM handle 0x10870278; line 1823 (connection #0)
* STATE: WAITPERFORM => PERFORM handle 0x10870278; line 1838 (connection #0)
* schannel: client wants to read 16384 bytes
* schannel: encdata_buffer resized 17408
* schannel: encrypted data buffer: offset 0 length 17408
// (a few decrypting data attempts...)
* schannel: decrypted data returned 536
* schannel: decrypted data buffer: offset 0 length 16384
* HTTP 1.1 or later with persistent connection, pipelining supported
< HTTP/1.1 200 OK
< Date: Tue, 18 Jun 2019 15:27:42 GMT
* Server Apache is not blacklisted
< Server: Apache
< X-Robots-Tag: noindex
< Link: <https://mywebsite.com/wp-json/>; rel="https://api.w.org/"
< X-Content-Type-Options: nosniff
< Access-Control-Expose-Headers: X-WP-Total, X-WP-TotalPages
< Access-Control-Allow-Headers: Authorization, Content-Type
< Expires: Wed, 11 Jan 1984 05:00:00 GMT
< Cache-Control: no-transform, no-cache, must-revalidate, max-age=0
< Allow: GET, POST, PUT, PATCH, DELETE
< Transfer-Encoding: chunked
< Content-Type: application/json; charset=UTF-8
<
* schannel: client wants to read 16384 bytes
* schannel: encrypted data buffer: offset 835 length 17408
// (a few decrypting data attempts...)
* schannel: decrypted data returned 1986
* schannel: decrypted data buffer: offset 0 length 16384
* STATE: PERFORM => DONE handle 0x10870278; line 2011 (connection #0)
* multi_done
* Connection #0 to host axanti.info left intact
I took out a few redundant part from the original text and kept what I think is the main piece of information. It seems that my JSON data is actually sent to the server but the intended result doesn't show up on my website (a product should be modified but it's actually not).
Is there any way this code could be wrong ? Or is the problem on the server side ? Because I litteraly apply the same stuff that is mentioned in the official documentation.

Looks like your payload if off. The id portion is redundant, as you're already specifying the product to update via the URL, so you can drop that. Additionally, you're attempting to set the price incorrectly. Per the REST docs, you need to use the regular_price attribute instead of price (price is read only). The proper payload should look like this:
{
name: 'My product name',
description: 'my product description',
regular_price' : '3.50',
}

Related

How to download compressed files using the curl C API?

I want to download a compressed file from a URL using libcurl C API. I have the following code:
// CurlGet.h
#include <cstddef>
#include <cstdlib>
#include <cstring>
#include <curl/curl.h>
struct memory {
char *response;
size_t size;
};
size_t callBackWrite(void *data, size_t size, size_t nmemb, void *userp) {
size_t written = fwrite(data, size, nmemb, (FILE *) userp);
return written;
}
int curlGetC(const char *url, const char* output_filename) {
CURL *curl_handle;
curl_global_init(CURL_GLOBAL_ALL);
/* init the curl session */
curl_handle = curl_easy_init();
if (!curl_handle) {
throw std::logic_error("You no curl");
}
/* set URL to get here */
curl_easy_setopt(curl_handle, CURLOPT_URL, url);
/* Switch on full protocol/debug output while testing */
curl_easy_setopt(curl_handle, CURLOPT_VERBOSE, 1L);
/* disable progress meter, set to 0L to enable it */
curl_easy_setopt(curl_handle, CURLOPT_NOPROGRESS, 0L);
/* send all data to this function */
curl_easy_setopt(curl_handle, CURLOPT_WRITEFUNCTION, callBackWrite);
/* open the file */
FILE *f = fopen(output_filename, "wb");
if (!f) {
throw std::invalid_argument("You no got file");
}
/* write the page body to this file handle */
curl_easy_setopt(curl_handle, CURLOPT_WRITEDATA, f);
/* get it! */
curl_easy_perform(curl_handle);
/* close the header file */
fclose(f);
/* cleanup curl stuff */
curl_easy_cleanup(curl_handle);
curl_global_cleanup();
return 0;
}
Then using this code to download a web page works as expected but downloading an omex file (which is actually just a zip file with the omex extension name) does not:
#include "CurlGet.h"
#include <iostream>
// works as expected
std::string url1 = "https://isocpp.org/wiki/faq/mixing-c-and-cpp";
std::string output_filename1 = "/mnt/d/libsemsim/semsim/example.html";
curlGetC(url1_.c_str(), output_filename1_.c_str());
// downloaded file is 0 bytes.
std::string url2 = "https://auckland.figshare.com/ndownloader/files/17432333";
std::string output_filename2 = "/mnt/d/libsemsim/semsim/example.omex";
curlGetC(url2_.c_str(), output_filename2_.c_str());
Could anybody suggest how to modify my code to get it to download the compressed file?
edit : Showing the verbose traces:
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
0 0 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0* Trying 52.48.88.255...
* TCP_NODELAY set
* Connected to auckland.figshare.com (52.48.88.255) port 443 (#0)
* ALPN, offering http/1.1
* successfully set certificate verify locations:
* CAfile: /etc/ssl/certs/ca-certificates.crt
CApath: /etc/ssl/certs
* SSL connection using TLSv1.2 / ECDHE-RSA-AES128-GCM-SHA256
* ALPN, server accepted to use http/1.1
* Server certificate:
* subject: C=GB; L=London; O=figshare LLP; CN=*.figshare.com
* start date: Mar 20 00:00:00 2019 GMT
* expire date: Jul 9 12:00:00 2020 GMT
* subjectAltName: host "auckland.figshare.com" matched cert's "*.figshare.com"
* issuer: C=US; O=DigiCert Inc; CN=DigiCert SHA2 Secure Server CA
* SSL certificate verify ok.
> GET /ndownloader/files/17432333 HTTP/1.1
Host: auckland.figshare.com
Accept: */*
< HTTP/1.1 302 Found
< Date: Sun, 12 Apr 2020 10:43:10 GMT
< Content-Type: application/octet-stream
< Content-Length: 0
< Connection: keep-alive
< Server: nginx
< X-Storage-Protocol: https
< X-Filename: BIOMD0000000204_new.omex
< Location: https://objectext.auckland.ac.nz/figshare/17432333/BIOMD0000000204_new.omex
< X-Storage-Host: objectext.auckland.ac.nz
< X-Storage-File: 17432333/BIOMD0000000204_new.omex
< X-Storage-Bucket: figshare
< Content-Disposition: attachment;filename=BIOMD0000000204_new.omex
< Cache-Control: no-cache, no-store
< Set-Cookie: fig_tracker_client=0975a192-4ec5-4a63-a800-c598eb7ca6b5; Max-Age=31536000; Path=/; expires=Mon, 12-Apr-2021 10:43:10 GMT; secure; HttpOnly
< X-Robots-Tag: noindex
< X-Frame-Options: SAMEORIGIN
< X-XSS-Protection: 1; mode=block
< Strict-Transport-Security: max-age=31536000; includeSubDomains;
< Cache-Control: public, must-revalidate, proxy-revalidate
< Access-Control-Allow-Credentials: true
< Access-Control-Allow-Methods: GET, OPTIONS
< Access-Control-Allow-Headers: Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Authorization,Range
< Access-Control-Expose-Headers: Location,Accept-Ranges,Content-Encoding,Content-Length,Content-Range
<
0 0 0 0 0 0 0 0 --:--:-- 0:00:01 --:--:-- 0
* Connection #0 to host auckland.figshare.com left intact
This really has nothing to do with the fact that the traget file is compressed. Zip files are archives whose components are compressed individually; it is not possible to decompress a zip file into a single meaningful object. That's different from gzipped tar archives, for example. (However it is not generally desirable for a user agent to automatically decompress a .tgz file into a .tar file, even though it could.)
Your problem stems from the fact that you didn't provide the full URI for the file. The web server responded by sending a redirect (302) return code. That tells the user agent to make a new request for the resource, using the URI provided in the Location response header.
You need to tell libcurl to follow redirects.
curl_easy_setopt(curl_handle, CURLOPT_FOLLOWLOCATION, 1L);
302 redirects differ from 301 redirects in that the redirection is marked as temporary. The 301 return code suggests to the user agent that it should remember the redirection and not attempt to use the original URL in the future. A 302 response should not be cached; it might, for example, be used to provide the location of what is currently the most recent version of a resource.
here is (probably) what happened:
You sent a request without the Accept-Encoding header, the server (foolishly, imo) assumed that since you didn't specify any specific transfer encodings, you probably support gzip.. (sounds stupid, i know, but the proper way to say "i dont support any transfer encodings" is to send the header Accept-Encoding: identity, but you didn't do that), and the server decided to answer with Content-Encoding: gzip, which your code ignored. what happens next is that gzip-compressed data was saved in your "output_filename".
to tell curl to automatically deal with encodings (which is the easiest solution, the vast majority of the time), just set CURLOPT_ACCEPT_ENCODING to emptystring, this tells curl to attempt to do the tansfer compressed, and automatically decompress the response before writing it:
curl_easy_setopt(curl_handle, CURLOPT_ACCEPT_ENCODING, "");
that should fix your problem. now curl will send a header looking like Accept-Encoding: gzip, deflate, br (the exact compression algorithms sent will depend on what your libcurl was compiled to support), and the server will choose 1 of those encodings, or if the server doesn't support any of the encodings your libcurl supports, the server should send the data uncompressed,
and curl in turn will auto-decompress the data before sending it to CURLOPT_WRITEFUNCTION
you can find relevant documentation here: https://curl.haxx.se/libcurl/c/CURLOPT_ACCEPT_ENCODING.html

Google cloud functions : All criteria for calling Http triggered cloud functions from outside cloud project (browser or c# client)

I have written Google cloud function (HTTP trigger). It tests successfully within the google cloud interface. Now I need to call it from Unity Game (C# .Net core).
First I tried to run it from browser. I took URL shown in Google cloud function interface. It does not work. I do not get stackdriver log (it does not even hit the URL?).
Is it because it needs oauth 2.0 token?
I am creating Http request , embedding JSON
request.ContentType = "application/json";
request.Method = "POST";
request.Headers["Authorization"] = "Bearer " + token;
//token obtained from oauth 2.0 JWT call
byte[] JsonContentBytes = Encoding.UTF8.GetBytes(strjsonReqContent);
// my Json object. requestJSON.ToString());
request.ContentLength = JsonContentBytes.Length;
Here I tried with Oauth 2.0 token as well. (It works for storage API. My service account for cloud function has project editor access)
I saw one post about using cloud function from outside the cloud project. It did not solve my problem.
Please let me know all the criteria for using cloud functions from outside the cloud project.
EDIT1:
Thanks for the suggestion. Here is the log from Curl execution. I am not used to web debugging. Please suggest what should I check further. I could make out that it is 'Bad Request'. The URL is the one I picked from cloud function console.
>curl -v -X POST https://us-central1- myproject.cloudfunctions.net/myfunctiontest -H "Content-Type:application/json" -d '{"username":"myemail#mydomain.com","password":"password1"}'
Note: Unnecessary use of -X or --request, POST is already inferred.
* Trying 172.217.163.174...
* TCP_NODELAY set
* Connected to us-central1-myproject.cloudfunctions.net (172.217.163.174) port 443 (#0)
* schannel: SSL/TLS connection with us-central1-myproject.cloudfunctions.net port 443 (step 1/3)
* schannel: checking server certificate revocation
* schannel: sending initial handshake data: sending 212 bytes...
* schannel: sent initial handshake data: sent 212 bytes
* schannel: SSL/TLS connection with us-central1-myproject.cloudfunctions.net port 443 (step 2/3)
* schannel: failed to receive handshake, need more data
* schannel: SSL/TLS connection with us-central1-myproject.cloudfunctions.net port 443 (step 2/3)
* schannel: encrypted data got 4096
* schannel: encrypted data buffer: offset 4096 length 4096
* schannel: encrypted data length: 4028
* schannel: encrypted data buffer: offset 4028 length 4096
* schannel: received incomplete message, need more data
* schannel: SSL/TLS connection with us-central1-myproject.cloudfunctions.net port 443 (step 2/3)
* schannel: encrypted data got 1024
* schannel: encrypted data buffer: offset 5052 length 5052
* schannel: received incomplete message, need more data
* schannel: SSL/TLS connection with us-central1-myproject.cloudfunctions.net port 443 (step 2/3)
* schannel: encrypted data got 1024
* schannel: encrypted data buffer: offset 6076 length 6076
* schannel: received incomplete message, need more data
* schannel: SSL/TLS connection with us-central1-myproject.cloudfunctions.net port 443 (step 2/3)
* schannel: encrypted data got 1024
* schannel: encrypted data buffer: offset 7100 length 7100
* schannel: received incomplete message, need more data
* schannel: SSL/TLS connection with us-central1-myproject.cloudfunctions.net port 443 (step 2/3)
* schannel: encrypted data got 1024
* schannel: encrypted data buffer: offset 8124 length 8124
* schannel: received incomplete message, need more data
* schannel: SSL/TLS connection with us-central1-myproject.cloudfunctions.net port 443 (step 2/3)
* schannel: encrypted data got 317
* schannel: encrypted data buffer: offset 8441 length 9148
* schannel: sending next handshake data: sending 93 bytes...
* schannel: SSL/TLS connection with us-central1-myproject.cloudfunctions.net port 443 (step 2/3)
* schannel: encrypted data got 284
* schannel: encrypted data buffer: offset 284 length 9148
* schannel: SSL/TLS handshake complete
* schannel: SSL/TLS connection with us-central1-myproject.cloudfunctions.net port 443 (step 3/3)
* schannel: stored credential handle in session cache
> POST /logontest HTTP/1.1
> Host: us-central1-myproject.cloudfunctions.net
> User-Agent: curl/7.55.1
> Accept: */*
> Content-Type:application/json
> Content-Length: 59
>
* upload completely sent off: 59 out of 59 bytes
* schannel: client wants to read 102400 bytes
* schannel: encdata_buffer resized 103424
* schannel: encrypted data buffer: offset 0 length 103424
* schannel: encrypted data got 506
* schannel: encrypted data buffer: offset 506 length 103424
* schannel: decrypted data length: 477
* schannel: decrypted data added: 477
* schannel: decrypted data cached: offset 477 length 102400
* schannel: encrypted data buffer: offset 0 length 103424
* schannel: decrypted data buffer: offset 477 length 102400
* schannel: schannel_recv cleanup
* schannel: decrypted data returned 477
* schannel: decrypted data buffer: offset 0 length 102400
< HTTP/1.1 400 Bad Request
< Content-Type: text/html
< Function-Execution-Id: qyx8g4vv8hn1
< X-Cloud-Trace-Context: 6f8012ea791b4a0f900ac4b84debaf5f;o=1
< Date: Thu, 02 May 2019 13:23:14 GMT
< Server: Google Frontend
< Content-Length: 192
< Alt-Svc: quic=":443"; ma=2592000; v="46,44,43,39"
<
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
<title>400 Bad Request</title>
<h1>Bad Request</h1>
<p>The browser (or proxy) sent a request that this server could not
understand.</p>
* Connection #0 to host us-central1-myproject.cloudfunctions.net left intact
The 'bad request' may not be due to URL since I took from the cloud function UI. Please suggest how I should proceed. Thanks.

webserver based on node.js couldn't parse the right data which sent by method 'POST' via CURL

I implemented a simple webserver based on node.js, which handle the data
sent by method 'POST' via libCURL.
Client: c++ code based on libCURL
Server: Node.js
Result:
Client
I implemented a simple webserver based on node.js, which handle the data
sent by method 'POST' via libCURL.
Client: c++ code based on libCURL
Server: Node.js
###Client####
>>>
* Found bundle for host 109.123.121.146: 0x1b13f00 [can pipeline]
* Re-using existing connection! (#0) with host 109.123.121.146
* Connected to 109.123.121.146 (109.123.121.146) port 8124 (#0)
> POST / HTTP/1.1
Host: 109.123.121.146:8124
Accept: */*
Content-Type: text/xml
Content-Length: 11
* upload completely sent off: 11 out of 11 bytes
< HTTP/1.1 200 OK
HTTP/1.1 200 OK
< Content-Type: text/plain;charset=utf-8
Content-Type: text/plain;charset=utf-8
< Date: Thu, 05 Jan 2017 21:14:05 GMT
Date: Thu, 05 Jan 2017 21:14:05 GMT
< Connection: keep-alive
Connection: keep-alive
< Transfer-Encoding: chunked
Transfer-Encoding: chunked
<
* Connection #0 to host 109.123.121.146 left intact
###Server####
####### 'POST' ######
Partial body: B=~� size:11
Body: B=~� size:11 ---->> why the data is invalid char, size is right.
Source Code
Client.cpp
string strUrl = "http://109.123.121.146:8124/";
string strLog = "Hello,CURL!";
curl_easy_setopt(g_curl_handle, CURLOPT_URL, strUrl.c_str());
curl_easy_setopt(g_curl_handle, CURLOPT_POST, 1);
curl_easy_setopt(g_curl_handle, CURLOPT_POSTFIELDS, strLog.c_str());
Server.js
req.addListener('data', function (data) {
body += data;
console.log("Partial body: " + data + " size:"+data.toString().length);
});
req.addListener('end', function () {
console.log("Body: " + body + " size:"+body.toString().length);
});
I wonder why the request data is invalid char:"B=~�" , or not the right string "Hello,CURL!",
Anyone konws, help to explain to me, thanks ~~~

libcurl POST request failing

I am trying to mimic the behavior of a python program using libcurl and getting rejected by the server. As near as I can tell, this is an issue with how the file is being handled. Here is the python code:
import requests
savedTextFile = open('filepath/file.txt', 'rw')
myPostRequest = requests.post("https://mywebserver.com/ws/v1/layers/template/lines2", headers={"API-Key":"source:1111111111"}, files={'file': savedTextFile}, verify=False)
The libcurl/C++ code I have currently is:
CURL* curl; //our curl object
struct curl_httppost* formpost=NULL;
struct curl_httppost* lastptr=NULL;
struct curl_slist* headerlist=NULL;
curl_global_init(CURL_GLOBAL_ALL); //pretty obvious
curl_formadd(&formpost,
&lastptr,
CURLFORM_COPYNAME, "file", // required ?
CURLFORM_FILE, dbFile.c_str(), // makes this part a file upload part
CURLFORM_CONTENTTYPE, "application/octet-stream", // generic binary
CURLFORM_END);
curl = curl_easy_init();
const int MediumBufferSize = 256;
char sApiKeyHeaderLine[MediumBufferSize];
sprintf_s(sApiKeyHeaderLine, MediumBufferSize, "API-Key:%s", api.c_str());
headerlist = curl_slist_append((struct curl_slist*) headerlist, sApiKeyHeaderLine);
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headerlist);
curl_easy_setopt(curl, CURLOPT_URL, full_url.c_str());
curl_easy_setopt(curl, CURLOPT_HTTPPOST, formpost);
curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L); //tell curl to output its progress
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0);
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0);
curl_easy_perform(curl);
curl_easy_cleanup(curl);
curl_global_cleanup();
Not sure what im missing.Here is the DOS console output:
* About to connect() to 54.219.209.180 port 443 (#1)
* Trying 54.219.209.180...
* Adding handle: conn: 0x490140
* Adding handle: send: 0
* Adding handle: recv: 0
* Curl_addHandleToPipeline: length: 1
* - Conn 1 (0x490140) send_pipe: 1, recv_pipe: 0
* Connected to 54.219.209.180 (54.219.209.180) port 443 (#1)
* schannel: SSL/TLS connection with 54.219.209.180 port 443 (step 1/3)
* schannel: disable server certificate revocation checks
* schannel: using IP address, SNI is being disabled by disabling the servername check against the subject names in server certificates.
* schannel: verifyhost setting prevents Schannel from comparing the supplied tar get name with the subject names in server certificates. Also disables SNI.
* schannel: sending initial handshake data: sending 90 bytes...
* schannel: sent initial handshake data: sent 90 bytes
* schannel: SSL/TLS connection with 54.219.209.180 port 443 (step 2/3)
* schannel: failed to receive handshake, need more data
* schannel: SSL/TLS connection with 54.219.209.180 port 443 (step 2/3)
* schannel: encrypted data buffer: offset 797 length 4096
* schannel: sending next handshake data: sending 326 bytes...
* schannel: SSL/TLS connection with 54.219.209.180 port 443 (step 2/3)
* schannel: encrypted data buffer: offset 59 length 4096
* schannel: SSL/TLS handshake complete
* schannel: SSL/TLS connection with 54.219.209.180 port 443 (step 3/3)
* schannel: incremented credential handle refcount = 1
* schannel: stored credential handle in session cache
> POST /ws/v1/layers/template/lines1 HTTP/1.1 Host: 54.219.209.180 Accept: */* LatLongo-API-Key:source:1234567890
Content-Length: 35023 Expect: 100-continue Content-Type: multipart/form-data; boundary=------------------------3e5310b06e42 8f31
* schannel: client wants to read 16384 bytes
* schannel: encrypted data buffer: offset 0 length 16384
* schannel: encrypted data got 245
* schannel: encrypted data buffer: offset 245 length 16384
* schannel: decrypted data length: 209
* schannel: decrypted data added: 209
* schannel: decrypted data cached: offset 209 length 16384
* schannel: decrypted data buffer: offset 209 length 16384
* schannel: decrypted data returned 209
* schannel: decrypted data buffer: offset 0 length 16384
< HTTP/1.1 400 BAD REQUEST
< Date: Thu, 09 Jan 2014 04:04:59 GMT
< Content-Type: text/html; charset=utf-8
< Transfer-Encoding: chunked
< Connection: keep-alive
* Server gunicorn/18.0 is not blacklisted
< Server: gunicorn/18.0
* HTTP error before end of send, stop sending
< POST form invalid
* Closing connection 1
* schannel: shutting down SSL/TLS connection with 54.219.209.180 port 443
* schannel: clear security context handle
* schannel: decremented credential handle refcount = 0

cURL requests changed

I've start work with cURL library, before work i compile library. i Send request and have some problem. Code in c++ that i used for work with cURL:
CURL *curl=NULL;
CURLcode res;
struct curl_slist *headers=NULL; // init to NULL is important
curl_slist_append(headers, "POST /oauth/authorize HTTP/1.1");
curl_slist_append(headers, "Host: sp-money.yandex.ru");
curl_slist_append(headers, "Content-Type: application/x-www-form-urlencoded");
curl_slist_append(headers, "charset: UTF-8");
curl_slist_append(headers, "Content-Length: 12345");
curl = curl_easy_init();
if(!curl)
return 0;
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
curl_easy_setopt(curl, CURLOPT_URL, "sp-money.yandex.ru");
curl_easy_setopt(curl, CURLOPT_PROXY, "127.0.0.1:8888");
if( curl_easy_perform(curl)!=CURLE_OK)
return 1;
I've used proxy, fiddler2, for check what data sent to server. When i check sent data
i get result:
POST HTTP://sp-money.yandex.ru/ HTTP/1.1
Host: sp-money.yandex.ru
Accept: */*
Connection: Keep-Alive
Content-Length: 151
Content-Type: application/x-www-form-urlencoded
also i check this data using Wiresharck, result the same.
Do you know why in first line cURL wrote:
POST HTTP://sp-money.yandex.ru/ HTTP/1.1
I send
POST /oauth/authorize HTTP/1.1
I've used VS 2010 for work, and also i don't used framework
POST /oauth/authorize HTTP/1.1 is not a header, it the HTTP Verb (POST) with URL and version.
I suppose you need to put that elsewhere (will look at the docs for second noww)
The POST line doesn't belong to headers, it should be set with CURLOPT_URL, CURLOPT_POST, and something like that for the protocol. Actually, the same goes for the Host: header, it is inferred from URL.