Browse Source

Add router.Static()

ithewei 3 năm trước cách đây
mục cha
commit
0a2e0fa8b9

+ 1 - 0
examples/http_server_test.cpp

@@ -32,6 +32,7 @@ int main(int argc, char** argv) {
     if (port == 0) port = 8080;
 
     HttpService router;
+    router.Static("/", "./html");
     router.GET("/ping", [](HttpRequest* req, HttpResponse* resp) {
         return resp->String("pong");
     });

+ 13 - 11
http/server/HttpHandler.cpp

@@ -230,7 +230,7 @@ int HttpHandler::defaultRequestHandler() {
         if (service->staticHandler) {
             status_code = customHttpHandler(service->staticHandler);
         }
-        else if (service->document_root.size() != 0) {
+        else if (service->staticDirs.size() > 0) {
             status_code = defaultStaticHandler();
         }
         else {
@@ -253,15 +253,17 @@ int HttpHandler::defaultStaticHandler() {
     if (req_path[0] != '/' || strstr(req_path, "/../")) {
         return HTTP_STATUS_BAD_REQUEST;
     }
-    std::string filepath = service->document_root + path;
-    if (req_path[1] == '\0') {
-        filepath += service->home_page;
-    }
 
-    // dir
-    bool is_dir = filepath[filepath.size()-1] == '/';
-    bool is_index_of = service->index_of.size() != 0 && hv_strstartswith(req_path, service->index_of.c_str());
-    if (is_dir && !is_index_of) {
+    std::string filepath;
+    bool is_dir = path.back() == '/' &&
+                  service->index_of.size() > 0 &&
+                  hv_strstartswith(req_path, service->index_of.c_str());
+    if (is_dir) {
+        filepath = service->document_root + path;
+    } else {
+        filepath = service->GetStaticFilepath(req_path);
+    }
+    if (filepath.empty()) {
         return HTTP_STATUS_NOT_FOUND;
     }
 
@@ -341,8 +343,8 @@ int HttpHandler::defaultStaticHandler() {
 int HttpHandler::defaultLargeFileHandler() {
     if (!writer) return HTTP_STATUS_NOT_IMPLEMENTED;
     if (!isFileOpened()) {
-        std::string filepath = service->document_root + req->Path();
-        if (openFile(filepath.c_str()) != 0) {
+        std::string filepath = service->GetStaticFilepath(req->Path().c_str());
+        if (filepath.empty() || openFile(filepath.c_str()) != 0) {
             return HTTP_STATUS_NOT_FOUND;
         }
         resp->content_length = file->size();

+ 5 - 0
http/server/HttpServer.cpp

@@ -268,6 +268,11 @@ static void loop_thread(void* userdata) {
             gmtime_fmt(hloop_now(hevent_loop(timer)), HttpMessage::s_date);
         }, 1000);
 
+        // document_root
+        if (service->document_root.size() > 0 && service->GetStaticFilepath("/").empty()) {
+            service->Static("/", service->document_root.c_str());
+        }
+
         // FileCache
         FileCache* filecache = &privdata->filecache;
         filecache->stat_interval = service->file_cache_stat_interval;

+ 27 - 0
http/server/HttpService.cpp

@@ -128,4 +128,31 @@ int HttpService::GetApi(HttpRequest* req, http_handler** handler) {
     return HTTP_STATUS_NOT_FOUND;
 }
 
+void HttpService::Static(const char* path, const char* dir) {
+    std::string strPath(path);
+    if (strPath.back() != '/') strPath += '/';
+    std::string strDir(dir);
+    if (strDir.back() == '/') strDir.pop_back();
+    staticDirs[strPath] = strDir;
+}
+
+std::string HttpService::GetStaticFilepath(const char* path) {
+    std::string filepath;
+    for (auto iter = staticDirs.begin(); iter != staticDirs.end(); ++iter) {
+        if (hv_strstartswith(path, iter->first.c_str())) {
+            filepath = iter->second + (path + iter->first.length() - 1);
+            break;
+        }
+    }
+
+    if (filepath.empty()) {
+        return filepath;
+    }
+
+    if (filepath.back() == '/') {
+        filepath += home_page;
+    }
+    return filepath;
+}
+
 }

+ 7 - 0
http/server/HttpService.h

@@ -110,6 +110,8 @@ struct HV_EXPORT HttpService {
     std::string     document_root;
     std::string     home_page;
     std::string     error_page;
+    // location => root
+    std::map<std::string, std::string, std::greater<std::string>> staticDirs;
     // indexof service (that is http.DirectoryServer)
     std::string     index_of;
     http_handler    errorHandler;
@@ -148,6 +150,11 @@ struct HV_EXPORT HttpService {
     // RESTful API /:field/ => req->query_params["field"]
     int  GetApi(HttpRequest* req, http_handler** handler);
 
+    // Static("/", "/var/www/html")
+    void Static(const char* path, const char* dir);
+    // @retval / => /var/www/html/index.html
+    std::string GetStaticFilepath(const char* path);
+
     hv::StringList Paths() {
         hv::StringList paths;
         for (auto& pair : api_handlers) {