forked from envoyproxy/nighthawk
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathrequest_options_list_plugin_impl.cc
117 lines (99 loc) · 5.43 KB
/
request_options_list_plugin_impl.cc
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
#include "source/request_source/request_options_list_plugin_impl.h"
#include "external/envoy/source/common/protobuf/message_validator_impl.h"
#include "external/envoy/source/common/protobuf/utility.h"
#include "external/envoy/source/exe/platform_impl.h"
#include "api/client/options.pb.h"
#include "source/common/request_impl.h"
#include "source/common/request_source_impl.h"
namespace Nighthawk {
std::string FileBasedOptionsListRequestSourceFactory::name() const {
return "nighthawk.file-based-request-source-plugin";
}
Envoy::ProtobufTypes::MessagePtr
FileBasedOptionsListRequestSourceFactory::createEmptyConfigProto() {
return std::make_unique<nighthawk::request_source::FileBasedOptionsListRequestSourceConfig>();
}
RequestSourcePtr FileBasedOptionsListRequestSourceFactory::createRequestSourcePlugin(
const Envoy::Protobuf::Message& message, Envoy::Api::Api& api,
Envoy::Http::RequestHeaderMapPtr header) {
const auto& any = dynamic_cast<const Envoy::ProtobufWkt::Any&>(message);
nighthawk::request_source::FileBasedOptionsListRequestSourceConfig config;
Envoy::MessageUtil util;
util.unpackTo(any, config);
uint32_t max_file_size = config.has_max_file_size() ? config.max_file_size().value() : 1000000;
if (api.fileSystem().fileSize(config.file_path()) > max_file_size) {
throw NighthawkException("file size must be less than max_file_size");
}
nighthawk::client::RequestOptionsList loaded_list;
// Locking to avoid issues with multiple threads reading the same file.
{
Envoy::Thread::LockGuard lock_guard(file_lock_);
util.loadFromFile(config.file_path(), loaded_list,
Envoy::ProtobufMessage::getStrictValidationVisitor(), api);
}
auto loaded_list_ptr = std::make_unique<const nighthawk::client::RequestOptionsList>(loaded_list);
return std::make_unique<OptionsListRequestSource>(config.num_requests(), std::move(header),
std::move(loaded_list_ptr));
}
REGISTER_FACTORY(FileBasedOptionsListRequestSourceFactory, RequestSourcePluginConfigFactory);
std::string InLineOptionsListRequestSourceFactory::name() const {
return "nighthawk.in-line-options-list-request-source-plugin";
}
Envoy::ProtobufTypes::MessagePtr InLineOptionsListRequestSourceFactory::createEmptyConfigProto() {
return std::make_unique<nighthawk::request_source::InLineOptionsListRequestSourceConfig>();
}
RequestSourcePtr InLineOptionsListRequestSourceFactory::createRequestSourcePlugin(
const Envoy::Protobuf::Message& message, Envoy::Api::Api&,
Envoy::Http::RequestHeaderMapPtr header) {
const auto& any = dynamic_cast<const Envoy::ProtobufWkt::Any&>(message);
nighthawk::request_source::InLineOptionsListRequestSourceConfig config;
Envoy::MessageUtil::unpackTo(any, config);
auto loaded_list_ptr =
std::make_unique<const nighthawk::client::RequestOptionsList>(config.options_list());
return std::make_unique<OptionsListRequestSource>(config.num_requests(), std::move(header),
std::move(loaded_list_ptr));
}
REGISTER_FACTORY(InLineOptionsListRequestSourceFactory, RequestSourcePluginConfigFactory);
OptionsListRequestSource::OptionsListRequestSource(
const uint32_t total_requests, Envoy::Http::RequestHeaderMapPtr header,
std::unique_ptr<const nighthawk::client::RequestOptionsList> options_list)
: header_(std::move(header)), options_list_(std::move(options_list)),
total_requests_(total_requests) {}
RequestGenerator OptionsListRequestSource::get() {
request_count_.push_back(0);
uint32_t& lambda_counter = request_count_.back();
RequestGenerator request_generator = [this, lambda_counter]() mutable -> RequestPtr {
// Initialize the header with the values from the default header.
Envoy::Http::RequestHeaderMapPtr header = Envoy::Http::RequestHeaderMapImpl::create();
Envoy::Http::HeaderMapImpl::copyFrom(*header, *header_);
// if request_max is 0, then we never stop generating requests.
if (lambda_counter >= total_requests_ && total_requests_ != 0) {
return nullptr;
}
// if the options_list_ is empty, we just return the default header.
if (options_list_->options_size() == 0) {
return std::make_unique<RequestImpl>(std::move(header));
}
// Increment the counter and get the request_option from the list for the current iteration.
const uint32_t index = lambda_counter % options_list_->options_size();
nighthawk::client::RequestOptions request_option = options_list_->options().at(index);
++lambda_counter;
// Override the default values with the values from the request_option
header->setMethod(envoy::config::core::v3::RequestMethod_Name(request_option.request_method()));
const uint32_t content_length = request_option.request_body_size().value();
if (content_length > 0) {
header->setContentLength(
content_length); // Content length is used later in stream_decoder to populate the body
}
for (const envoy::config::core::v3::HeaderValueOption& option_header :
request_option.request_headers()) {
auto lower_case_key = Envoy::Http::LowerCaseString(std::string(option_header.header().key()));
header->setCopy(lower_case_key, std::string(option_header.header().value()));
}
return std::make_unique<RequestImpl>(std::move(header));
};
return request_generator;
}
void OptionsListRequestSource::initOnThread() {}
void OptionsListRequestSource::destroyOnThread() {}
} // namespace Nighthawk