Эх сурвалжийг харах

Initial commit for FRPCWebUI

xcbosa-itx 2 жил өмнө
commit
590d3d81bf

+ 1 - 0
.gitignore

@@ -0,0 +1 @@
+cmake-build-debug

+ 8 - 0
.idea/.gitignore

@@ -0,0 +1,8 @@
+# Default ignored files
+/shelf/
+/workspace.xml
+# Editor-based HTTP Client requests
+/httpRequests/
+# Datasource local storage ignored files
+/dataSources/
+/dataSources.local.xml

+ 2 - 0
.idea/FRPCWebUI.iml

@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<module classpath="CMake" type="CPP_MODULE" version="4" />

+ 4 - 0
.idea/misc.xml

@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="CMakeWorkspace" PROJECT_DIR="$PROJECT_DIR$" />
+</project>

+ 8 - 0
.idea/modules.xml

@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="ProjectModuleManager">
+    <modules>
+      <module fileurl="file://$PROJECT_DIR$/.idea/FRPCWebUI.iml" filepath="$PROJECT_DIR$/.idea/FRPCWebUI.iml" />
+    </modules>
+  </component>
+</project>

+ 6 - 0
.idea/vcs.xml

@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="VcsDirectoryMappings">
+    <mapping directory="$PROJECT_DIR$" vcs="Git" />
+  </component>
+</project>

+ 6 - 0
CMakeLists.txt

@@ -0,0 +1,6 @@
+cmake_minimum_required(VERSION 3.24)
+project(FRPCWebUI)
+
+set(CMAKE_CXX_STANDARD 17)
+
+add_executable(FRPCWebUI main.cpp httpserver/HTTPServer.cpp httpserver/HTTPServer.h webui.h httpserver/ClientConnection.cpp httpserver/ClientConnection.h utils/ResponseData.cpp utils/ResponseData.h utils/FileResponseData.cpp utils/FileResponseData.h utils/FileReader.cpp webuiconf.h)

+ 11 - 0
data/html/error.html

@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+    <meta charset="UTF-8">
+    <title>Error {{ERR_CODE}}</title>
+</head>
+<body>
+    <p style="text-align: center">{{ERR_MSG}} <br>({{ERR_CODE}})<br/></p>
+    <p style="text-align: center">FRPCWebUI / XCHttpServer 1.0</p>
+</body>
+</html>

+ 31 - 0
httpserver/ClientConnection.cpp

@@ -0,0 +1,31 @@
+//
+// Created by xcbosa on 2023/1/28.
+//
+
+#include "ClientConnection.h"
+#include "../webui.h"
+
+namespace xc {
+    namespace httpserver {
+
+        ClientConnection::ClientConnection(int sockFd, struct sockaddr_in address) {
+            this->sockFd = sockFd;
+            this->address = address;
+        }
+
+        void ClientConnection::workAndDestroy() {
+            thread(workLoop);
+        }
+
+        void ClientConnection::workLoop() {
+            ::FILE *clRead = fdopen(this->sockFd, "r");
+            ::FILE *clWrite = fdopen(dup(this->sockFd), "w");
+            char smallBuf[smallBuffSize];
+            ::fgets(smallBuf, smallBuffSize, clRead);
+            if (::strstr(smallBuf, "HTTP/") == NULL) {
+                
+            }
+        }
+
+    } // xc
+} // httpserver

+ 29 - 0
httpserver/ClientConnection.h

@@ -0,0 +1,29 @@
+//
+// Created by xcbosa on 2023/1/28.
+//
+
+#ifndef FRPCWEBUI_CLIENTCONNECTION_H
+#define FRPCWEBUI_CLIENTCONNECTION_H
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <unistd.h>
+
+namespace xc {
+    namespace httpserver {
+
+        class ClientConnection {
+        public:
+            ClientConnection(int sockFd, struct sockaddr_in address);
+            void workAndDestroy();
+        private:
+            int sockFd;
+            struct sockaddr_in address;
+            void workLoop();
+        };
+
+    } // xc
+} // httpserver
+
+#endif //FRPCWEBUI_CLIENTCONNECTION_H

+ 46 - 0
httpserver/HTTPServer.cpp

