-
Notifications
You must be signed in to change notification settings - Fork 377
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 #69
Changes from all commits
cfb825d
8b117a5
553c238
66f59c5
75d61ce
9c2913b
5a6b127
85b2e74
62e25d2
934aff7
5b96edd
52a6275
037efba
47171ad
de18575
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -13,6 +13,7 @@ | |
#include <map> | ||
#include <cstdlib> | ||
|
||
#include "restclient-cpp/helpers.h" | ||
#include "restclient-cpp/version.h" | ||
|
||
/** | ||
|
@@ -40,6 +41,26 @@ typedef struct { | |
HeaderFields headers; | ||
} Response; | ||
|
||
/** @class PostFormInfo | ||
* @brief This class represents the form information to send on | ||
* POST Form requests | ||
*/ | ||
class PostFormInfo { | ||
struct curl_httppost* formPtr; | ||
struct curl_httppost* lastFormPtr; | ||
public: | ||
PostFormInfo(); | ||
~PostFormInfo(); | ||
/* 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(); | ||
|
@@ -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 postForm(const std::string& url, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why not just use an overload of There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. good point |
||
const PostFormInfo& data); | ||
Response put(const std::string& url, | ||
edwinpjacques marked this conversation as resolved.
Show resolved
Hide resolved
|
||
const std::string& content_type, | ||
const std::string& data); | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -87,6 +87,23 @@ RestClient::Response RestClient::post(const std::string& url, | |
#endif | ||
} | ||
|
||
/** | ||
* @brief HTTP POST Form method | ||
* | ||
* @param url to query | ||
* @param data post form information | ||
* | ||
* @return response struct | ||
*/ | ||
RestClient::Response RestClient::postForm(const std::string& url, | ||
const PostFormInfo& data) { | ||
RestClient::Response ret; | ||
RestClient::Connection *conn = new RestClient::Connection(""); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There shouldn't be any need to use There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, that's true. That will allow the remove of a lot of extraneous code and improve performance of RestClient interface. It should be done for all RestClient methods. |
||
ret = conn->postForm(url, data); | ||
delete conn; | ||
return ret; | ||
} | ||
|
||
/** | ||
* @brief HTTP PUT method | ||
* | ||
|
@@ -187,3 +204,51 @@ RestClient::Response RestClient::options(const std::string& url) { | |
delete conn; | ||
return ret; | ||
} | ||
|
||
/** | ||
* @brief PostFormInfo constructor | ||
*/ | ||
RestClient::PostFormInfo::PostFormInfo() | ||
: formPtr(NULL), lastFormPtr(NULL) { | ||
} | ||
|
||
/** | ||
* @brief PostFormInfo destructor | ||
*/ | ||
RestClient::PostFormInfo::~PostFormInfo() { | ||
// cleanup the formpost chain | ||
if (this->formPtr) { | ||
curl_formfree(this->formPtr); | ||
this->formPtr = NULL; | ||
this->lastFormPtr = NULL; | ||
} | ||
} | ||
|
||
/** | ||
* @brief set the name and the value of the HTML "file" form's input | ||
* | ||
* @param fieldName name of the "file" input | ||
* @param fieldValue path to the file to upload | ||
*/ | ||
void RestClient::PostFormInfo::addFormFile( | ||
const std::string& fieldName, const std::string& fieldValue) { | ||
curl_formadd(&this->formPtr, &this->lastFormPtr, | ||
CURLFORM_COPYNAME, fieldName.c_str(), | ||
CURLFORM_FILE, fieldValue.c_str(), | ||
CURLFORM_END); | ||
} | ||
|
||
/** | ||
* @brief set the name and the value of an HTML form's input | ||
* (other than "file" like "text", "hidden" or "submit") | ||
* | ||
* @param fieldName name of the input element | ||
* @param fieldValue value to be assigned to the input element | ||
*/ | ||
void RestClient::PostFormInfo::addFormContent( | ||
const std::string& fieldName, const std::string& fieldValue) { | ||
curl_formadd(&this->formPtr, &this->lastFormPtr, | ||
CURLFORM_COPYNAME, fieldName.c_str(), | ||
CURLFORM_COPYCONTENTS, fieldValue.c_str(), | ||
CURLFORM_END); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,10 @@ | ||
#include "restclient-cpp/restclient.h" | ||
#include <gtest/gtest.h> | ||
#include <json/json.h> | ||
#include <cstdio> | ||
#include <fstream> | ||
#include <string> | ||
#include <sstream> | ||
|
||
class RestClientTest : public ::testing::Test | ||
{ | ||
|
@@ -118,6 +121,37 @@ TEST_F(RestClientTest, TestRestClientPOSTBody) | |
EXPECT_EQ("restclient-cpp/" RESTCLIENT_VERSION, root["headers"].get("User-Agent", "no url set").asString()); | ||
} | ||
|
||
TEST_F(RestClientTest, TestRestClientPostForm) | ||
{ | ||
// generating a file name with a timestamp | ||
std::ostringstream fileName; | ||
time_t rawtime; | ||
tm * timeinfo; | ||
time(&rawtime); | ||
timeinfo = localtime( &rawtime ); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The system time is not a reliable way to ensure you have a unique file name. You should just use There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Agreed, but it's reliable enough. If it really bugs you, it can be changed. Mostly this needs to run on dev systems on and a clean container that's spun up in CI so no worries there. |
||
|
||
fileName << "TestPostForm_" << (timeinfo->tm_year)+1900 << "_" << timeinfo->tm_mon+1 | ||
<< "_" << timeinfo->tm_mday << "-" << timeinfo->tm_hour | ||
<< "_"<< timeinfo->tm_min << "_" << timeinfo->tm_sec << ".txt"; | ||
|
||
// creating a dummy file to upload via a post form request | ||
std::ofstream ofDummyFile(fileName.str().c_str()); | ||
ASSERT_TRUE(static_cast<bool>(ofDummyFile)); | ||
ofDummyFile << "Dummy file for the unit test 'TestRestClientPostForm' of the restclient-cpp Project."; | ||
ASSERT_TRUE(static_cast<bool>(ofDummyFile)); | ||
ofDummyFile.close(); | ||
|
||
// uploading the dummy file | ||
RestClient::PostFormInfo UploadInfo; | ||
UploadInfo.addFormFile("submitted", fileName.str()); | ||
UploadInfo.addFormContent("filename", fileName.str()); | ||
RestClient::Response res = RestClient::postForm("http://posttestserver.com/post.php?dir=restclientcpptests", UploadInfo); | ||
EXPECT_EQ(200, res.code); | ||
|
||
// remove dummy file | ||
remove(fileName.str().c_str()); | ||
} | ||
|
||
// check for failure | ||
TEST_F(RestClientTest, TestRestClientPOSTFailureCode) | ||
{ | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This name doesn't accurately reflect the notion that a form can be submitted with any HTTP method. Why not just name this
FormData
instead?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sounds good.