BaseHTTPServer.h 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159
  1. #ifndef BELL_BASE_HTTP_SERV
  2. #define BELL_BASE_HTTP_SERV
  3. #include <cstdio>
  4. #include <string>
  5. #include <map>
  6. #include <memory>
  7. #include <functional>
  8. #include <iostream>
  9. #include <vector>
  10. #include <cstring>
  11. #ifdef _WIN32
  12. #include <winsock2.h>
  13. #else
  14. #include <sys/socket.h>
  15. #endif
  16. namespace bell {
  17. class ResponseReader {
  18. public:
  19. ResponseReader(){};
  20. virtual ~ResponseReader() = default;
  21. virtual size_t getTotalSize() = 0;
  22. virtual size_t read(char *buffer, size_t size) = 0;
  23. virtual void close() = 0;
  24. };
  25. class RequestBodyReader : public ResponseReader {
  26. public:
  27. std::vector<uint8_t> partialBuffer;
  28. int fd = 0;
  29. size_t contentLength = 0;
  30. size_t sizeRead = 0;
  31. RequestBodyReader(size_t contentLength, int fd, std::vector<uint8_t> &partialBuffer) {
  32. this->contentLength = contentLength;
  33. this->partialBuffer = partialBuffer;
  34. this->fd = fd;
  35. };
  36. size_t read(char *buffer, size_t size) {
  37. if (sizeRead < partialBuffer.size()) {
  38. size_t toRead = std::min(size, partialBuffer.size() - sizeRead);
  39. memcpy(buffer, &partialBuffer[sizeRead], toRead);
  40. sizeRead += toRead;
  41. return toRead;
  42. } else {
  43. size_t toRead = std::min(size, contentLength - sizeRead);
  44. size_t read = recv(fd, buffer, toRead, 0);
  45. sizeRead += read;
  46. return read;
  47. }
  48. }
  49. void close() {
  50. }
  51. size_t getTotalSize() { return contentLength; }
  52. };
  53. class FileResponseReader : public ResponseReader {
  54. public:
  55. FILE *file;
  56. size_t fileSize;
  57. FileResponseReader(std::string fileName) {
  58. file = fopen(fileName.c_str(), "r");
  59. fseek(file, 0, SEEK_END); // seek to end of file
  60. fileSize = ftell(file); // get current file pointer
  61. fseek(file, 0, SEEK_SET); // seek back to beginning of file
  62. };
  63. size_t read(char *buffer, size_t size) {
  64. return fread(buffer, 1, size, file);
  65. }
  66. void close() {
  67. fclose(file);
  68. }
  69. size_t getTotalSize() { return fileSize; }
  70. };
  71. enum class RequestType { GET, POST };
  72. struct HTTPRequest {
  73. std::map<std::string, std::string> urlParams;
  74. std::map<std::string, std::string> queryParams;
  75. std::unique_ptr<ResponseReader> responseReader = std::unique_ptr<RequestBodyReader>(nullptr);
  76. std::string body;
  77. std::string url;
  78. int handlerId;
  79. int connection;
  80. int contentLength;
  81. };
  82. struct HTTPResponse {
  83. int connectionFd;
  84. int status;
  85. bool useGzip = false;
  86. std::string body;
  87. std::string contentType;
  88. std::vector<std::string> extraHeaders = std::vector<std::string>();
  89. std::unique_ptr<ResponseReader> responseReader;
  90. };
  91. typedef std::function<void(std::unique_ptr<bell::HTTPRequest>)> httpHandler;
  92. struct HTTPRoute {
  93. RequestType requestType;
  94. httpHandler handler;
  95. bool readBodyToStr;
  96. };
  97. struct HTTPConnection {
  98. int fd = 0;
  99. std::vector<uint8_t> buffer;
  100. std::vector<uint8_t> partialBuffer = std::vector<uint8_t>();
  101. int contentLength = 0;
  102. std::string httpMethod;
  103. bool toBeClosed = false;
  104. bool headersRead = false;
  105. bool isEventConnection = false;
  106. bool isCaptivePortal = false;
  107. };
  108. class BaseHTTPServer {
  109. public:
  110. BaseHTTPServer() {};
  111. virtual ~BaseHTTPServer() = default;
  112. /**
  113. * Should contain server's bind port
  114. */
  115. int serverPort;
  116. /**
  117. * Called when handler is being registered on the http server
  118. *
  119. * @param requestType GET or POST
  120. * @param endpoint registering under
  121. * @param readResponseToStr if true, response will be read to string, otherwise it will return a reader object
  122. * httpHandler lambda to be called when given endpoint gets executed
  123. */
  124. virtual void registerHandler(RequestType requestType, const std::string & endpoint,
  125. httpHandler, bool readResponseToStr = true) = 0;
  126. /**
  127. * Writes given response to a fd
  128. */
  129. virtual void respond(const HTTPResponse &) = 0;
  130. };
  131. } // namespace bell
  132. #endif