Merge pull request #41 from an-tao/dev

Debug form post request
This commit is contained in:
An Tao 2019-01-23 11:41:35 +08:00 committed by GitHub
commit 2fc2c60af1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 202 additions and 8 deletions

View File

@ -355,7 +355,7 @@ void ApiTest::jsonTest(const HttpRequestPtr &req, const std::function<void(const
{
auto json = req->getJsonObject();
Json::Value ret;
if(json)
if (json)
{
ret["result"] = "ok";
}
@ -366,3 +366,19 @@ void ApiTest::jsonTest(const HttpRequestPtr &req, const std::function<void(const
auto resp = HttpResponse::newHttpJsonResponse(ret);
callback(resp);
}
void ApiTest::formTest(const HttpRequestPtr &req, const std::function<void(const HttpResponsePtr &)> &callback)
{
auto parameters = req->getParameters();
Json::Value ret;
if (parameters["k1"] == "1" && parameters["k2"] == "")
{
ret["result"] = "ok";
}
else
{
ret["result"] = "bad";
}
auto resp = HttpResponse::newHttpJsonResponse(ret);
callback(resp);
}

View File

@ -17,6 +17,7 @@ class ApiTest : public drogon::HttpController<ApiTest>
METHOD_ADD(ApiTest::staticApi, "/static", Get, Post);
METHOD_ADD(ApiTest::get2, "/get/{1}", Get);
METHOD_ADD(ApiTest::jsonTest, "/json", Post);
METHOD_ADD(ApiTest::formTest, "/form", Post);
METHOD_LIST_END
//your declaration of processing function maybe like this:
void get(const HttpRequestPtr &req, const std::function<void(const HttpResponsePtr &)> &callback, int p1, std::string &&p2);
@ -26,6 +27,7 @@ class ApiTest : public drogon::HttpController<ApiTest>
void rootGet(const HttpRequestPtr &req, const std::function<void(const HttpResponsePtr &)> &callback);
void rootPost(const HttpRequestPtr &req, const std::function<void(const HttpResponsePtr &)> &callback);
void jsonTest(const HttpRequestPtr &req, const std::function<void(const HttpResponsePtr &)> &callback);
void formTest(const HttpRequestPtr &req, const std::function<void(const HttpResponsePtr &)> &callback);
};
} // namespace v1
} // namespace api

View File

@ -489,6 +489,32 @@ void doTest(const HttpClientPtr &client)
}
});
/// Test form post
req = HttpRequest::newHttpFormPostRequest();
req->setPath("/api/v1/apitest/form");
req->setParameter("k1", "1");
req->setParameter("k2", "");
client->sendRequest(req, [=](ReqResult result, const HttpResponsePtr &resp) {
if (result == ReqResult::Ok)
{
auto ret = resp->getJsonObject();
if (ret && (*ret)["result"].asString() == "ok")
{
outputGood(req);
}
else
{
LOG_DEBUG << resp->getBody();
LOG_ERROR << "Error!";
exit(1);
}
}
else
{
LOG_ERROR << "Error!";
exit(1);
}
});
}
int main()

View File

@ -29,7 +29,6 @@ namespace drogon
class HttpRequest;
typedef std::shared_ptr<HttpRequest> HttpRequestPtr;
/// Abstract class for webapp developer to get or set the Http request;
class HttpRequest
{
@ -114,7 +113,7 @@ class HttpRequest
/// Create a request object.
static HttpRequestPtr newHttpRequest();
static HttpRequestPtr newHttpJsonRequest(const Json::Value &data);
static HttpRequestPtr newHttpFormPostRequest();
virtual ~HttpRequest() {}
};

View File

