http_ex.cpp 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120
  1. #include "http_ex.h"
  2. #include <util/generic/buffer.h>
  3. #include <util/generic/cast.h>
  4. #include <util/stream/null.h>
  5. bool THttpClientRequestExtension::Parse(char* req, TBaseServerRequestData& rd) {
  6. rd.SetSocket(Socket());
  7. if (!rd.Parse(req)) {
  8. Output() << "HTTP/1.1 403 Forbidden\r\n"
  9. "Content-Type: text/plain\r\n"
  10. "Content-Length: 39\r\n"
  11. "\r\n"
  12. "The server cannot be used as a proxy.\r\n";
  13. return false;
  14. }
  15. return true;
  16. }
  17. bool THttpClientRequestExtension::ProcessHeaders(TBaseServerRequestData& rd, TBlob& postData) {
  18. for (const auto& header : ParsedHeaders) {
  19. rd.AddHeader(header.first, header.second);
  20. }
  21. char* s = RequestString.begin();
  22. enum EMethod {
  23. NotImplemented,
  24. Get,
  25. Post,
  26. Put,
  27. Patch,
  28. Delete,
  29. Options,
  30. };
  31. enum EMethod foundMethod;
  32. char* urlStart;
  33. if (strnicmp(s, "GET ", 4) == 0) {
  34. foundMethod = Get;
  35. urlStart = s + 4;
  36. } else if (strnicmp(s, "POST ", 5) == 0) {
  37. foundMethod = Post;
  38. urlStart = s + 5;
  39. } else if (strnicmp(s, "PUT ", 4) == 0) {
  40. foundMethod = Put;
  41. urlStart = s + 4;
  42. } else if (strnicmp(s, "PATCH ", 6) == 0) {
  43. foundMethod = Patch;
  44. urlStart = s + 6;
  45. } else if (strnicmp(s, "DELETE ", 7) == 0) {
  46. foundMethod = Delete;
  47. urlStart = s + 7;
  48. } else if (strnicmp(s, "OPTIONS ", 8) == 0) {
  49. foundMethod = Options;
  50. urlStart = s + 8;
  51. } else {
  52. foundMethod = NotImplemented;
  53. }
  54. switch (foundMethod) {
  55. case Get:
  56. case Delete:
  57. if (!Parse(urlStart, rd)) {
  58. return false;
  59. }
  60. break;
  61. case Post:
  62. case Put:
  63. case Patch:
  64. try {
  65. ui64 contentLength = 0;
  66. if (Input().HasExpect100Continue()) {
  67. Output().SendContinue();
  68. }
  69. if (!Input().ContentEncoded() && Input().GetContentLength(contentLength)) {
  70. if (contentLength > HttpServ()->Options().MaxInputContentLength) {
  71. Output() << "HTTP/1.1 413 Payload Too Large\r\nContent-Length:0\r\n\r\n";
  72. Output().Finish();
  73. return false;
  74. }
  75. TBuffer buf(SafeIntegerCast<size_t>(contentLength));
  76. buf.Resize(Input().Load(buf.Data(), (size_t)contentLength));
  77. postData = TBlob::FromBuffer(buf);
  78. } else {
  79. postData = TBlob::FromStream(Input());
  80. }
  81. } catch (...) {
  82. Output() << "HTTP/1.1 400 Bad request\r\n\r\n";
  83. return false;
  84. }
  85. if (!Parse(urlStart, rd)) {
  86. return false;
  87. }
  88. break;
  89. case Options:
  90. if (!OptionsAllowed()) {
  91. Output() << "HTTP/1.1 405 Method Not Allowed\r\n\r\n";
  92. return false;
  93. } else if (!Parse(urlStart, rd)) {
  94. return false;
  95. }
  96. break;
  97. case NotImplemented:
  98. Output() << "HTTP/1.1 501 Not Implemented\r\n\r\n";
  99. return false;
  100. }
  101. return true;
  102. }