libcpr / cpr

C++ Requests: Curl for People, a spiritual port of Python Requests.
https://docs.libcpr.org/
Other
6.49k stars 924 forks source link

Expose the global session under the hood #958

Closed zuoxinyu closed 1 year ago

zuoxinyu commented 1 year ago

Is your feature request related to a problem?

I want perform logging on every request/response emitted by cpr::Get() / cpr::Post() / cpr::Put() etc... , but the interceptor can only attached to a session.

Possible Solution

I don't know is there a hidden global session behind global request methods like get/post.

If there is, it's better to expose it via a method like cpr::GlobalSession() so that users can use AddInterceptor() or SetOption() which performing on each global call, without creating a session.

A simple example:

auto &session = cpr::GlobalSession();
session.AddInterceptor(logger_interceptor);
session.SetProxies({{"http", "http://proxyserver.com"}});
auto resp = cpr::Get(cpr::Url{"http://example.com"});       // via proxy and perform logging on request/response
resp = cpr::Post(cpr::Url{"http:example.com/resources"})
...

Alternatives

No response

Additional Context

No response

COM8 commented 1 year ago

Thanks for reporting @zuoxinyu !

Solution

Do not use the global cpr::Get, ... operations since they create a temporary session object. This means, if you call cpr:Get twice, it will create two session objects with individual http handshakes and connection establishments.

https://github.com/libcpr/cpr/blob/253346373575b383a56e2741b8250a6acf6fa50e/include/cpr/api.h#L116-L122

zuoxinyu commented 1 year ago

Alright I've read the source code for Get. In that case, maybe we could add some API to the cpr::Session class in the same style as cpr::Get, which would do the same thing just like we have a GlobalSession.

COM8 commented 1 year ago

Sorry, but I don't really get what you want. We won't be having a global session since then we would limit/have to deal with concurrency.

If you want to log everything, setup your own global cpr::Session(s) and insert an cpr::Interceptor inside them.

e.g.

cpr::Session GlobalSession;

class LoggingInterceptor : public cpr::Interceptor {
  public:
    cpr::Response intercept(cpr::Session& session) override {
        // Log the request URL
        std::cout << "Request url: " << session.GetFullRequestUrl() << std::endl;

        // Proceed the request and save the response
        cpr::Response response = proceed(session);

        // Log response status code
        std::cout << "Response status code: " << response.status_code << std::endl;

        // Return the stored response
        return response;
    }
};

int main() {
    GlobalSession.AddInterceptor(std::make_shared<LoggingInterceptor>());

    // Do other stuff...
}

Here you can find more examples: https://docs.libcpr.org/advanced-usage.html#interceptors