Forráskód Böngészése

update http file server

xuqiang 4 hónapja
szülő
commit
894138c00f
2 módosított fájl, 145 hozzáadás és 60 törlés
  1. 3 0
      include/httpserver.h
  2. 142 60
      src/httpserver.cpp

+ 3 - 0
include/httpserver.h

@@ -28,6 +28,9 @@ private:
 
 signals:
     void monitorConfigureUpdate(const QString &filename);
+    void netparseConfigureUpdate(const QString &filename);
+    void formulaConfigureUpdate(const QString &filename);
+    void upgradePlugin();
     void reloadCanvas();
 
 private slots:

+ 142 - 60
src/httpserver.cpp

@@ -2,10 +2,17 @@
 #include "logger.h"
 #include <fstream>
 #include <QJsonObject>
+#include <QJsonArray>
 #include <QJsonDocument>
 #include <QDir>
+#include <QCryptographicHash>
+#include <QMessageAuthenticationCode>
 #include "appcontext.h"
 
+#define FILE_SERVER_VERSION     "1.0.0"
+#define FILE_SERVER_PASSWD      "HGwP42vt65AgQyJa"
+#define FILE_SERVER_SECRIT_KEY  "7R1mo2T7XJTrSgSJHBzRZYSydWybDD46"
+
 HttpServer::HttpServer(QObject *parent)
     : QObject{parent}
 {
@@ -156,81 +163,156 @@ void HttpServer::run_hhttp_sever()
     });
 
     // 画面配置文件更新接口
