From 3142fb96b9c308cddb108d75c4b9b516a67559a2 Mon Sep 17 00:00:00 2001 From: Arsentiy Milchakov Date: Thu, 19 Oct 2017 12:44:15 +0300 Subject: [PATCH] [partners_api] booking api small refactoring --- partners_api/CMakeLists.txt | 2 + partners_api/booking_api.cpp | 94 ++----------------- partners_api/booking_api.hpp | 35 +------ partners_api/booking_http.cpp | 88 +++++++++++++++++ partners_api/booking_http.hpp | 48 ++++++++++ partners_api/partners_api.pro | 2 + .../partners_api_tests/booking_tests.cpp | 30 +++--- .../partners_api.xcodeproj/project.pbxproj | 8 ++ 8 files changed, 175 insertions(+), 132 deletions(-) create mode 100644 partners_api/booking_http.cpp create mode 100644 partners_api/booking_http.hpp diff --git a/partners_api/CMakeLists.txt b/partners_api/CMakeLists.txt index 8af42c3e9a..d3e8239399 100644 --- a/partners_api/CMakeLists.txt +++ b/partners_api/CMakeLists.txt @@ -11,6 +11,8 @@ set( banner.hpp booking_api.cpp booking_api.hpp + booking_http.cpp + booking_http.hpp cian_api.cpp cian_api.hpp facebook_ads.cpp diff --git a/partners_api/booking_api.cpp b/partners_api/booking_api.cpp index bba059d78a..57945fa4cc 100644 --- a/partners_api/booking_api.cpp +++ b/partners_api/booking_api.cpp @@ -1,6 +1,5 @@ #include "partners_api/booking_api.hpp" -#include "platform/http_client.hpp" #include "platform/platform.hpp" #include "coding/url_encode.hpp" @@ -9,10 +8,7 @@ #include "base/logging.hpp" #include "base/thread.hpp" -#include -#include #include -#include #include #include @@ -20,8 +16,8 @@ #include "private.h" -using namespace platform; using namespace booking; +using namespace booking::http; using namespace std; using namespace std::chrono; @@ -35,77 +31,22 @@ string const kPhotoSmallUrl = "http://aff.bstatic.com/images/hotel/max300/"; string const kSearchBaseUrl = "https://www.booking.com/search.html"; string g_BookingUrlForTesting = ""; -bool RunSimpleHttpRequest(bool const needAuth, string const & url, string & result) -{ - HttpClient request(url); - - if (needAuth) - request.SetUserAndPassword(BOOKING_KEY, BOOKING_SECRET); - - if (request.RunHttpRequest() && !request.WasRedirected() && request.ErrorCode() == 200) - { - result = request.ServerResponse(); - return true; - } - - return false; -} - -string MakeApiUrl(string const & baseUrl, string const & func, - vector> const & params) -{ - ASSERT_NOT_EQUAL(params.size(), 0, ()); - - ostringstream os; - if (!g_BookingUrlForTesting.empty()) - os << g_BookingUrlForTesting << func << "?"; - else - os << baseUrl << func << "?"; - - bool firstParam = true; - for (auto const & param : params) - { - if (firstParam) - { - firstParam = false; - } - else - { - os << "&"; - } - os << param.first << "=" << param.second; - } - - return os.str(); -} - string MakeApiUrlV1(string const & func, vector> const & params) { + if (!g_BookingUrlForTesting.empty()) + return MakeApiUrl(g_BookingUrlForTesting, "." + func, params); + return MakeApiUrl(kBookingApiBaseUrlV1, "." + func, params); } string MakeApiUrlV2(string const & func, vector> const & params) { + if (!g_BookingUrlForTesting.empty()) + return MakeApiUrl(g_BookingUrlForTesting, "/" + func, params); + return MakeApiUrl(kBookingApiBaseUrlV2, "/" + func, params); } -std::string FormatTime(system_clock::time_point p) -{ - time_t t = duration_cast(p.time_since_epoch()).count(); - ostringstream os; - os << put_time(std::gmtime(&t), "%Y-%m-%d"); - return os.str(); -} - -string FormatByComma(vector const & src) -{ - ostringstream os; - ostream_iterator outIt(os, ","); - copy(src.cbegin(), src.cend(), outIt); - - return os.str(); -} - void ClearHotelInfo(HotelInfo & info) { info.m_hotelId.clear(); @@ -291,26 +232,6 @@ void FillHotelIds(string const & src, vector & result) namespace booking { -vector> AvailabilityParams::Get() const -{ - vector> result; - - result.push_back({"hotel_ids", FormatByComma(m_hotelIds)}); - result.push_back({"checkin", FormatTime(m_checkin)}); - result.push_back({"checkout", FormatTime(m_checkout)}); - - for (size_t i = 0; i < m_rooms.size(); ++i) - result.push_back({"room" + to_string(i+1), m_rooms[i]}); - - if (m_minReviewScore != 0.0) - result.push_back({"min_review_score", std::to_string(m_minReviewScore)}); - - if (!m_stars.empty()) - result.push_back({"stars", FormatByComma(m_stars)}); - - return result; -} - // static bool RawApi::GetHotelAvailability(string const & hotelId, string const & currency, string & result) { @@ -452,7 +373,6 @@ void Api::GetHotelAvailability(AvailabilityParams const & params, } catch (my::Json::Exception const & e) { - LOG(LINFO, (httpResult)); LOG(LERROR, (e.Msg())); result.clear(); } diff --git a/partners_api/booking_api.hpp b/partners_api/booking_api.hpp index 1cd8bd86b7..e95fa871d4 100644 --- a/partners_api/booking_api.hpp +++ b/partners_api/booking_api.hpp @@ -1,10 +1,11 @@ #pragma once +#include "partners_api/booking_http.hpp" + #include "platform/safe_callback.hpp" #include #include -#include #include #include @@ -47,34 +48,6 @@ struct HotelInfo uint32_t m_scoreCount = 0; }; -/// Params for checking availability of hotels. -/// [m_hotelIds], [m_checkin], [m_checkout], [m_rooms] are required. -struct AvailabilityParams -{ - using Time = std::chrono::system_clock::time_point; - - std::vector> Get() const; - - /// Limit the result list to the specified hotels where they have availability for the - /// specified guests and dates. - std::vector m_hotelIds; - /// The arrival date. Must be within 360 days in the future and in the format yyyy-mm-dd. - Time m_checkin; - /// The departure date. Must be later than [m_checkin]. Must be between 1 and 30 days after - /// [m_checkin]. Must be within 360 days in the future and in the format yyyy-mm-dd. - Time m_checkout; - /// Each room is s comma separated array of guests to stay in this room where "A" represents an - /// adult and an integer represents a child. eg room1=A,A,4 would be a room with 2 adults and 1 - /// four year-old child. Child age numbers are 0..17. - std::vector m_rooms; - /// Show only hotels with review_score >= that. min_review_score should be in the range 1 to 10. - /// Values are rounded down: min_review_score 7.8 will result in properties with review scores - /// of 7 and up. - double m_minReviewScore = {}; - /// Limit to hotels with the given number(s) of stars. Supported values 1-5. - vector m_stars; -}; - class RawApi { public: @@ -82,7 +55,7 @@ public: static bool GetHotelAvailability(std::string const & hotelId, std::string const & currency, std::string & result); static bool GetExtendedInfo(std::string const & hotelId, std::string const & lang, std::string & result); // Booking Api v2 methods: - static bool HotelAvailability(AvailabilityParams const & params, std::string & result); + static bool HotelAvailability(http::AvailabilityParams const & params, std::string & result); }; using GetMinPriceCallback = platform::SafeCallback; @@ -104,7 +77,7 @@ public: /// These methods use caching server to prevent Booking from being ddossed. void GetHotelInfo(std::string const & hotelId, std::string const & lang, GetHotelInfoCallback const & fn); - void GetHotelAvailability(AvailabilityParams const & params, + void GetHotelAvailability(http::AvailabilityParams const & params, GetHotelAvailabilityCallback const & fn); }; diff --git a/partners_api/booking_http.cpp b/partners_api/booking_http.cpp new file mode 100644 index 0000000000..c33d07dc89 --- /dev/null +++ b/partners_api/booking_http.cpp @@ -0,0 +1,88 @@ +#include "partners_api/booking_http.hpp" + +#include "platform/http_client.hpp" + +#include "base/string_utils.hpp" + +#include +#include + +#include "private.h" + +using namespace platform; +using namespace std; +using namespace std::chrono; + +namespace booking +{ +namespace http +{ +bool RunSimpleHttpRequest(bool const needAuth, string const & url, string & result) +{ + HttpClient request(url); + + if (needAuth) + request.SetUserAndPassword(BOOKING_KEY, BOOKING_SECRET); + + if (request.RunHttpRequest() && !request.WasRedirected() && request.ErrorCode() == 200) + { + result = request.ServerResponse(); + return true; + } + + return false; +} + +string MakeApiUrl(string const & baseUrl, string const & func, Params const & params) +{ + ASSERT_NOT_EQUAL(params.size(), 0, ()); + + ostringstream os; + os << baseUrl << func << "?"; + + bool firstParam = true; + for (auto const & param : params) + { + if (firstParam) + { + firstParam = false; + } + else + { + os << "&"; + } + os << param.first << "=" << param.second; + } + + return os.str(); +} + +std::string FormatTime(Time p) +{ + time_t t = duration_cast(p.time_since_epoch()).count(); + ostringstream os; + os << put_time(std::gmtime(&t), "%Y-%m-%d"); + return os.str(); +} + +Params AvailabilityParams::Get() const +{ + Params result; + + result.push_back({"hotel_ids", strings::JoinStrings(m_hotelIds, ',')}); + result.push_back({"checkin", FormatTime(m_checkin)}); + result.push_back({"checkout", FormatTime(m_checkout)}); + + for (size_t i = 0; i < m_rooms.size(); ++i) + result.push_back({"room" + to_string(i + 1), m_rooms[i]}); + + if (m_minReviewScore != 0.0) + result.push_back({"min_review_score", std::to_string(m_minReviewScore)}); + + if (!m_stars.empty()) + result.push_back({"stars", strings::JoinStrings(m_stars, ',')}); + + return result; +} +} +} diff --git a/partners_api/booking_http.hpp b/partners_api/booking_http.hpp new file mode 100644 index 0000000000..0941c8fa47 --- /dev/null +++ b/partners_api/booking_http.hpp @@ -0,0 +1,48 @@ +#pragma once + +#include +#include +#include + +namespace booking +{ +namespace http +{ +bool RunSimpleHttpRequest(bool const needAuth, std::string const & url, std::string & result); + +using Time = std::chrono::system_clock::time_point; +using Params = std::vector>; +using Hotels = std::vector; +using Rooms = std::vector; +using Stars = std::vector; + +std::string MakeApiUrl(std::string const & baseUrl, std::string const & func, Params const & params); +std::string FormatTime(Time p); + +/// Params for checking availability of hotels. +/// [m_hotelIds], [m_checkin], [m_checkout], [m_rooms] are required. +struct AvailabilityParams +{ + Params Get() const; + + /// Limit the result list to the specified hotels where they have availability for the + /// specified guests and dates. + Hotels m_hotelIds; + /// The arrival date. Must be within 360 days in the future and in the format yyyy-mm-dd. + Time m_checkin; + /// The departure date. Must be later than [m_checkin]. Must be between 1 and 30 days after + /// [m_checkin]. Must be within 360 days in the future and in the format yyyy-mm-dd. + Time m_checkout; + /// Each room is s comma separated array of guests to stay in this room where "A" represents an + /// adult and an integer represents a child. eg room1=A,A,4 would be a room with 2 adults and 1 + /// four year-old child. Child age numbers are 0..17. + Rooms m_rooms; + /// Show only hotels with review_score >= that. min_review_score should be in the range 1 to 10. + /// Values are rounded down: min_review_score 7.8 will result in properties with review scores + /// of 7 and up. + double m_minReviewScore = {}; + /// Limit to hotels with the given number(s) of stars. Supported values 1-5. + Stars m_stars; +}; +} // namespace http +} // namespace booking diff --git a/partners_api/partners_api.pro b/partners_api/partners_api.pro index b3e4a05238..ef946fff85 100644 --- a/partners_api/partners_api.pro +++ b/partners_api/partners_api.pro @@ -12,6 +12,7 @@ SOURCES += \ ads_base.cpp \ ads_engine.cpp \ booking_api.cpp \ + booking_http.cpp \ cian_api.cpp \ facebook_ads.cpp \ google_ads.cpp \ @@ -31,6 +32,7 @@ HEADERS += \ ads_engine.hpp \ banner.hpp \ booking_api.hpp \ + booking_http.hpp \ cian_api.hpp \ facebook_ads.hpp \ google_ads.hpp \ diff --git a/partners_api/partners_api_tests/booking_tests.cpp b/partners_api/partners_api_tests/booking_tests.cpp index bf8e85994d..e09b444e6c 100644 --- a/partners_api/partners_api_tests/booking_tests.cpp +++ b/partners_api/partners_api_tests/booking_tests.cpp @@ -9,6 +9,8 @@ #include using namespace partners_api; +using namespace booking; +using namespace booking::http; namespace { @@ -16,7 +18,7 @@ UNIT_TEST(Booking_GetHotelAvailability) { string const kHotelId = "98251"; // Booking hotel id for testing. string result; - TEST(booking::RawApi::GetHotelAvailability(kHotelId, "", result), ()); + TEST(RawApi::GetHotelAvailability(kHotelId, "", result), ()); TEST(!result.empty(), ()); } @@ -24,31 +26,31 @@ UNIT_TEST(Booking_GetExtendedInfo) { string const kHotelId = "0"; // Internal hotel id for testing. string result; - TEST(booking::RawApi::GetExtendedInfo(kHotelId, "en", result), ()); + TEST(RawApi::GetExtendedInfo(kHotelId, "en", result), ()); TEST(!result.empty(), ()); } UNIT_TEST(Booking_HotelAvailability) { - booking::AvailabilityParams params; + AvailabilityParams params; params.m_hotelIds = {"98251"}; params.m_rooms = {"A,A"}; params.m_checkin = std::chrono::system_clock::now() + std::chrono::hours(24); params.m_checkout = std::chrono::system_clock::now() + std::chrono::hours(24 * 7); params.m_stars = {"4", "5"}; string result; - TEST(booking::RawApi::HotelAvailability(params, result), ()); + TEST(RawApi::HotelAvailability(params, result), ()); TEST(!result.empty(), ()); LOG(LINFO, (result)); } UNIT_CLASS_TEST(AsyncGuiThread, Booking_GetMinPrice) { - booking::SetBookingUrlForTesting("http://localhost:34568/booking/min_price"); - MY_SCOPE_GUARD(cleanup, []() { booking::SetBookingUrlForTesting(""); }); + SetBookingUrlForTesting("http://localhost:34568/booking/min_price"); + MY_SCOPE_GUARD(cleanup, []() { SetBookingUrlForTesting(""); }); string const kHotelId = "0"; // Internal hotel id for testing. - booking::Api api; + Api api; { string price; string currency; @@ -110,10 +112,10 @@ UNIT_CLASS_TEST(AsyncGuiThread, Booking_GetMinPrice) UNIT_CLASS_TEST(AsyncGuiThread, GetHotelInfo) { string const kHotelId = "0"; // Internal hotel id for testing. - booking::Api api; - booking::HotelInfo info; + Api api; + HotelInfo info; - api.GetHotelInfo(kHotelId, "en", [&info](booking::HotelInfo const & i) + api.GetHotelInfo(kHotelId, "en", [&info](HotelInfo const & i) { info = i; testing::Notify(); @@ -129,16 +131,16 @@ UNIT_CLASS_TEST(AsyncGuiThread, GetHotelInfo) UNIT_CLASS_TEST(AsyncGuiThread, GetHotelAvailability) { - booking::SetBookingUrlForTesting("http://localhost:34568/booking/min_price"); - MY_SCOPE_GUARD(cleanup, []() { booking::SetBookingUrlForTesting(""); }); + SetBookingUrlForTesting("http://localhost:34568/booking/min_price"); + MY_SCOPE_GUARD(cleanup, []() { SetBookingUrlForTesting(""); }); - booking::AvailabilityParams params; + AvailabilityParams params; params.m_hotelIds = {"77615", "10623"}; params.m_rooms = {"A,A"}; params.m_checkin = std::chrono::system_clock::now() + std::chrono::hours(24); params.m_checkout = std::chrono::system_clock::now() + std::chrono::hours(24 * 7); params.m_stars = {"4"}; - booking::Api api; + Api api; std::vector result; api.GetHotelAvailability(params, [&result](std::vector const & r) diff --git a/xcode/partners_api/partners_api.xcodeproj/project.pbxproj b/xcode/partners_api/partners_api.xcodeproj/project.pbxproj index cd908ac7f1..561ceb175c 100644 --- a/xcode/partners_api/partners_api.xcodeproj/project.pbxproj +++ b/xcode/partners_api/partners_api.xcodeproj/project.pbxproj @@ -19,6 +19,8 @@ 3488B0371E9D11860068AFD8 /* ads_engine_tests.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 346E889D1E9D088200D4CE9B /* ads_engine_tests.cpp */; }; 3488B0381E9D11890068AFD8 /* rb_tests.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 346E889E1E9D088200D4CE9B /* rb_tests.cpp */; }; 3488B0391E9D118D0068AFD8 /* facebook_tests.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3DBC1C501E4B14810016897F /* facebook_tests.cpp */; }; + 3D3731EF1F98A7AF00D2121B /* booking_http.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3D3731ED1F98A7AF00D2121B /* booking_http.cpp */; }; + 3D3731F01F98A7AF00D2121B /* booking_http.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 3D3731EE1F98A7AF00D2121B /* booking_http.hpp */; }; 3D452AEF1EE6D202009EAB9B /* google_tests.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3D452AED1EE6D202009EAB9B /* google_tests.cpp */; }; 3D452AF01EE6D202009EAB9B /* mopub_tests.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3D452AEE1EE6D202009EAB9B /* mopub_tests.cpp */; }; 3D452AF31EE6D20D009EAB9B /* google_ads.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3D452AF11EE6D20D009EAB9B /* google_ads.cpp */; }; @@ -80,6 +82,8 @@ 346E889E1E9D088200D4CE9B /* rb_tests.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = rb_tests.cpp; sourceTree = ""; }; 3475E0E11DBF581B004C7E69 /* common-debug.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = "common-debug.xcconfig"; path = "../common-debug.xcconfig"; sourceTree = ""; }; 3475E0E21DBF581B004C7E69 /* common-release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = "common-release.xcconfig"; path = "../common-release.xcconfig"; sourceTree = ""; }; + 3D3731ED1F98A7AF00D2121B /* booking_http.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = booking_http.cpp; sourceTree = ""; }; + 3D3731EE1F98A7AF00D2121B /* booking_http.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = booking_http.hpp; sourceTree = ""; }; 3D452AED1EE6D202009EAB9B /* google_tests.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = google_tests.cpp; sourceTree = ""; }; 3D452AEE1EE6D202009EAB9B /* mopub_tests.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = mopub_tests.cpp; sourceTree = ""; }; 3D452AF11EE6D20D009EAB9B /* google_ads.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = google_ads.cpp; sourceTree = ""; }; @@ -181,6 +185,8 @@ F6B5363B1DA520B20067EEA5 /* partners_api */ = { isa = PBXGroup; children = ( + 3D3731ED1F98A7AF00D2121B /* booking_http.cpp */, + 3D3731EE1F98A7AF00D2121B /* booking_http.hpp */, BB1956E41F543D7B003ECE6C /* locals_api.cpp */, BB1956E51F543D7C003ECE6C /* locals_api.hpp */, 3D47B2B01F14FA14000828D2 /* utils.hpp */, @@ -291,6 +297,7 @@ 3DFEBF9D1EFBFC1500317D5C /* taxi_provider.hpp in Headers */, 346E88991E9D087400D4CE9B /* ads_engine.hpp in Headers */, 3DFEBF9C1EFBFC1500317D5C /* taxi_engine.hpp in Headers */, + 3D3731F01F98A7AF00D2121B /* booking_http.hpp in Headers */, F6B536431DA520E40067EEA5 /* uber_api.hpp in Headers */, 3DBC1C551E4B14920016897F /* facebook_ads.hpp in Headers */, BB1956E71F543D7C003ECE6C /* locals_api.hpp in Headers */, @@ -395,6 +402,7 @@ 3DFEBF891EF82C1300317D5C /* viator_tests.cpp in Sources */, 3DFEBF851EF82BEA00317D5C /* viator_api.cpp in Sources */, F6B536421DA520E40067EEA5 /* uber_api.cpp in Sources */, + 3D3731EF1F98A7AF00D2121B /* booking_http.cpp in Sources */, 3DFEBF9B1EFBFC1500317D5C /* taxi_engine.cpp in Sources */, 346E889B1E9D087400D4CE9B /* rb_ads.cpp in Sources */, 3DBC1C541E4B14920016897F /* facebook_ads.cpp in Sources */,