drogonframework / drogon

Drogon: A C++14/17/20 based HTTP web application framework running on Linux/macOS/Unix/Windows
MIT License
11.52k stars 1.1k forks source link

Add coroutines support for HttpFilter #1225

Closed omar-mohamed-khallaf closed 2 years ago

omar-mohamed-khallaf commented 2 years ago

Is your feature request related to a problem? Please describe. Executing queries in HttpFilter specially for redis becomes messy because of the callbacks and dependency between the queries:

Describe the solution you'd like Add coroutines support for HttpFilter::doFilter method.

Additional context Example:

auto redisClient = drogon::app().getFastRedisClient();
    redisClient->execCommandAsync(
            [fcb, redisClient, username](const drogon::nosql::RedisResult &result) {
                redisClient->execCommandAsync(
                        [fcb, redisClient, username](const drogon::nosql::RedisResult &result) {
                            redisClient->execCommandAsync(
                                    [fcb, redisClient](const drogon::nosql::RedisResult &result) {
                                        redisClient->execCommandAsync(
                                                [](const drogon::nosql::RedisResult &result) {
                                                    for (const auto &r : result.asArray())
                                                        LOG_DEBUG << r.asInteger();
                                                    },
                                                [fcb](const drogon::nosql::RedisException &exception) {
                                                    returnUnauthorized(exception.what(), fcb);
                                                    },
                                                "EXEC");
                                    },
                                    [fcb](const drogon::nosql::RedisException &exception) {
                                        returnUnauthorized(exception.what(), fcb);
                                        },
                                    "EXPIRE qbook:%s.actions %s", username.c_str(), std::to_string(SESSION_EXPIRE_SEC).c_str());
                        },
                        [fcb](const drogon::nosql::RedisException &exception) {
                            returnUnauthorized(exception.what(), fcb);
                            },
                        "EXPIRE qbook:%s.session_id %s", username.c_str(), std::to_string(SESSION_EXPIRE_SEC).c_str());
            },
            [fcb](const drogon::nosql::RedisException &exception) {
                returnUnauthorized(exception.what(), fcb);
                },
            "MULTI");
1111mp commented 2 years ago

Does the filter support async?

auto redisClientPtr = app().getRedisClient();
transPtr->execCommandAsync(
        [fccb](const nosql::RedisResult &r) { 
                   // successed
                   return fccb();
                 },
        [](const std::exception &err) { /* this command failed */ },
        "del %s", auth.data());

I have tested in my project and it seems that only synchronous methods can be used.

hwc0919 commented 2 years ago

Does the filter support async?

auto redisClientPtr = app().getRedisClient();
transPtr->execCommandAsync(
      [fccb](const nosql::RedisResult &r) { 
                   // successed
                   return fccb();
                 },
      [](const std::exception &err) { /* this command failed */ },
      "del %s", auth.data());

I have tested in my project and it seems that only synchronous methods can be used.

@1111mp It does, but the filter chain callback must be running on the IO threads due to some implementation details. So you can only use fast RedisClient or fast DbClient here.