@ -15,7 +15,7 @@
namespace drogon
{
enum HttpStatusCode
{
//rfc2616-6.1.1
@ -73,6 +73,7 @@ enum ContentType
CT_APPLICATION_JSON = 0,
CT_TEXT_PLAIN,
CT_TEXT_HTML,
CT_APPLICATION_X_FORM,
CT_APPLICATION_X_JAVASCRIPT,
CT_TEXT_CSS,
CT_TEXT_XML,

View File

@ -50,9 +50,10 @@ std::string base64Encode(const unsigned char *bytes_to_encode, unsigned int in_l
/// Decode the base64 format string.
std::string base64Decode(std::string const &encoded_string);
/// Decode the URL format string send by web browser.
/// Decode from or encode to the URL format string
std::string urlDecode(const std::string &szToDecode);
std::string urlDecode(const char *begin, const char *end);
std::string urlEncode(const std::string &str);
/// Commpress or decompress data using gzip lib.
/**

View File

@ -13,6 +13,7 @@
*/
#include "HttpRequestImpl.h"
#include <drogon/utils/Utilities.h>
#include <iostream>
using namespace drogon;
@ -133,7 +134,7 @@ void HttpRequestImpl::appendToBuffer(MsgBuffer *output) const
content.append("&");
}
content.resize(content.length() - 1);
///TODO: URL code?
content = urlEncode(content);
if (_method == Get || _method == Delete)
{
output->append("?");
@ -211,7 +212,7 @@ void HttpRequestImpl::appendToBuffer(MsgBuffer *output) const
void HttpRequestImpl::addHeader(const char *start, const char *colon, const char *end)
{
std::string field(start, colon);
//field name is case-insensitive.so we transform it to lower;(rfc2616-4.2)
//Field name is case-insensitive.so we transform it to lower;(rfc2616-4.2)
std::transform(field.begin(), field.end(), field.begin(), ::tolower);
++colon;
while (colon < end && isspace(*colon))
@ -274,6 +275,15 @@ HttpRequestPtr HttpRequest::newHttpRequest()
return req;
}
HttpRequestPtr HttpRequest::newHttpFormPostRequest()
{
auto req = std::make_shared<HttpRequestImpl>();
req->setMethod(drogon::Post);
req->setVersion(drogon::HttpRequest::kHttp11);
req->_contentType = CT_APPLICATION_X_FORM;
return req;
}
HttpRequestPtr HttpRequest::newHttpJsonRequest(const Json::Value &data)
{
auto req = std::make_shared<HttpRequestImpl>();

View File

@ -24,6 +24,9 @@ std::string webContentTypeAndCharsetToString(ContentType contenttype, const std:
case CT_TEXT_HTML:
return "text/html; charset=" + charSet;
case CT_APPLICATION_X_FORM:
return "application/x-www-form-urlencoded";
case CT_APPLICATION_XML:
return "application/xml; charset=" + charSet;
@ -94,6 +97,9 @@ std::string webContentTypeToString(ContentType contenttype)
case CT_TEXT_HTML:
return "text/html; charset=utf-8";
case CT_APPLICATION_X_FORM:
return "application/x-www-form-urlencoded";
case CT_APPLICATION_XML:
return "application/xml; charset=utf-8";

View File

@ -27,6 +27,10 @@
#include <mutex>
#include <cstdlib>
#include <stack>
#include <cctype>
#include <iomanip>
#include <sstream>
#include <string>
namespace drogon
{
@ -272,6 +276,121 @@ std::string base64Decode(std::string const &encoded_string)
return ret;
}
static std::string charToHex(char c)
{
std::string result;
char first, second;
first = (c & 0xF0) / 16;
first += first > 9 ? 'A' - 10 : '0';
second = c & 0x0F;
second += second > 9 ? 'A' - 10 : '0';
result.append(1, first);
result.append(1, second);
return result;
}
std::string urlEncode(const std::string &src)
{
std::string result;
std::string::const_iterator iter;
for (iter = src.begin(); iter != src.end(); ++iter)
{
switch (*iter)
{
case ' ':
result.append(1, '+');
break;
// alnum
case 'A':
case 'B':
case 'C':
case 'D':
case 'E':
case 'F':
case 'G':
case 'H':
case 'I':
case 'J':
case 'K':
case 'L':
case 'M':
case 'N':
case 'O':
case 'P':
case 'Q':
case 'R':
case 'S':
case 'T':
case 'U':
case 'V':
case 'W':
case 'X':
case 'Y':
case 'Z':
case 'a':
case 'b':
case 'c':
case 'd':
case 'e':
case 'f':
case 'g':
case 'h':
case 'i':
case 'j':
case 'k':
case 'l':
case 'm':
case 'n':
case 'o':
case 'p':
case 'q':
case 'r':
case 's':
case 't':
case 'u':
case 'v':
case 'w':
case 'x':
case 'y':
case 'z':
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
// mark
case '-':
case '_':
case '.':
case '!':
case '~':
case '*':
case '\'':
case '(':
case ')':
case '&':
case '=':
result.append(1, *iter);
break;
// escape
default:
result.append(1, '%');
result.append(charToHex(*iter));
break;
}
}
return result;
}
std::string urlDecode(const std::string &szToDecode)
{

View File

@ -8,4 +8,5 @@ add_executable(sha1_test Sha1Test.cc)
add_executable(view_data_test HttpViewDataTest.cc)
add_executable(md5_test Md5Test.cc ../src/ssl_funcs/Md5.cc)
add_executable(http_full_date_test HttpFullDateTest.cc)
add_executable(gzip_test GzipTest.cc)
add_executable(gzip_test GzipTest.cc)
add_executable(url_codec_test UrlCodecTest.cc)

13
lib/tests/UrlCodecTest.cc Normal file
View File

@ -0,0 +1,13 @@
#include <drogon/utils/Utilities.h>
#include <iostream>
int main()
{
std::string input = "k1=1&k2=安";
auto output = drogon::urlEncode(input);
std::cout << output << std::endl;
auto output2 = drogon::urlDecode(output);
std::cout << output2 << std::endl;
std::cout << drogon::urlDecode("k2%3D%E5%AE%89&k1%3D1");
return 0;
}