Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added a method to perform POST Form Upload #163

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 36 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,25 @@ RestClient::Response r = RestClient::patch("http://url.com/patch", "application/
RestClient::Response r = RestClient::del("http://url.com/delete")
RestClient::Response r = RestClient::head("http://url.com")
RestClient::Response r = RestClient::options("http://url.com")

// Post Form Upload
/* Filling information about the form in a RestClient::FormData object */
RestClient::FormData uploadInfo;
/* "submitted" is the name of the "file" input and "TestPostForm.txt"
is the location of the file to submit.
<input type="file" name="submitted">
*/
uploadInfo.addFormFile("submitted", "TestPostForm.txt");
/* In some rare cases, some fields related to the form can be filled with
addFormContent(), the 1st argument is the name of the input element and
the 2nd argument is the value assigned to it.
<input type="text" name="filename" value=""/>
<input type="submit" name="submit" value="send">
*/
uploadInfo.addFormContent("filename", "myfile.cpp");
uploadInfo.addFormContent("submit", "send");
/* Performing a post form upload with the information provided above */
RestClient::Response res = RestClient::post("http://posttestserver.com/post.php?dir=restclientcpptests", uploadInfo);
```

The response is of type [RestClient::Response][restclient_response] and has
Expand Down Expand Up @@ -295,6 +314,23 @@ conn->SetHeaders(headers);
auto resp = conn->get("/images/json");
```

## HTTP Proxy Tunneling Support

An HTTP Proxy can be set to use for the upcoming request.
To specify a port number, append :[port] to the end of the host name. If not specified, `libcurl` will default to using port 1080 for proxies. The proxy string may be prefixed with `http://` or `https://`. If no HTTP(S) scheme is specified, the address provided to `libcurl` will be prefixed with `http://` to specify an HTTP proxy. A proxy host string can embedded user + password.
The operation will be tunneled through the proxy as curl option `CURLOPT_HTTPPROXYTUNNEL` is enabled by default.
A numerical IPv6 address must be written within [brackets].

```cpp
// set CURLOPT_PROXY
conn->SetProxy("https://37.187.100.23:3128");
/* or you can set it without the protocol scheme and
http:// will be prefixed by default */
conn->SetProxy("37.187.100.23:3128");
/* the following request will be tunneled through the proxy */
RestClient::Response res = conn->get("/get");
```

## Dependencies
- [libcurl][]

Expand Down
2 changes: 2 additions & 0 deletions include/restclient-cpp/connection.h
Original file line number Diff line number Diff line change
Expand Up @@ -224,6 +224,8 @@ class Connection {
RestClient::Response get(const std::string& uri);
RestClient::Response post(const std::string& uri,
const std::string& data);
RestClient::Response post(const std::string& uri,
const FormData& data);
RestClient::Response put(const std::string& uri,
const std::string& data);
RestClient::Response patch(const std::string& uri,
Expand Down
2 changes: 2 additions & 0 deletions include/restclient-cpp/helpers.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
#ifndef INCLUDE_RESTCLIENT_CPP_HELPERS_H_
#define INCLUDE_RESTCLIENT_CPP_HELPERS_H_

#include <curl/curl.h>

#include <string>
#include <cctype>
#include <algorithm>
Expand Down
23 changes: 23 additions & 0 deletions include/restclient-cpp/restclient.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#include <map>
#include <cstdlib>

#include "restclient-cpp/helpers.h"
#include "restclient-cpp/version.h"

/**
Expand Down Expand Up @@ -40,6 +41,26 @@ typedef struct {
HeaderFields headers;
} Response;

/** @class FormData
* @brief This class represents the form information to send on
* POST Form requests
*/
class FormData {
struct curl_httppost* formPtr;
struct curl_httppost* lastFormPtr;
public:
FormData();
~FormData();
/* Fill in the file upload field */
void addFormFile(const std::string& fieldName,
const std::string& fieldValue);
/* Fill in the filename or the submit field */
void addFormContent(const std::string& fieldName,
const std::string& fieldValue);
/* Get Form pointer */
struct curl_httppost* getFormPtr() const { return formPtr; }
};

// init and disable functions
int init();
void disable();
Expand All @@ -53,6 +74,8 @@ Response get(const std::string& url);
Response post(const std::string& url,
const std::string& content_type,
const std::string& data);
Response post(const std::string& url,
const FormData& data);
Response put(const std::string& url,
const std::string& content_type,
const std::string& data);
Expand Down
56 changes: 54 additions & 2 deletions source/connection.cc
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,8 @@ RestClient::Connection::GetInfo() {
ret.uriProxy = this->uriProxy;
ret.unixSocketPath = this->unixSocketPath;

ret.uriProxy = this->uriProxy;

return ret;
}

Expand Down Expand Up @@ -298,12 +300,16 @@ RestClient::Connection::SetKeyPassword(const std::string& keyPassword) {
*/
void
RestClient::Connection::SetProxy(const std::string& uriProxy) {
if (uriProxy.empty()) {
return;
}

std::string uriProxyUpper = uriProxy;
// check if the provided address is prefixed with "http"
std::transform(uriProxyUpper.begin(), uriProxyUpper.end(),
uriProxyUpper.begin(), ::toupper);

if ((uriProxy.length() > 0) && (uriProxyUpper.compare(0, 4, "HTTP") != 0)) {
if (uriProxyUpper.compare(0, 4, "HTTP") != 0) {
this->uriProxy = "http://" + uriProxy;
} else {
this->uriProxy = uriProxy;
Expand Down Expand Up @@ -483,6 +489,32 @@ RestClient::Connection::performCurlRequest(const std::string& uri,
this->keyPassword.c_str());
}

// set web proxy address
if (!this->uriProxy.empty()) {
curl_easy_setopt(getCurlHandle(), CURLOPT_PROXY,
uriProxy.c_str());
curl_easy_setopt(getCurlHandle(), CURLOPT_HTTPPROXYTUNNEL,
1L);
}
// set key password
if (!this->keyPassword.empty()) {
curl_easy_setopt(getCurlHandle(), CURLOPT_KEYPASSWD,
this->keyPassword.c_str());
}

// set web proxy address
if (!this->uriProxy.empty()) {
curl_easy_setopt(getCurlHandle(), CURLOPT_PROXY,
uriProxy.c_str());
curl_easy_setopt(getCurlHandle(), CURLOPT_HTTPPROXYTUNNEL,
1L);
}
// set key password
if (!this->keyPassword.empty()) {
curl_easy_setopt(getCurlHandle(), CURLOPT_KEYPASSWD,
this->keyPassword.c_str());
}

// set web proxy address
if (!this->uriProxy.empty()) {
curl_easy_setopt(getCurlHandle(), CURLOPT_PROXY,
Expand Down Expand Up @@ -580,6 +612,26 @@ RestClient::Connection::post(const std::string& url,

return this->performCurlRequest(url);
}
/**
* @brief HTTP POST Form method
*
* @param url to query
* @param data form info
*
* @return response struct
*/
RestClient::Response
RestClient::Connection::post(const std::string& url,
const FormData& data) {
/** Now specify we want to POST data */
curl_easy_setopt(getCurlHandle(), CURLOPT_POST, 1L);
/* stating that Expect: 100-continue is not wanted */
AppendHeader("Expect", "");
/** set post form */
curl_easy_setopt(getCurlHandle(), CURLOPT_HTTPPOST, data.getFormPtr());

return this->performCurlRequest(url);
}
/**
* @brief HTTP PUT method
*
Expand Down Expand Up @@ -620,7 +672,7 @@ RestClient::Connection::put(const std::string& url,
*/
RestClient::Response
RestClient::Connection::patch(const std::string& url,
const std::string& data) {
const std::string& data) {
/** initialize upload object */
RestClient::Helpers::UploadObject up_obj;
up_obj.data = data.c_str();
Expand Down
1 change: 1 addition & 0 deletions source/helpers.cc
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ size_t RestClient::Helpers::write_callback(void *data, size_t size,
* @param size of data
* @param nmemb memblock
* @param userdata pointer to user data object to save headr data
*
* @return size * nmemb;
*/
size_t RestClient::Helpers::header_callback(void *data, size_t size,
Expand Down
Loading