winget-cli

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

ProxyServer.cpp (2759B)


      1 // Copyright (c) Microsoft Corporation.
      2 // Licensed under the MIT License.
      3 
      4 #include "ProxyServer.h"
      5 
      6 #include "../util/TestHelper.h"
      7 #include "ErrorHandling.h"
      8 #include "ReportingHandler.h"
      9 #include "ServerCommon.h"
     10 #include "UrlBuilder.h"
     11 
     12 using namespace SFS;
     13 using namespace SFS::details;
     14 using namespace SFS::test;
     15 using namespace SFS::test::details;
     16 
     17 namespace SFS::test::details
     18 {
     19 class ProxyServerImpl : public BaseServerImpl
     20 {
     21   private:
     22     void ConfigureRequestHandlers() override;
     23     std::string GetLogIdentifier() override;
     24 };
     25 } // namespace SFS::test::details
     26 
     27 ProxyServer::ProxyServer()
     28 {
     29     m_impl = std::make_unique<ProxyServerImpl>();
     30     m_impl->Start();
     31 }
     32 
     33 ProxyServer::~ProxyServer()
     34 {
     35     const auto ret = Stop();
     36     if (!ret)
     37     {
     38         TEST_UNSCOPED_INFO("Failed to stop: " + std::string(ToString(ret.GetCode())));
     39     }
     40 }
     41 
     42 Result ProxyServer::Stop()
     43 {
     44     return m_impl->Stop();
     45 }
     46 
     47 std::string ProxyServer::GetBaseUrl() const
     48 {
     49     return m_impl->GetUrl();
     50 }
     51 
     52 void ProxyServerImpl::ConfigureRequestHandlers()
     53 {
     54     auto HandleRequest = [&](const httplib::Request& req, httplib::Response& res) {
     55         // As a proxy, we'll parse the URL and Path/Query so we can reuse them in httplib::Client
     56         ReportingHandler handler;
     57         UrlBuilder urlBuilder(req.target.c_str(), handler);
     58         const std::string path = urlBuilder.GetPath();
     59         const std::string query = urlBuilder.GetQuery();
     60         urlBuilder.ResetPath().ResetQuery();
     61 
     62         // URL may come back from UrlBuilder with a final /, which doesn't work with httplib::Client, so we remove it
     63         auto url = urlBuilder.GetUrl();
     64         if (url.at(url.size() - 1) == '/')
     65         {
     66             url.pop_back();
     67         }
     68         const std::string pathAndQuery = path + (query.empty() ? "" : ("?" + query));
     69         httplib::Client cli(url);
     70         httplib::Result result;
     71         if (req.method == "GET")
     72         {
     73             result = cli.Get(pathAndQuery, req.headers);
     74         }
     75         else if (req.method == "POST")
     76         {
     77             const auto length = std::stoi(req.get_header_value("Content-Length"));
     78             result =
     79                 cli.Post(pathAndQuery, req.headers, req.body.c_str(), length, req.get_header_value("Content-Type"));
     80         }
     81 
     82         if (!result)
     83         {
     84             BUFFER_LOG("Client error: " + to_string(result.error()));
     85             throw StatusCodeException(httplib::StatusCode::InternalServerError_500);
     86         }
     87         res = result.value();
     88     };
     89 
     90     m_server.Get(".*", HandleRequest);
     91     m_server.Post(".*", HandleRequest);
     92 }
     93 
     94 std::string ProxyServerImpl::GetLogIdentifier()
     95 {
     96     return "ProxyServer";
     97 }