From e59b30301a03f9b3b7e943c795d9e3f4f5a8fc4e Mon Sep 17 00:00:00 2001 From: OSSRS-AI Date: Tue, 18 Nov 2025 12:12:16 -0500 Subject: [PATCH] AI: API: Change pagination default count to 10, minimum 1. v7.0.128 (#4584) --- trunk/doc/CHANGELOG.md | 1 + trunk/src/app/srs_app_http_api.cpp | 24 ++++-- trunk/src/app/srs_app_http_api.hpp | 6 ++ trunk/src/core/srs_core_version7.hpp | 2 +- trunk/src/utest/srs_utest_ai24.cpp | 105 +++++++++++++++++++++++++++ 5 files changed, 129 insertions(+), 9 deletions(-) diff --git a/trunk/doc/CHANGELOG.md b/trunk/doc/CHANGELOG.md index 2eb333f41..16599decf 100644 --- a/trunk/doc/CHANGELOG.md +++ b/trunk/doc/CHANGELOG.md @@ -7,6 +7,7 @@ The changelog for SRS. ## SRS 7.0 Changelog +* v7.0, 2025-11-18, AI: API: Change pagination default count to 10, minimum 1. v7.0.128 * v7.0, 2025-11-14, AI: Fix race condition causing immediate deletion of new sources. v7.0.127 (#4449) * v7.0, 2025-11-11, AI: WebRTC: Support optional msid attribute per RFC 8830. v7.0.126 (#4570) * v7.0, 2025-11-11, AI: SRT: Stop TS parsing after codec detection. v7.0.125 (#4569) diff --git a/trunk/src/app/srs_app_http_api.cpp b/trunk/src/app/srs_app_http_api.cpp index 72f414b15..e2d7e1c5b 100644 --- a/trunk/src/app/srs_app_http_api.cpp +++ b/trunk/src/app/srs_app_http_api.cpp @@ -147,6 +147,18 @@ srs_error_t srs_api_response_code(ISrsHttpResponseWriter *w, ISrsHttpMessage *r, return srs_api_response_jsonp_code(w, callback, code); } +void srs_api_parse_pagination(ISrsHttpMessage *r, int &start, int &count) +{ + std::string rstart = r->query_get("start"); + std::string rcount = r->query_get("count"); + + // Parse start parameter, default to 0, minimum 0. + start = srs_max(0, atoi(rstart.c_str())); + + // Parse count parameter, default to 10, minimum 1. + count = rcount.empty() ? 10 : srs_max(1, atoi(rcount.c_str())); +} + // @remark we will free the code. srs_error_t srs_api_response_code(ISrsHttpResponseWriter *w, ISrsHttpMessage *r, srs_error_t code) { @@ -794,10 +806,8 @@ srs_error_t SrsGoApiStreams::serve_http(ISrsHttpResponseWriter *w, ISrsHttpMessa SrsJsonArray *data = SrsJsonAny::array(); obj->set("streams", data); - std::string rstart = r->query_get("start"); - std::string rcount = r->query_get("count"); - int start = srs_max(0, atoi(rstart.c_str())); - int count = srs_max(1, atoi(rcount.c_str())); + int start, count; + srs_api_parse_pagination(r, start, count); if ((err = stat_->dumps_streams(data, start, count)) != srs_success) { int code = srs_error_code(err); srs_freep(err); @@ -866,10 +876,8 @@ srs_error_t SrsGoApiClients::serve_http(ISrsHttpResponseWriter *w, ISrsHttpMessa SrsJsonArray *data = SrsJsonAny::array(); obj->set("clients", data); - std::string rstart = r->query_get("start"); - std::string rcount = r->query_get("count"); - int start = srs_max(0, atoi(rstart.c_str())); - int count = srs_max(1, atoi(rcount.c_str())); + int start, count; + srs_api_parse_pagination(r, start, count); if ((err = stat_->dumps_clients(data, start, count)) != srs_success) { int code = srs_error_code(err); srs_freep(err); diff --git a/trunk/src/app/srs_app_http_api.hpp b/trunk/src/app/srs_app_http_api.hpp index b986141fb..98bc446e9 100644 --- a/trunk/src/app/srs_app_http_api.hpp +++ b/trunk/src/app/srs_app_http_api.hpp @@ -35,6 +35,12 @@ extern srs_error_t srs_api_response(ISrsHttpResponseWriter *w, ISrsHttpMessage * extern srs_error_t srs_api_response_code(ISrsHttpResponseWriter *w, ISrsHttpMessage *r, int code); extern srs_error_t srs_api_response_code(ISrsHttpResponseWriter *w, ISrsHttpMessage *r, srs_error_t code); +// Parse pagination parameters from HTTP request query string. +// @param r The HTTP request message. +// @param start Output parameter for start index, defaults to 0, minimum 0. +// @param count Output parameter for count, defaults to 10, minimum 1. +extern void srs_api_parse_pagination(ISrsHttpMessage *r, int &start, int &count); + // For http root. class SrsGoApiRoot : public ISrsHttpHandler { diff --git a/trunk/src/core/srs_core_version7.hpp b/trunk/src/core/srs_core_version7.hpp index 65afefc46..0940d73d3 100644 --- a/trunk/src/core/srs_core_version7.hpp +++ b/trunk/src/core/srs_core_version7.hpp @@ -9,6 +9,6 @@ #define VERSION_MAJOR 7 #define VERSION_MINOR 0 -#define VERSION_REVISION 127 +#define VERSION_REVISION 128 #endif \ No newline at end of file diff --git a/trunk/src/utest/srs_utest_ai24.cpp b/trunk/src/utest/srs_utest_ai24.cpp index 6f03e2614..7d6736f92 100644 --- a/trunk/src/utest/srs_utest_ai24.cpp +++ b/trunk/src/utest/srs_utest_ai24.cpp @@ -8,6 +8,7 @@ #include #include #include +#include #include #include #include @@ -21,6 +22,7 @@ #include #include #include +#include #ifdef SRS_FFMPEG_FIT #include @@ -1311,3 +1313,106 @@ VOID TEST(SdpTest, ParseLibdatachannelSdpFromIssue4570) } EXPECT_TRUE(found_audio_ssrc); } + +// Test: srs_api_parse_pagination with various input scenarios +VOID TEST(HttpApiPaginationTest, ParsePagination) +{ + int start, count; + + // Test 1: Default values (no query parameters) + if (true) { + MockHttpMessageForApiResponse mock_msg; + srs_api_parse_pagination(&mock_msg, start, count); + EXPECT_EQ(0, start); + EXPECT_EQ(10, count); + } + + // Test 2: Valid start and count + if (true) { + MockHttpMessageForApiResponse mock_msg; + mock_msg.query_params_["start"] = "5"; + mock_msg.query_params_["count"] = "20"; + srs_api_parse_pagination(&mock_msg, start, count); + EXPECT_EQ(5, start); + EXPECT_EQ(20, count); + } + + // Test 3: Zero count (should use minimum 1) + if (true) { + MockHttpMessageForApiResponse mock_msg; + mock_msg.query_params_["start"] = "0"; + mock_msg.query_params_["count"] = "0"; + srs_api_parse_pagination(&mock_msg, start, count); + EXPECT_EQ(0, start); + EXPECT_EQ(1, count); + } + + // Test 4: Negative start (should use minimum 0) + if (true) { + MockHttpMessageForApiResponse mock_msg; + mock_msg.query_params_["start"] = "-10"; + mock_msg.query_params_["count"] = "5"; + srs_api_parse_pagination(&mock_msg, start, count); + EXPECT_EQ(0, start); + EXPECT_EQ(5, count); + } + + // Test 5: Negative count (should use minimum 1) + if (true) { + MockHttpMessageForApiResponse mock_msg; + mock_msg.query_params_["start"] = "10"; + mock_msg.query_params_["count"] = "-5"; + srs_api_parse_pagination(&mock_msg, start, count); + EXPECT_EQ(10, start); + EXPECT_EQ(1, count); + } + + // Test 6: Empty count string (should use default 10) + if (true) { + MockHttpMessageForApiResponse mock_msg; + mock_msg.query_params_["start"] = "5"; + mock_msg.query_params_["count"] = ""; + srs_api_parse_pagination(&mock_msg, start, count); + EXPECT_EQ(5, start); + EXPECT_EQ(10, count); + } + + // Test 7: Only start parameter + if (true) { + MockHttpMessageForApiResponse mock_msg; + mock_msg.query_params_["start"] = "15"; + srs_api_parse_pagination(&mock_msg, start, count); + EXPECT_EQ(15, start); + EXPECT_EQ(10, count); + } + + // Test 8: Only count parameter + if (true) { + MockHttpMessageForApiResponse mock_msg; + mock_msg.query_params_["count"] = "25"; + srs_api_parse_pagination(&mock_msg, start, count); + EXPECT_EQ(0, start); + EXPECT_EQ(25, count); + } + + // Test 9: Invalid (non-numeric) values + if (true) { + MockHttpMessageForApiResponse mock_msg; + mock_msg.query_params_["start"] = "abc"; + mock_msg.query_params_["count"] = "xyz"; + srs_api_parse_pagination(&mock_msg, start, count); + // atoi returns 0 for invalid strings + EXPECT_EQ(0, start); + EXPECT_EQ(1, count); // minimum enforced since atoi returns 0 + } + + // Test 10: Large values + if (true) { + MockHttpMessageForApiResponse mock_msg; + mock_msg.query_params_["start"] = "1000000"; + mock_msg.query_params_["count"] = "500"; + srs_api_parse_pagination(&mock_msg, start, count); + EXPECT_EQ(1000000, start); + EXPECT_EQ(500, count); + } +}