-
Notifications
You must be signed in to change notification settings - Fork 440
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
Sending sync request through http_client #448
Changes from 6 commits
8195e58
2e3031f
9a5ac8a
088bae8
86b0922
f27b07b
08a07f3
7f6d292
0c8b6d5
3d8c763
a0bdc20
2d93638
0344793
da399cd
c7f4bca
daf3046
a4c7fc5
8800e9d
5509530
85c1efd
6652aa3
0292a14
a288fe8
3d860ae
47a14ce
d43d5ae
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 |
---|---|---|
|
@@ -131,9 +131,9 @@ class Session : public http_client::Session | |
is_session_active_ = true; | ||
std::string url = host_ + std::string(http_request_->uri_); | ||
auto callback_ptr = &callback; | ||
curl_operation_.reset(new HttpOperation(http_request_->method_, url, callback_ptr, | ||
http_request_->headers_, http_request_->body_, false, | ||
http_request_->timeout_ms_)); | ||
curl_operation_.reset(new HttpOperation( | ||
http_request_->method_, url, callback_ptr, RequestMode::Sync, http_request_->headers_, | ||
http_request_->body_, false, http_request_->timeout_ms_)); | ||
curl_operation_->SendAsync([this, callback_ptr](HttpOperation &operation) { | ||
if (operation.WasAborted()) | ||
{ | ||
|
@@ -153,6 +153,33 @@ class Session : public http_client::Session | |
}); | ||
} | ||
|
||
virtual std::unique_ptr<http_client::Response> SendRequestSync( | ||
http_client::SessionState &session_state) noexcept override | ||
{ | ||
is_session_active_ = true; | ||
std::string url = host_ + std::string(http_request_->uri_); | ||
curl_operation_.reset(new HttpOperation(http_request_->method_, url, nullptr, RequestMode::Sync, | ||
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. Could we set 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. We do need to know the actual sync mode in ctor. There are some initializations done in ctor, and the
What kind of inconsistency we are talking about. |
||
http_request_->headers_, http_request_->body_, false, | ||
http_request_->timeout_ms_)); | ||
curl_operation_->SendSync(); | ||
session_state = curl_operation_->GetSessionState(); | ||
if (curl_operation_->WasAborted()) | ||
{ | ||
session_state = http_client::SessionState::Cancelled; | ||
} | ||
if (curl_operation_->GetResponseCode() >= CURL_LAST) | ||
{ | ||
// we have a http response | ||
auto response = std::unique_ptr<Response>(new Response()); | ||
response->headers_ = curl_operation_->GetResponseHeaders(); | ||
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. How do you propagate Response code? If you are using int for that, then in Java it'd typically allocate 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. Currently we use |
||
response->body_ = curl_operation_->GetResponseBody(); | ||
is_session_active_ = false; | ||
return std::move(response); | ||
} | ||
is_session_active_ = false; | ||
return nullptr; | ||
} | ||
|
||
virtual bool CancelSession() noexcept override | ||
{ | ||
curl_operation_->Abort(); | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -10,6 +10,8 @@ | |
/* | ||
Usage Example | ||
|
||
Async Request: | ||
|
||
struct SimpleReponseHandler: public ResponseHandler { | ||
void OnResponse(Response& res) noexcept override | ||
{ | ||
|
@@ -37,6 +39,17 @@ | |
session->FinishSession() // optionally in the end | ||
...shutdown | ||
sessionManager.FinishAllSessions() | ||
|
||
Sync Request: | ||
|
||
SessionMamager sessionManager; | ||
auto session = sessionManager.createSession("localhost", 8000); | ||
auto request = session->CreateRequest(); | ||
request->AddHeader(..); | ||
SessionState session_state; | ||
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. So this is not a 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. Correct. |
||
auto response = session->SendRequestSync(session_state); | ||
// session_state will contain SessionState::Response if successful. | ||
|
||
*/ | ||
|
||
OPENTELEMETRY_BEGIN_NAMESPACE | ||
|
@@ -138,6 +151,8 @@ class Session | |
|
||
virtual void SendRequest(EventHandler &) noexcept = 0; | ||
|
||
virtual std::unique_ptr<Response> SendRequestSync(SessionState &) noexcept = 0; | ||
|
||
virtual bool IsSessionActive() noexcept = 0; | ||
|
||
virtual bool CancelSession() noexcept = 0; | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -248,16 +248,46 @@ TEST_F(BasicCurlHttpTests, CurlHttpOperations) | |
std::multimap<std::string, std::string, curl::curl_ci> m1 = { | ||
{"name1", "value1_1"}, {"name1", "value1_2"}, {"name2", "value3"}, {"name3", "value3"}}; | ||
curl::Headers headers = m1; | ||
curl::HttpOperation http_operations1(http_client::Method::Head, "/get", handler, headers, body, | ||
true); | ||
curl::HttpOperation http_operations1(http_client::Method::Head, "/get", handler, | ||
lalitb marked this conversation as resolved.
Show resolved
Hide resolved
|
||
curl::RequestMode::Async, headers, body, true); | ||
http_operations1.Send(); | ||
|
||
curl::HttpOperation http_operations2(http_client::Method::Get, "/get", handler, headers, body, | ||
true); | ||
curl::HttpOperation http_operations2(http_client::Method::Get, "/get", handler, | ||
curl::RequestMode::Async, headers, body, true); | ||
http_operations2.Send(); | ||
|
||
curl::HttpOperation http_operations3(http_client::Method::Get, "/get", handler, headers, body, | ||
false); | ||
curl::HttpOperation http_operations3(http_client::Method::Get, "/get", handler, | ||
curl::RequestMode::Async, headers, body, false); | ||
http_operations3.Send(); | ||
delete handler; | ||
} | ||
|
||
TEST_F(BasicCurlHttpTests, SendGetRequestSync) | ||
{ | ||
received_requests_.clear(); | ||
curl::SessionManager session_manager; | ||
|
||
auto session = session_manager.CreateSession("127.0.0.1", HTTP_PORT); | ||
auto request = session->CreateRequest(); | ||
request->SetUri("get/"); | ||
http_client::SessionState session_state; | ||
auto response = session->SendRequestSync(session_state); | ||
EXPECT_EQ(response->GetStatusCode(), 200); | ||
EXPECT_EQ(session_state, http_client::SessionState::Response); | ||
} | ||
|
||
TEST_F(BasicCurlHttpTests, SendGetRequestSyncTimeout) | ||
{ | ||
received_requests_.clear(); | ||
curl::SessionManager session_manager; | ||
|
||
auto session = | ||
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. If I need to send 2 synchronous requests from two different threads, do I need to create two separate sessions? Why do I have to specify session IP, port, and Uri separately - is there a reason to not having something like:
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.
Yeah, its doable as separate PR. 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. Ok, I have done the modified sync requests as below:
|
||
session_manager.CreateSession("222.222.222.200", HTTP_PORT); // Non Existing address | ||
auto request = session->CreateRequest(); | ||
request->SetTimeoutMs(std::chrono::milliseconds(3000)); | ||
request->SetUri("get/"); | ||
http_client::SessionState session_state; | ||
auto response = session->SendRequestSync(session_state); | ||
EXPECT_EQ(session_state, http_client::SessionState::ConnectFailed); | ||
EXPECT_TRUE(response == nullptr); | ||
} |
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.
I believe it would be much cleaner if you operate only on
Response
object rather than onSessionState
. Let me elaborate - right now you have two possible states:success
- in this case you returnResponse
and status code; orfailure
- in this case you force the user to test ifResponse
ptr is nullptr, and then inspect theSessionState
parameter passed by reference.. which is not reallySession
state (becauseSession
may have multiple requests), but rather this exactRequest
state.So since in reality it is
Request
state, can you have this aggregated onResponse
object - making sure that you always returnResponse
: failed or succeeded, always return it. It may be successful response or empty response, failed response, with an indication onResponse
object that it's a failed response. Then you avoid the nullptr entirely, you avoid checking on two separate objects, and you can just propagate the object elsewhere to the place that needs to make a decision what to do next with that failed request-response pair.Could you please clarify - if the original intent of
SessionManager
was to support more than one concurrent request at a time? If so, thenSessionState
is a misleading name for a synchronous request resultt. Session may have more than one request, one failed, one successful, andSessionState
name does not represent the actualSessionManager
Session state.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.
Response
object represents http-response containing - body, header and code. Any error during http handshake are returned inSessionState
. This is to keep it consistent with how we achieve it in async requests:If it's fine, we can always return empty response in case of error, and the
Response::status_code
would be 0 in that case.Session
is more of logical entity, and doesn't represent multiple ongoing http requests.SessionManager
-> MultipleSession
s.Single
Session
-> SingleRequest