@@ -0,0 +1,46 @@
+//
+// Created by xcbosa on 2023/1/28.
+//
+
+#include "HTTPServer.h"
+#include "ClientConnection.h"
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <unistd.h>
+
+namespace xc {
+    namespace httpserver {
+
+        HTTPServer::HTTPServer(ushort bindPort) {
+            this->bindPort = bindPort;
+        }
+
+        void HTTPServer::serverLoop() {
+            this->serverSocketFd = socket(PF_INET, SOCK_STREAM, 0);
+            assertx(this->serverSocketFd != -1, "Socket init failed.");
+            struct sockaddr_in serverAddress;
+            serverAddress.sin_family = AF_INET;
+            serverAddress.sin_port = htons(this->bindPort);
+            serverAddress.sin_addr.s_addr = INADDR_ANY;
+            bzero(&(serverAddress.sin_zero), 8);
+            if (::bind(this->serverSocketFd, (struct sockaddr *)&serverAddress, sizeof(struct sockaddr)) == -1) {
+                cerr << "Unable to bind port" << this->bindPort << endl;
+                assertx(0, "");
+            }
+            if (listen(this->serverSocketFd, 5) == -1) {
+                cerr << "Unable to bind port" << this->bindPort << endl;
+                assertx(0, "");
+            }
+            cout << "Bind to" << this->bindPort << endl;
+            while (true) {
+                struct sockaddr_in clientAddress;
+                socklen_t clientAddressSize = sizeof(clientAddress);
+                int clientSocketFd = accept(this->serverSocketFd, (struct sockaddr*)&clientAddress, &clientAddressSize);
+                auto client = new ClientConnection(clientSocketFd, clientAddress);
+                client->workAndDestroy();
+            }
+        }
+
+    } // xc
+} // httpserver

+ 25 - 0
httpserver/HTTPServer.h

@@ -0,0 +1,25 @@
+//
+// Created by xcbosa on 2023/1/28.
+//
+
+#ifndef FRPCWEBUI_HTTPSERVER_H
+#define FRPCWEBUI_HTTPSERVER_H
+
+#include "../webui.h"
+
+namespace xc {
+    namespace httpserver {
+
+        class HTTPServer {
+        public:
+            HTTPServer(ushort bindPort);
+            void serverLoop();
+        private:
+            int serverSocketFd;
+            ushort bindPort;
+        };
+
+    } // xc
+} // httpserver
+
+#endif //FRPCWEBUI_HTTPSERVER_H

+ 6 - 0
main.cpp

@@ -0,0 +1,6 @@
+#include <iostream>
+
+int main() {
+    std::cout << "Hello, World!" << std::endl;
+    return 0;
+}

+ 18 - 0
utils/FileReader.cpp

@@ -0,0 +1,18 @@
+//
+// Created by xcbosa on 2023/1/28.
+//
+
+#include "../webui.h"
+#include <sstream>
+#include <fstream>
+
+namespace xc::utils {
+    string contentsOfTextFile(string filePath) {
+        ifstream fin(filePath);
+        stringstream buffer;
+        buffer << fin.rdbuf();
+        string str(buffer.str());
+        fin.close();
+        return str;
+    }
+}

+ 49 - 0
utils/FileResponseData.cpp

@@ -0,0 +1,49 @@
+//
+// Created by xcbosa on 2023/1/28.
+//
+
+#include "FileResponseData.h"
+
+namespace xc {
+    namespace utils {
+        Replacement::Replacement(string replace, string with) {
+            this->replace = replace;
+            this->with = with;
+        }
+
+        FileResponseData::FileResponseData(int statusCode, string filePath, string contentType):
+                ResponseData(statusCode, "", contentType),
+                filePath() {
+            this->setFilePath(filePath);
+        }
+
+        FileResponseData::FileResponseData(int statusCode, string filePath, string contentType, vector<Replacement> replacements):
+                ResponseData(statusCode, "", contentType) {
+            this->setFilePath(filePath, replacements);
+        }
+
+        string FileResponseData::getFilePath() {
+            return this->filePath;
+        }
+
+        void FileResponseData::setFilePath(string filePath) {
+            this->filePath = filePath;
+            this->setBody(contentsOfTextFile(filePath));
+        }
+
+        void FileResponseData::setFilePath(string filePath, vector<Replacement> replacements) {
+            this->filePath = filePath;
+            string str = contentsOfTextFile(filePath);
+            for (auto replacement : replacements) {
+                string fullReplaceText = "{{" + replacement.replace + "}}";
+                string::size_type pos = 0;
+                while ((pos = str.find(fullReplaceText)) != string::npos) {
+                    str.replace(pos, fullReplaceText.length(), replacement.with);
+                }
+            }
+            this->setBody(str);
+        }
+
+
+    } // xc
+} // utils

+ 34 - 0
utils/FileResponseData.h

@@ -0,0 +1,34 @@
+//
+// Created by xcbosa on 2023/1/28.
+//
+
+#ifndef FRPCWEBUI_FILERESPONSEDATA_H
+#define FRPCWEBUI_FILERESPONSEDATA_H
+
+#include "ResponseData.h"
+
+namespace xc {
+    namespace utils {
+
+        struct Replacement {
+        public:
+            string replace;
+            string with;
+            Replacement(string replace, string with);
+        };
+
+        class FileResponseData: public ResponseData {
+        public:
+            FileResponseData(int statusCode, string filePath, string contentType);
+            FileResponseData(int statusCode, string filePath, string contentType, vector<Replacement> replacements);
+            string getFilePath();
+            void setFilePath(string filePath);
+            void setFilePath(string filePath, vector<Replacement> replacements);
+        private:
+            string filePath;
+        };
+
+    } // xc
+} // utils
+
+#endif //FRPCWEBUI_FILERESPONSEDATA_H

+ 64 - 0
utils/ResponseData.cpp

