test_http_server.cpp 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151
  1. #include "test_http_server.h"
  2. #include <library/cpp/http/misc/httpcodes.h>
  3. #include <library/cpp/http/server/http_ex.h>
  4. #include <util/generic/yexception.h>
  5. namespace NYql {
  6. class TTestHttpServer::TImpl : public THttpServer::ICallBack {
  7. class TRequestProcessor : public THttpClientRequestEx {
  8. public:
  9. explicit TRequestProcessor(TImpl* parent)
  10. : Parent_(parent)
  11. {
  12. Y_UNUSED(Parent_);
  13. }
  14. bool Reply(void* /*tsr*/) override {
  15. if (!ProcessHeaders()) {
  16. return true;
  17. }
  18. if (!RequestString.StartsWith("GET ")) {
  19. return true;
  20. }
  21. TRequest r;
  22. for (auto& p : ParsedHeaders) {
  23. if (p.first == "Authorization" && p.second.StartsWith("OAuth ")) {
  24. r.OAuthToken = p.second.substr(strlen("OAuth "));
  25. continue;
  26. }
  27. if (p.first == "If-None-Match") {
  28. r.IfNoneMatch = p.second;
  29. continue;
  30. }
  31. if (p.first == "If-Modified-Since") {
  32. r.IfModifiedSince = p.second;
  33. continue;
  34. }
  35. }
  36. auto reply = Parent_->ProcessNextRequest(r);
  37. switch (reply.Code) {
  38. case HTTP_OK:
  39. Output() << "HTTP/1.1 200 Ok\r\n";
  40. break;
  41. case HTTP_NOT_MODIFIED:
  42. Output() << "HTTP/1.1 304 Not modified\r\n";
  43. break;
  44. case HTTP_FORBIDDEN:
  45. Output() << "HTTP/1.1 403 Forbidden\r\n";
  46. break;
  47. default:
  48. return true;
  49. }
  50. if (reply.ETag) {
  51. Output() << "ETag: " + reply.ETag + "\r\n";
  52. }
  53. if (reply.LastModified) {
  54. Output() << "Last-Modified: " + reply.LastModified + "\r\n";
  55. }
  56. if (reply.Content || reply.ContentLength) {
  57. const int length = reply.ContentLength.GetOrElse(reply.Content.length());
  58. Output() << "Content-Length: " << length << "\r\n";
  59. }
  60. Output() << "\r\n";
  61. if (reply.Content) {
  62. Output() << reply.Content;
  63. }
  64. Output().Finish();
  65. return true;
  66. }
  67. private:
  68. TImpl* Parent_ = nullptr;
  69. };
  70. public:
  71. explicit TImpl(int port)
  72. : HttpServer_(this, THttpServer::TOptions(port))
  73. , Port_(port)
  74. {
  75. }
  76. TClientRequest* CreateClient() override {
  77. return new TRequestProcessor(this);
  78. }
  79. void Start() {
  80. Y_ENSURE(HttpServer_.Start());
  81. }
  82. void Stop() {
  83. HttpServer_.Stop();
  84. }
  85. TString GetUrl() const {
  86. return "http://localhost:" + ToString(Port_);
  87. }
  88. void SetRequestHandler(TRequestHandler handler) {
  89. RequestHandler_ = std::move(handler);
  90. }
  91. private:
  92. TReply ProcessNextRequest(const TRequest& request) {
  93. return RequestHandler_(request);
  94. }
  95. private:
  96. THttpServer HttpServer_;
  97. const int Port_;
  98. TRequestHandler RequestHandler_;
  99. };
  100. TTestHttpServer::TTestHttpServer(int port)
  101. : Impl_(new TImpl(port)) {
  102. }
  103. TTestHttpServer::~TTestHttpServer() {
  104. Impl_->Stop();
  105. }
  106. void TTestHttpServer::Start() {
  107. Impl_->Start();
  108. }
  109. TString TTestHttpServer::GetUrl() const {
  110. return Impl_->GetUrl();
  111. }
  112. void TTestHttpServer::SetRequestHandler(TRequestHandler handler) {
  113. return Impl_->SetRequestHandler(std::move(handler));
  114. }
  115. }