123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159 |
- #ifndef BELL_BASE_HTTP_SERV
- #define BELL_BASE_HTTP_SERV
- #include <cstdio>
- #include <string>
- #include <map>
- #include <memory>
- #include <functional>
- #include <iostream>
- #include <vector>
- #include <cstring>
- #ifdef _WIN32
- #include <winsock2.h>
- #else
- #include <sys/socket.h>
- #endif
- namespace bell {
- class ResponseReader {
- public:
- ResponseReader(){};
- virtual ~ResponseReader() = default;
- virtual size_t getTotalSize() = 0;
- virtual size_t read(char *buffer, size_t size) = 0;
- virtual void close() = 0;
- };
- class RequestBodyReader : public ResponseReader {
- public:
- std::vector<uint8_t> partialBuffer;
- int fd = 0;
- size_t contentLength = 0;
- size_t sizeRead = 0;
- RequestBodyReader(size_t contentLength, int fd, std::vector<uint8_t> &partialBuffer) {
- this->contentLength = contentLength;
- this->partialBuffer = partialBuffer;
- this->fd = fd;
- };
- size_t read(char *buffer, size_t size) {
- if (sizeRead < partialBuffer.size()) {
- size_t toRead = std::min(size, partialBuffer.size() - sizeRead);
- memcpy(buffer, &partialBuffer[sizeRead], toRead);
- sizeRead += toRead;
- return toRead;
- } else {
- size_t toRead = std::min(size, contentLength - sizeRead);
- size_t read = recv(fd, buffer, toRead, 0);
- sizeRead += read;
- return read;
- }
- }
- void close() {
- }
- size_t getTotalSize() { return contentLength; }
- };
- class FileResponseReader : public ResponseReader {
- public:
- FILE *file;
- size_t fileSize;
- FileResponseReader(std::string fileName) {
- file = fopen(fileName.c_str(), "r");
- fseek(file, 0, SEEK_END); // seek to end of file
- fileSize = ftell(file); // get current file pointer
- fseek(file, 0, SEEK_SET); // seek back to beginning of file
- };
- size_t read(char *buffer, size_t size) {
- return fread(buffer, 1, size, file);
- }
- void close() {
- fclose(file);
- }
- size_t getTotalSize() { return fileSize; }
- };
- enum class RequestType { GET, POST };
- struct HTTPRequest {
- std::map<std::string, std::string> urlParams;
- std::map<std::string, std::string> queryParams;
- std::unique_ptr<ResponseReader> responseReader = std::unique_ptr<RequestBodyReader>(nullptr);
- std::string body;
- std::string url;
- int handlerId;
- int connection;
- int contentLength;
- };
- struct HTTPResponse {
- int connectionFd;
- int status;
- bool useGzip = false;
- std::string body;
- std::string contentType;
- std::vector<std::string> extraHeaders = std::vector<std::string>();
- std::unique_ptr<ResponseReader> responseReader;
- };
- typedef std::function<void(std::unique_ptr<bell::HTTPRequest>)> httpHandler;
- struct HTTPRoute {
- RequestType requestType;
- httpHandler handler;
- bool readBodyToStr;
- };
- struct HTTPConnection {
- int fd = 0;
- std::vector<uint8_t> buffer;
- std::vector<uint8_t> partialBuffer = std::vector<uint8_t>();
- int contentLength = 0;
- std::string httpMethod;
- bool toBeClosed = false;
- bool headersRead = false;
- bool isEventConnection = false;
- bool isCaptivePortal = false;
- };
- class BaseHTTPServer {
- public:
- BaseHTTPServer() {};
- virtual ~BaseHTTPServer() = default;
- /**
- * Should contain server's bind port
- */
- int serverPort;
- /**
- * Called when handler is being registered on the http server
- *
- * @param requestType GET or POST
- * @param endpoint registering under
- * @param readResponseToStr if true, response will be read to string, otherwise it will return a reader object
- * httpHandler lambda to be called when given endpoint gets executed
- */
- virtual void registerHandler(RequestType requestType, const std::string & endpoint,
- httpHandler, bool readResponseToStr = true) = 0;
- /**
- * Writes given response to a fd
- */
- virtual void respond(const HTTPResponse &) = 0;
- };
- } // namespace bell
- #endif
|