Skip to content

Commit

Permalink
[feat] http client with cert
Browse files Browse the repository at this point in the history
Signed-off-by: zhuangbowei.zbw <zhuangbowei.zbw@alibaba-inc.com>
  • Loading branch information
WaberZhuang committed Dec 14, 2023
1 parent 6bdc1df commit 9c07a1d
Show file tree
Hide file tree
Showing 4 changed files with 118 additions and 5 deletions.
27 changes: 22 additions & 5 deletions net/http/client.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,13 @@ class PooledDialer {
resolver(new_default_resolver(kDNSCacheLife)) {
}

PooledDialer(TLSContext *_tls_ctx) :
tls_ctx(_tls_ctx),
tcpsock(new_tcp_socket_pool(new_tcp_socket_client(), -1, true)),
tlssock(new_tcp_socket_pool(new_tls_client(tls_ctx, new_tcp_socket_client(), true), -1, true)),
resolver(new_default_resolver(kDNSCacheLife)) {
}

~PooledDialer() { delete tls_ctx; }

ISocketStream* dial(std::string_view host, uint16_t port, bool secure,
Expand Down Expand Up @@ -104,11 +111,19 @@ enum RoundtripStatus {

class ClientImpl : public Client {
public:
PooledDialer m_dialer;
PooledDialer *m_dialer;
CommonHeaders<> m_common_headers;
ICookieJar *m_cookie_jar;
ClientImpl(ICookieJar *cookie_jar) :
m_cookie_jar(cookie_jar) {}
m_cookie_jar(cookie_jar),
m_dialer(new PooledDialer()) {}

ClientImpl(ICookieJar *cookie_jar, TLSContext *tls_ctx) :
m_cookie_jar(cookie_jar),
m_dialer(new PooledDialer(tls_ctx)) {
}

~ClientImpl() { delete m_dialer; }

using SocketStream_ptr = std::unique_ptr<ISocketStream>;
int redirect(Operation* op) {
Expand Down Expand Up @@ -150,8 +165,8 @@ class ClientImpl : public Client {
LOG_ERROR_RETURN(ETIMEDOUT, ROUNDTRIP_FAILED, "connection timedout");
auto &req = op->req;
auto s = (m_proxy && !m_proxy_url.empty())
? m_dialer.dial(m_proxy_url, tmo.timeout())
: m_dialer.dial(req, tmo.timeout());
? m_dialer->dial(m_proxy_url, tmo.timeout())
: m_dialer->dial(req, tmo.timeout());
if (!s) LOG_ERROR_RETURN(0, ROUNDTRIP_NEED_RETRY, "connection failed");

SocketStream_ptr sock(s);
Expand Down Expand Up @@ -250,7 +265,7 @@ class ClientImpl : public Client {
}

ISocketStream* native_connect(std::string_view host, uint16_t port, bool secure, uint64_t timeout) override {
return m_dialer.dial(host, port, secure, timeout);
return m_dialer->dial(host, port, secure, timeout);
}

CommonHeaders<>* common_headers() override {
Expand All @@ -260,6 +275,8 @@ class ClientImpl : public Client {

Client* new_http_client(ICookieJar *cookie_jar) { return new ClientImpl(cookie_jar); }

Client* new_http_client_with_tls(ICookieJar *cookie_jar, TLSContext *tls_ctx) { return new ClientImpl(cookie_jar, tls_ctx); }

} // namespace http
} // namespace net
} // namespace photon
4 changes: 4 additions & 0 deletions net/http/client.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ limitations under the License.
#include <photon/common/stream.h>
#include <photon/common/timeout.h>
#include <photon/net/socket.h>
#include <photon/net/security-context/tls-stream.h>


namespace photon {
Expand Down Expand Up @@ -135,6 +136,9 @@ class Client : public Object {
//A Client without cookie_jar would ignore all response-header "Set-Cookies"
Client* new_http_client(ICookieJar *cookie_jar = nullptr);

//tls_ctx with be deleted cascade with client
Client* new_http_client_with_tls(ICookieJar *cookie_jar = nullptr, TLSContext *tls_ctx = nullptr);

ICookieJar* new_simple_cookie_jar();

} // namespace http
Expand Down
4 changes: 4 additions & 0 deletions net/http/test/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -26,3 +26,7 @@ add_test(NAME cookie_jar_test COMMAND $<TARGET_FILE:cookie_jar_test>)
add_executable(headers_test headers_test.cpp)
target_link_libraries(headers_test PRIVATE photon_shared ${testing_libs})
add_test(NAME headers_test COMMAND $<TARGET_FILE:headers_test>)

add_executable(client_tls_test client_tls_test.cpp)
target_link_libraries(client_tls_test PRIVATE photon_shared ${testing_libs})
add_test(NAME client_tls_test COMMAND $<TARGET_FILE:client_tls_test>)
88 changes: 88 additions & 0 deletions net/http/test/client_tls_test.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
/*
Copyright 2022 The Photon Authors
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

#include <gtest/gtest.h>

#include <photon/photon.h>
#include <photon/common/alog.h>
#include <photon/common/alog-stdstring.h>
#include <photon/thread/thread.h>
#include <photon/net/socket.h>
#include <photon/net/security-context/tls-stream.h>
#include <photon/net/http/message.h>
#include <photon/net/http/server.h>
#include <photon/net/http/client.h>

#include "../../test/cert-key.cpp"

using namespace photon;

int idiot_handler(void*, net::http::Request &req, net::http::Response &resp, std::string_view) {
std::string str;
auto r = req.headers.range();
auto cl = r.second - r.first + 1;
if (cl > 4096) {
LOG_ERROR_RETURN(0, -1, "RetType failed test");
}
resp.set_result(200);
resp.headers.content_length(cl);
resp.headers.insert("Test_Handle", "test");

str.resize(cl);
memset((void*)str.data(), '0', cl);
resp.write((void*)str.data(), str.size());
return 0;
}

TEST(client_tls, basic) {
auto ctx = net::new_tls_context(cert_str, key_str, passphrase_str);
auto tcpserver = net::new_tls_server(ctx, net::new_tcp_socket_server(), true);
DEFER(delete tcpserver);
tcpserver->timeout(1000UL*1000);
tcpserver->setsockopt(SOL_SOCKET, SO_REUSEPORT, 1);
tcpserver->bind(19876, net::IPAddr("127.0.0.1"));
tcpserver->listen();

auto server = net::http::new_http_server();
DEFER(delete server);
server->add_handler({nullptr, &idiot_handler});

tcpserver->set_handler(server->get_connection_handler());
tcpserver->start_loop();

auto client = net::http::new_http_client_with_tls(nullptr, ctx);
DEFER(delete client);
auto op = client->new_operation(net::http::Verb::GET, "https://localhost:19876/test");
DEFER(delete op);
auto exp_len = 20;
op->req.headers.range(0, exp_len - 1);
op->call();
EXPECT_EQ(200, op->resp.status_code());
char buf[4096];
auto ret = op->resp.read(buf, 4096);
EXPECT_EQ(exp_len, ret);
EXPECT_EQ(true, "test" == op->resp.headers["Test_Handle"]);
}

int main(int argc, char** arg) {
if (photon::init(photon::INIT_EVENT_DEFAULT, photon::INIT_IO_NONE))
return -1;
DEFER(photon::fini());
set_log_output_level(ALOG_DEBUG);
::testing::InitGoogleTest(&argc, arg);
LOG_DEBUG("test result:`", RUN_ALL_TESTS());
return 0;
}

0 comments on commit 9c07a1d

Please sign in to comment.