@@ -0,0 +1,64 @@
+//
+// Created by xcbosa on 2023/1/28.
+//
+
+#include "ResponseData.h"
+
+namespace xc {
+    namespace utils {
+        ResponseData::ResponseData(int statusCode, string body): headers() {
+            this->statusCode = statusCode;
+            this->body = body;
+            this->headers["Server"] = "XCHttpServer";
+            this->headers["Transfer-Encoding"] = "chunked";
+            this->headers["Content-Type"] = "text/html";
+        }
+
+        ResponseData::ResponseData(int statusCode, string body, string contentType):
+                ResponseData(statusCode, body) {
+            this->headers["Content-Type"] = contentType;
+        }
+
+        void ResponseData::setHeader(string headerName, string value) {
+            this->headers[headerName] = value;
+        }
+
+        void ResponseData::removeHeader(string headerName) {
+            this->headers[headerName] = nullptr;
+        }
+
+        string ResponseData::getHeader(string headerName) {
+            return this->headers[headerName];
+        }
+
+        void ResponseData::setStatusCode(int statusCode) {
+            this->statusCode = statusCode;
+        }
+
+        void ResponseData::setContentType(string mimeType) {
+            this->setHeader("Content-Type", mimeType);
+        }
+
+        int ResponseData::getStatusCode() {
+            return this->statusCode;
+        }
+
+        void ResponseData::setBody(string body) {
+            this->body = body;
+        }
+
+        string ResponseData::getBody() {
+            return this->body;
+        }
+
+        void ResponseData::writeTo(::FILE *fp) {
+            ::fprintf(fp, "HTTP/1.0 %d FRPCWebUI\r\n", this->statusCode);
+            for (auto item : this->headers) {
+                ::fprintf(fp, "%s: %s\r\n", item.first.c_str(), item.second.c_str());
+            }
+            ::fputs("\r\n", fp);
+            ::fputs(this->body.c_str(), fp);
+            ::fflush(fp);
+        }
+    } // xc
+} // utils

+ 35 - 0
utils/ResponseData.h

@@ -0,0 +1,35 @@
+//
+// Created by xcbosa on 2023/1/28.
+//
+
+#ifndef FRPCWEBUI_RESPONSEDATA_H
+#define FRPCWEBUI_RESPONSEDATA_H
+
+#include "../webui.h"
+
+namespace xc {
+    namespace utils {
+
+        class ResponseData {
+        public:
+            ResponseData(int statusCode, string body);
+            ResponseData(int statusCode, string body, string contentType);
+            void setHeader(string headerName, string value);
+            void removeHeader(string headerName);
+            string getHeader(string headerName);
+            void setContentType(string mimeType);
+            void setStatusCode(int statusCode);
+            int getStatusCode();
+            void setBody(string body);
+            string getBody();
+            void writeTo(::FILE *fp);
+        private:
+            int statusCode;
+            map<string, string> headers;
+            string body;
+        };
+
+    } // xc
+} // utils
+
+#endif //FRPCWEBUI_RESPONSEDATA_H

+ 30 - 0
webui.h

@@ -0,0 +1,30 @@
+//
+// Created by xcbosa on 2023/1/28.
+//
+
+#ifndef FRPCWEBUI_WEBUI_H
+#define FRPCWEBUI_WEBUI_H
+
+#include <vector>
+#include <map>
+#include <string>
+#include <iostream>
+#include <thread>
+#include <mutex>
+#include "webuiconf.h"
+
+using namespace std;
+
+#define assertx(expr, message) \
+    if (!(expr)) { std::cerr << message << std::endl; exit(-1); }
+
+namespace xc {
+    constexpr int smallBuffSize = 32;
+
+    namespace utils {
+        string contentsOfTextFile(string filePath);
+    }
+}
+
+
+#endif //FRPCWEBUI_WEBUI_H

+ 32 - 0
webuiconf.h

@@ -0,0 +1,32 @@
+//
+// Created by xcbosa on 2023/1/28.
+//
+
+#ifndef FRPCWEBUI_WEBUICONF_H
+#define FRPCWEBUI_WEBUICONF_H
+
+#include <vector>
+#include "utils/FileResponseData.h"
+
+using namespace std;
+
+namespace xc::conf {
+    using namespace utils;
+
+    const FileResponseData errorPage400(400, "html/error.html", "text/html", {
+        Replacement("{{ERR_MSG}}", "请求格式错误,无法解析请求"),
+        Replacement("{{ERR_CODE}}", "400")
+    });
+
+    const FileResponseData errorPage404(404, "html/error.html", "text/html", {
+        Replacement("{{ERR_MSG}}", "不存在指定的资源"),
+        Replacement("{{ERR_CODE}}", "404")
+    });
+
+    const FileResponseData errorPage500(500, "html/error.html", "text/html", {
+        Replacement("{{ERR_MSG}}", "服务器内部错误,可能是服务器访问量过大,请稍后重试"),
+        Replacement("{{ERR_CODE}}", "500")
+    });
+}
+
+#endif //FRPCWEBUI_WEBUICONF_H