-
Notifications
You must be signed in to change notification settings - Fork 1.7k
Support CURL based HTTP client #1182
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
Conversation
6388246 to
0b259d8
Compare
|
That sounds like a cool extension of cpprestsdk. Particularly, because it might have the potential to replace the somewhat crude HTTP protocol implementation of A while ago we proposed a pull request to integrate the ASIO client with Botan to remove the dependency of OpenSSL (and SChannel/WinHTTP for that matter). At the time, this PR was actually meant as a draft and @garethsb-sony correctly noted that it might be time to rethink the HTTP/TLS backend architecture of cpprestsdk. In case this pull request is meant in a similar way, we would be interested to join the discussion and potentially help to get our Botan backend upstream one or the other way. Currently we maintain it as a custom fork of cpprestsdk, but maybe it might be helpful for the community as well. For the matter of ideas: Wrapping boost Beast under cpprestsdk would probably be a great addition as well. |
|
Thanks for the interest. We actually want to go to OpenSSL route using CURL as the http backend so that we can use our custom OpenSSL engine during HTTP negotiation. Primary driving decision is to abstract the primary keys from the application for security reasons. Our investigation showed that this is not possible with boost ASIO or boost beast. We didn't have any concerns about the complexity involved in ASIO layer since we never looked at it. CURL seems to be the right fit. It is small and scalable. The only reason why we stacked curl on top of winhttp is because winhttp interface is well documented. We just had to emulate winhttp API just enough with CURL to get to functional state. We could have written a curl only client but we see bigger interest in having a light WinHTTP layer on other applications. We are planning to post a winhttppal project in github in the future. |
BillyONeal
left a comment
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.
This change needs associated changes to azure-pipelines.yaml to ensure tests are passing for this backend, and so that future maintenance doesn't regress its behavior.
I'm not a fan of now 3 layers of wrappers (cpprestsdk/curl-winhttp-wrapper/curl) in particular because the names the winhttp wrapper use conflict with the real winhttp function names, meaning the backend can't be compiled or used on Windows.
| , m_tlsext_sni_enabled(true) | ||
| #endif | ||
| #if defined(_WIN32) && !defined(__cplusplus_winrt) | ||
| #if (defined(_WIN32) && !defined(__cplusplus_winrt)) || defined(CPPREST_FORCE_HTTP_CLIENT_CURL) |
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.
Hmmm I think with this we are moving to a place where the backend is not just a function of the platform, it's something someone might want to trigger from. We should probably change the build infrastructure to set CPPREST_FORCE_HTTP_CLIENT_Xxx where Xxx can be one of the backends, and remove all of this repeated platform testing (here (defined(_WIN32) && !defined(__cplusplus_winrt))) in the codebase.
That's not directly related to this review of course but I want to investigate doing that before merging this.
|
I believe I addressed all concerns in the review. Can you please take a look one more time? |
| { | ||
| WinHttpBase *base = static_cast<WinHttpBase *>(hInternet); | ||
|
|
||
|
|
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.
what happens if "offers" is a tls version higher than the used libcurl understands? wouldn't this line cause curl to use a sslversion < what was offered?
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.
That's true. Offered is not what is actually used. Upper level gives a list of options that the transport protocol can use. What actually gets used depends on the curl version.
If there is a complete mismatch in terms of capabilities, CURL will use the CURL_SSLVERSION_DEFAULT as a minimum and CURL_SSLVERSION_MAX_DEFAULT as a maximum.
These definitions come from the current curl library in use.
Are you interested in enforcing the offered as required?
The time to merge things to master is not when they're 'enough to be in a functional state'. Pushing the merge button means that the owners of cpprestsdk are taking responsibility for maintaining and shipping the code in the PR, and we are not interested in maintaining a Curl-To-WinHTTP abstraction layer.
If you want to make this as a separate project and then point cpprestsdk to it as an external dependency, that would be far more acceptable. But it's failing some of the test cases for the actual WinHTTP implementation (e.g. handling of the Host: header), meaning this isn't actually meeting WinHTTP's contract somewhere. |
The project is now public. I'll take your suggestion and create a dependency there. I actually debugged the host header failure. It is failing because libcurl sends "accept encoding" by default and test is expecting to observe only the headers it sent. I can fix the failing test. That's the only issue here. |
BillyONeal
left a comment
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.
Based on your comments I don't really think our interests are aligned here.
| TEST(server_hostname_mismatch) { test_failed_ssl_cert(U("https://wrong.host.badssl.com/")); } | ||
|
|
||
| #if !defined(__cplusplus_winrt) | ||
| #if !defined(__cplusplus_winrt) && !defined(CPPREST_FORCE_HTTP_CLIENT_CURL) |
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.
These tests failing suggests that you aren't handling the Host: header correctly in TLS.
|
|
||
| void on_send_request_validate_cn() | ||
| { | ||
| // we do the validation inside curl |
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 don't think so because you're failing these tests.
- If this is the case then you should just remove the function entirely rather than leaving a noop.
OK, then can you structure it like this:
I think that will put us much closer to something we can consider merging. /cc @barcharcraz |
isn't also: I'd be OK with billy's suggested actions, or with a new "curl only" backend that didn't depend on anything to do with winhttp. Also, the build script should make the winhttppal an opt in thing. And when opted in it should apply on all platforms (so if you ask for the pal you get it everywhere, not just on platforms without winhttp). |
Why is winhttppal reserved? WinHttp is an existing client library in windows but winhttppal doesn't exist anywhere else except the github page I linked
Yeah, I'll follow the actions. As I said, we are seeing the winhttppal being used in multiple projects that are trying to migrate to linux. It has a big benefit for a lot of folks.
Both winhttppal and curl works on windows as well as linux. Code was developed on windows using visual studio and c++ 11 primitives only. Later tested on linux with ubuntu 16.04 and ubuntu 18.04. Code is cross-platform compatible. |
Yes, sorry, I had my 'STL maintainer' hat on :P. (I don't actually care what the macro is as long as it's descriptive) |
I just mean that I'd prefer we don't try and have the buildsystem guess if you want/need winhttppal. |
- static analysis - hide copy constructors - Remove terminatestring function and size the buffers appropriately - No need for empty string initialization - Use references instead of copies where possible - replace atoi with stoi - No need to check null pointer on delete - Fix copy paste mistake - Support older curl versions - More read function unifications
462b710 to
2124784
Compare
|
@BillyONeal : can you review the changes? I think I didn't understand some of the preprocessor macro comments you were mentioning about. |
BillyONeal
left a comment
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.
LGTM, thanks for your contribution.
@barcharcraz Can you take a look?
|
Thanks for your contribution! |
This is a curl based HTTP client that allows us to use custom SSL engines. Adaptation layer is a stripped down version of http_client_winhttp.cpp. WinHTTP functions (aka winhttppal) has been written from scratch against the MULTI curl interface.
While the current code is not complete, it is %95 functional.
1700 test pass
4 test failures
compression_tests:compress_client_server
connections_and_errors:server_close_without_responding
outside_tests:request_headers
progress_handler_tests:set_progress_handler_request_timeout
3 test not supported
outside_tests:server_hostname_host_override
outside_tests:server_hostname_host_override_after_upgrade
client_construction:ssl_context_callback_https
proxy and authentication tests not run.