Skip to content

Commit ca22103

Browse files
authored
Add sending customized http requests to drogon_ctl (#2186)
1 parent 3fce70b commit ca22103

File tree

2 files changed

+152
-4
lines changed

2 files changed

+152
-4
lines changed

drogon_ctl/press.cc

Lines changed: 149 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,10 @@
1919
#include <memory>
2020
#include <iomanip>
2121
#include <cstdlib>
22+
#include <json/json.h>
23+
#include <fstream>
24+
#include <string>
25+
#include <unordered_map>
2226
#ifndef _WIN32
2327
#include <unistd.h>
2428
#endif
@@ -33,9 +37,10 @@ std::string press::detail()
3337
" -t num number of threads(default : 1)\n"
3438
" -c num concurrent connections(default : 1)\n"
3539
" -k disable SSL certificate validation(default: enable)\n"
40+
" -f customize http request json file(default: disenable)\n"
3641
" -q no progress indication(default: show)\n\n"
3742
"example: drogon_ctl press -n 10000 -c 100 -t 4 -q "
38-
"http://localhost:8080/index.html\n";
43+
"http://localhost:8080/index.html -f ./http_request.json\n";
3944
}
4045

4146
void outputErrorAndExit(const std::string_view &err)
@@ -151,6 +156,24 @@ void press::handleCommand(std::vector<std::string> &parameters)
151156
continue;
152157
}
153158
}
159+
else if (param.find("-f") == 0)
160+
{
161+
if (param == "-f")
162+
{
163+
++iter;
164+
if (iter == parameters.end())
165+
{
166+
outputErrorAndExit("No http request json file!");
167+
}
168+
httpRequestJsonFile_ = *iter;
169+
continue;
170+
}
171+
else
172+
{
173+
httpRequestJsonFile_ = param.substr(2);
174+
continue;
175+
}
176+
}
154177
else if (param == "-k")
155178
{
156179
certValidation_ = false;
@@ -190,6 +213,118 @@ void press::handleCommand(std::vector<std::string> &parameters)
190213
path_ = url_.substr(posOfPath);
191214
}
192215
}
216+
217+
/*
218+
http_request.json
219+
{
220+
"method": "POST",
221+
"header": {
222+
"token": "e2e9d0fe-dd14-4eaf-8ac1-0997730a805d"
223+
},
224+
"body": {
225+
"passwd": "123456",
226+
"account": "10001"
227+
}
228+
}
229+
*/
230+
if (!httpRequestJsonFile_.empty())
231+
{
232+
Json::Value httpRequestJson;
233+
std::ifstream httpRequestFile(httpRequestJsonFile_,
234+
std::ifstream::binary);
235+
if (!httpRequestFile.is_open())
236+
{
237+
outputErrorAndExit(std::string{"No "} + httpRequestJsonFile_);
238+
}
239+
httpRequestFile >> httpRequestJson;
240+
241+
if (!httpRequestJson.isMember("method"))
242+
{
243+
outputErrorAndExit("No contain method");
244+
}
245+
246+
auto methodStr = httpRequestJson["method"].asString();
247+
std::transform(methodStr.begin(),
248+
methodStr.end(),
249+
methodStr.begin(),
250+
::toupper);
251+
252+
auto toHttpMethod = [&]() -> drogon::HttpMethod {
253+
if (methodStr == "GET")
254+
{
255+
return drogon::HttpMethod::Get;
256+
}
257+
else if (methodStr == "POST")
258+
{
259+
return drogon::HttpMethod::Post;
260+
}
261+
else if (methodStr == "HEAD")
262+
{
263+
return drogon::HttpMethod::Head;
264+
}
265+
else if (methodStr == "PUT")
266+
{
267+
return drogon::HttpMethod::Put;
268+
}
269+
else if (methodStr == "DELETE")
270+
{
271+
return drogon::HttpMethod::Delete;
272+
}
273+
else if (methodStr == "OPTIONS")
274+
{
275+
return drogon::HttpMethod::Options;
276+
}
277+
else if (methodStr == "PATCH")
278+
{
279+
return drogon::HttpMethod::Patch;
280+
}
281+
else
282+
{
283+
outputErrorAndExit("invalid method");
284+
}
285+
return drogon::HttpMethod::Get;
286+
};
287+
288+
std::unordered_map<std::string, std::string> header;
289+
if (httpRequestJson.isMember("header"))
290+
{
291+
auto &jsonValue = httpRequestJson["header"];
292+
for (const auto &key : jsonValue.getMemberNames())
293+
{
294+
if (jsonValue[key].isString())
295+
{
296+
header[key] = jsonValue[key].asString();
297+
}
298+
else
299+
{
300+
header[key] = jsonValue[key].toStyledString();
301+
}
302+
}
303+
}
304+
305+
std::string body;
306+
if (httpRequestJson.isMember("body"))
307+
{
308+
Json::FastWriter fastWriter;
309+
body = fastWriter.write(httpRequestJson["body"]);
310+
}
311+
312+
createHttpRequestFunc_ = [this,
313+
method = toHttpMethod(),
314+
body = std::move(body),
315+
header =
316+
std::move(header)]() -> HttpRequestPtr {
317+
auto request = HttpRequest::newHttpRequest();
318+
request->setPath(path_);
319+
request->setMethod(method);
320+
for (const auto &[field, val] : header)
321+
request->addHeader(field, val);
322+
if (!body.empty())
323+
request->setBody(body);
324+
return request;
325+
};
326+
}
327+
193328
// std::cout << "host=" << host_ << std::endl;
194329
// std::cout << "path=" << path_ << std::endl;
195330
doTesting();
@@ -232,9 +367,19 @@ void press::sendRequest(const HttpClientPtr &client)
232367
{
233368
return;
234369
}
235-
auto request = HttpRequest::newHttpRequest();
236-
request->setPath(path_);
237-
request->setMethod(Get);
370+
371+
HttpRequestPtr request;
372+
if (createHttpRequestFunc_)
373+
{
374+
request = createHttpRequestFunc_();
375+
}
376+
else
377+
{
378+
request = HttpRequest::newHttpRequest();
379+
request->setPath(path_);
380+
request->setMethod(Get);
381+
}
382+
238383
// std::cout << "send!" << std::endl;
239384
client->sendRequest(
240385
request,

drogon_ctl/press.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#include <drogon/HttpClient.h>
2121
#include <trantor/utils/Date.h>
2222
#include <trantor/net/EventLoopThreadPool.h>
23+
#include <functional>
2324
#include <string>
2425
#include <atomic>
2526
#include <memory>
@@ -62,6 +63,8 @@ class press : public DrObject<press>, public CommandHandler
6263
size_t numOfThreads_{1};
6364
size_t numOfRequests_{1};
6465
size_t numOfConnections_{1};
66+
std::string httpRequestJsonFile_;
67+
std::function<HttpRequestPtr()> createHttpRequestFunc_;
6568
bool certValidation_{true};
6669
bool processIndication_{true};
6770
std::string url_;

0 commit comments

Comments
 (0)