-    m_server.Post("/update/monitor", [&](const httplib::Request &req, httplib::Response &res, const httplib::ContentReader &content_reader) {
+    m_server.Post("/", [&](const httplib::Request &req, httplib::Response &res, const httplib::ContentReader &content_reader) {
+
+        std::cout << "Headers:\n";
+        for (const auto &header : req.headers) {
+            std::cout << header.first << ": " << header.second << "\n";
+        }
+
         QJsonDocument doc;
-        if (req.is_multipart_form_data()) {
-            // NOTE: `content_reader` is blocking until every form data field is read
-            // This approach allows streaming processing of large files
-            std::vector<httplib::FormData> items;
-            content_reader(
-                [&](const httplib::FormData &item) {
-                items.push_back(item);
-                return true;
-                },
-                [&](const char *data, size_t data_length) {
-                items.back().content.append(data, data_length);
-                return true;
-            });
-
-            // Process the received items
-            for (const auto& item : items) {
-                if (item.filename.empty()) {
-                    // Text field
-                    // std::cout << "Field: " << item.name << " = " << item.content << std::endl;
 
-                    QJsonObject obj = {
-                        {"message", QString("File error")}
-                    };
-                    doc.setObject(obj);
-                    
-                    res.status = httplib::StatusCode::BadRequest_400;
-                    res.set_content(doc.toJson(QJsonDocument::Compact).data(), "application/json");
-                } else {
-                    // File
-                    QString currentPath = QDir::currentPath();
-                    QString savePath = QString("%1/%2").arg(currentPath, "update");
+        // 检查请求头中是否存在 Access-Token
+        auto it = req.headers.find("Access-Token");
+        if (it != req.headers.end() && !it->second.empty()) {
+            QString token = QString::fromStdString(it->second);
+            auto x = token.split(".");
+            QString h = x.first();
+            QString s = x.last();
 
-                    QDir dir(savePath);
-                    if(!dir.exists()) {
-                        dir.mkpath(savePath);
-                    }
+            auto header = QJsonDocument::fromJson(QByteArray::fromBase64(h.toUtf8())).array();
+            auto timestamp = header[0].toString();
+            auto type = header[2].toString();
 
-                    QString filename = QString("%1/%2").arg(savePath, "monitor.xml");
-                    std::ofstream ofs(filename.toStdString(), std::ios::binary);
-                    if (!ofs) {
-                        LOG_ERROR("open file failed: {}", filename.toStdString());
-                        continue;
-                    }
+            QJsonArray signature;
+            signature.push_back(timestamp);
+            signature.push_back(FILE_SERVER_VERSION);
+            signature.push_back(type);
+            signature.push_back(FILE_SERVER_PASSWD);
+            doc.setArray(signature);
+
+            QByteArray byteArray;
+            byteArray.push_back(h.toUtf8());
+            byteArray.push_back(".");
+            byteArray.push_back(QMessageAuthenticationCode::hash(QString(doc.toJson(QJsonDocument::Compact)).toUtf8(), FILE_SERVER_SECRIT_KEY, QCryptographicHash::Sha256).toBase64());
+            QString sign = QString(byteArray);
+            LOG_DEBUG("Access-Token: {} {}", token.toStdString(), sign.toStdString());
 
-                    ofs.write(item.content.data(), item.content.size());
-                    ofs.close();
-                    LOG_INFO("monitor configure file successfully update");
-                    emit monitorConfigureUpdate(filename);
+            if(sign == token) {
+                if (req.is_multipart_form_data()) {
+                    // NOTE: `content_reader` is blocking until every form data field is read
+                    // This approach allows streaming processing of large files
+                    std::vector<httplib::FormData> items;
+                    content_reader(
+                        [&](const httplib::FormData &item) {
+                        items.push_back(item);
+                        return true;
+                        },
+                        [&](const char *data, size_t data_length) {
+                        items.back().content.append(data, data_length);
+                        return true;
+                    });
+
+                    // Process the received items
+                    for (const auto& item : items) {
+                        if (item.filename.empty()) {
+                            // Text field
+                            QJsonObject obj = {
+                                {"message", QString("File error")}
+                            };
+                            doc.setObject(obj);
+                            
+                            res.status = httplib::StatusCode::BadRequest_400;
+                            res.set_content(doc.toJson(QJsonDocument::Compact).data(), "application/json");
+                        } else {
+                            // File
+                            QString currentPath = QDir::currentPath();
+                            QString savePath;
+                            QString filename;
+
+                            if(type == "monitor") {
+                                savePath = QString("%1/%2").arg(currentPath, "storage/upload/monitor");
+                                filename = QString("%1/%2").arg(savePath, "monitor.xml");
+                            } else if(type == "netparse") {
+                                savePath = QString("%1/%2").arg(currentPath, "storage/upload/netparse");
+                            } else if(type == "formula") {
+                                savePath = QString("%1/%2").arg(currentPath, "storage/upload/formula");
+                            } else if(type == "pluginadd" || type == "pluginupgrade") {
+                                savePath = QString("%1/%2").arg(currentPath, "storage/upload/plugins");
+                            } else {
+                                res.status = httplib::StatusCode::BadRequest_400;
+                                res.set_content(R"({"message": "Invalid file type"})", "application/json");
+                                return;
+                            }
+                            filename = QString("%1/%2").arg(savePath, QString::fromStdString(item.filename));
+
+                            QDir dir(savePath);
+                            if(!dir.exists()) {
+                                dir.mkpath(savePath);
+                            }
+
+                            std::ofstream ofs(filename.toStdString(), std::ios::binary);
+                            if (!ofs) {
+                                LOG_ERROR("open file failed: {}", filename.toStdString());
+                                continue;
+                            }
+
+                            ofs.write(item.content.data(), item.content.size());
+                            ofs.close();
+                            
+                            if(type == "monitor") {
+                                LOG_INFO("monitor configure file successfully update");
+                                emit monitorConfigureUpdate(filename);
+                            } else if(type == "formula") {
+                                LOG_INFO("formula configure file successfully update");
+                                emit formulaConfigureUpdate(filename);
+                            } else if(type == "netparse") {
+                                LOG_INFO("netparse configure file successfully update");
+                                emit netparseConfigureUpdate(filename);
+                            } else if(type == "pluginadd") {
+                                LOG_INFO("add plugin: {}", item.filename);
+                            } else if(type == "pluginupgrade") {
+                                auto pluginName = header[3].toString();
+                                LOG_INFO("upgrade plugin: {}", pluginName.toStdString());
+                            }
+
+                            QJsonObject obj = {
+                                {"message", QString("'File successfully upload")}
+                            };
+                            doc.setObject(obj);
+                            
+                            res.status = httplib::StatusCode::OK_200;
+                            res.set_content(doc.toJson(QJsonDocument::Compact).data(), "application/json");
+                        }
+                    }
+                } else {
+                    // std::string body;
+                    // content_reader([&](const char *data, size_t data_length) {
+                    //     body.append(data, data_length);
+                    //     return true;
+                    // });
 
                     QJsonObject obj = {
-                        {"message", QString("'File successfully update")}
+                        {"message", QString("File error")}
                     };
                     doc.setObject(obj);
                     
-                    res.status = httplib::StatusCode::OK_200;
+                    res.status = httplib::StatusCode::BadRequest_400;
                     res.set_content(doc.toJson(QJsonDocument::Compact).data(), "application/json");
                 }
+            } else {
+                res.status = httplib::StatusCode::BadRequest_400; // error token
+                res.set_content(R"({"message": "Invalid access token"})", "application/json");
             }
         } else {
-            // std::string body;
-            // content_reader([&](const char *data, size_t data_length) {
-            //     body.append(data, data_length);
-            //     return true;
-            // });
-
-            QJsonObject obj = {
-                {"message", QString("File error")}
-            };
-            doc.setObject(obj);
-            
-            res.status = httplib::StatusCode::BadRequest_400;
-            res.set_content(doc.toJson(QJsonDocument::Compact).data(), "application/json");
+            LOG_DEBUG("No Access-Token found");
+            res.status = httplib::StatusCode::Unauthorized_401; // 未授权
+            res.set_content(R"({"message": "Access token missing"})", "application/json");
         }
+
+        // return;
+
+
     });
 
     m_server.listen(m_addr, m_port);