Browse Source

fix #179: 中文路径

ithewei 3 years ago
parent
commit
2624022cf4

+ 8 - 2
cpputil/hurl.cpp

@@ -35,18 +35,24 @@ static inline bool is_unambiguous(char c) {
            c == '~';
 }
 
+static inline bool char_in_str(char c, const char* str) {
+    const char* p = str;
+    while (*p && *p != c) ++p;
+    return *p != '\0';
+}
+
 static inline unsigned char hex2i(char hex) {
     return hex <= '9' ? hex - '0' :
         hex <= 'F' ? hex - 'A' + 10 : hex - 'a' + 10;
 }
 
-std::string url_escape(const char* istr) {
+std::string url_escape(const char* istr, const char* unescaped_chars) {
     std::string ostr;
     static char tab[] = "0123456789ABCDEF";
     const unsigned char* p = reinterpret_cast<const unsigned char*>(istr);
     char szHex[4] = "%00";
     while (*p != '\0') {
-        if (is_unambiguous(*p)) {
+        if (is_unambiguous(*p) || char_in_str(*p, unescaped_chars)) {
             ostr += *p;
         }
         else {

+ 1 - 1
cpputil/hurl.h

@@ -5,7 +5,7 @@
 
 #include "hexport.h"
 
-HV_EXPORT std::string url_escape(const char* istr);
+HV_EXPORT std::string url_escape(const char* istr, const char* unescaped_chars = "");
 HV_EXPORT std::string url_unescape(const char* istr);
 
 #endif // HV_URL_H_

+ 3 - 1
examples/curl.cpp

@@ -8,6 +8,7 @@
  */
 
 #include "http_client.h"
+#include "hurl.h"
 
 #ifdef _MSC_VER
 #include "misc/win32_getopt.h"
@@ -262,7 +263,8 @@ int main(int argc, char* argv[]) {
             req.method = HTTP_POST;
         }
     }
-    req.url = url;
+    // http://127.0.0.1:8080@user:pswd/path?k1=v1&k2=v2#fragment
+    req.url = url_escape(url, ":/@?=&#");
     req.http_cb = [](HttpMessage* res, http_parser_state state, const char* data, size_t size) {
         if (state == HP_HEADERS_COMPLETE) {
             if (verbose) {

+ 1 - 0
getting_started.sh

@@ -33,6 +33,7 @@ cmd="bin/curl -v localhost:8080" && run_cmd
 
 # http indexof service
 cmd="bin/curl -v localhost:8080/downloads/" && run_cmd
+cmd="bin/curl -v localhost:8080/downloads/中文.html" && run_cmd
 
 # http api service
 cmd="bin/curl -v localhost:8080/paths" && run_cmd

+ 10 - 0
html/downloads/中文.html

@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html>
+<head>
+  <meta charset="utf-8" />
+  <title>中文测试</title>
+</head>
+<body>
+  <center><h1> 欢迎使用 <a href="https://github.com/ithewei/libhv.git">libhv</a> </h1></center>
+</body>
+</html>

+ 2 - 2
html/index.html

@@ -1,9 +1,9 @@
 <!DOCTYPE html>
 <html>
 <head>
-  <title>httpd</title>
+  <title>libhv</title>
 </head>
 <body>
-  <center><h1>Welcome to httpd!</h1></center>
+  <center><h1> Welcome to <a href="https://github.com/ithewei/libhv.git">libhv</a> </h1></center>
 </body>
 </html>

+ 9 - 9
http/HttpMessage.cpp

@@ -547,15 +547,7 @@ void HttpRequest::ParseUrl() {
     FillHost(host_.c_str(), port_);
     // path
     if (parser.field_set & (1<<UF_PATH)) {
-        const char* sp = url.c_str() + parser.field_data[UF_PATH].off;
-        char* ep = (char*)(sp + parser.field_data[UF_PATH].len);
-        char ev = *ep;
-        *ep = '\0';
-        path = url_unescape(sp);
-        if (ev != '\0') {
-            *ep = ev;
-            path += ep;
-        }
+        path = url.substr(parser.field_data[UF_PATH].off);
     }
     // query
     if (parser.field_set & (1<<UF_QUERY)) {
@@ -563,6 +555,14 @@ void HttpRequest::ParseUrl() {
     }
 }
 
+std::string HttpRequest::Path() {
+    const char* s = path.c_str();
+    const char* e = s;
+    while (*e && *e != '?' && *e != '#') ++e;
+    std::string path_no_query(s, e);
+    return url_unescape(path_no_query.c_str());
+}
+
 void HttpRequest::FillHost(const char* host, int port) {
     if (headers.find("Host") == headers.end()) {
         if (port == 0 ||

+ 3 - 6
http/HttpMessage.h

@@ -463,13 +463,10 @@ public:
     // url -> structed url
     void ParseUrl();
 
+    // /path?query#fragment
+    std::string FullPath() { return path; }
     // /path
-    std::string Path() {
-        const char* s = path.c_str();
-        const char* e = s;
-        while (*e && *e != '?' && *e != '#') ++e;
-        return std::string(s, e);
-    }
+    std::string Path();
 
     // ?query_params
     template<typename T>

+ 28 - 11
http/server/http_page.cpp

@@ -24,8 +24,6 @@ void make_http_status_page(http_status status_code, std::string& page) {
 }
 
 void make_index_of_page(const char* dir, std::string& page, const char* url) {
-    std::list<hdir_t> dirs;
-    listdir(dir, dirs);
     char c_str[1024] = {0};
     snprintf(c_str, sizeof(c_str), R"(<!DOCTYPE html>
 <html>
@@ -35,11 +33,27 @@ void make_index_of_page(const char* dir, std::string& page, const char* url) {
 <body>
   <h1>Index of %s</h1>
   <hr>
-<pre>
 )", url, url);
     page += c_str;
+
+    page += "  <table border=\"0\">\n";
+    page += R"(    <tr>
+      <th align="left" width="30%">Name</th>
+      <th align="left" width="20%">Date</th>
+      <th align="left" width="20%">Size</th>
+    </tr>
+)";
+
+#define _ADD_TD_(page, td)  \
+    page += "      <td>";   \
+    page += td;             \
+    page += "</td>\n";      \
+
+    std::list<hdir_t> dirs;
+    listdir(dir, dirs);
     for (auto& item : dirs) {
         if (item.name[0] == '.' && item.name[1] == '\0') continue;
+        page += "    <tr>\n";
         int len = strlen(item.name) + (item.type == 'd');
         // name
         snprintf(c_str, sizeof(c_str), "<a href=\"%s%s\">%s%s</a>",
@@ -47,14 +61,13 @@ void make_index_of_page(const char* dir, std::string& page, const char* url) {
                 item.type == 'd' ? "/" : "",
                 len < AUTOINDEX_FILENAME_MAXLEN ? item.name : std::string(item.name, item.name+AUTOINDEX_FILENAME_MAXLEN-4).append("...").c_str(),
                 item.type == 'd' ? "/" : "");
-        page += c_str;
+        _ADD_TD_(page, c_str)
         if (strcmp(item.name, "..") != 0) {
             // mtime
             struct tm* tm = localtime(&item.mtime);
-            snprintf(c_str, sizeof(c_str), "%04d-%02d-%02d %02d:%02d:%02d        ",
+            snprintf(c_str, sizeof(c_str), "%04d-%02d-%02d %02d:%02d:%02d",
                     tm->tm_year+1900, tm->tm_mon+1, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec);
-            page += std::string(AUTOINDEX_FILENAME_MAXLEN - len, ' ');
-            page += c_str;
+            _ADD_TD_(page, c_str)
             // size
             if (item.type == 'd') {
                 page += '-';
@@ -74,13 +87,17 @@ void make_index_of_page(const char* dir, std::string& page, const char* url) {
                     hsize /= 1024.0f;
                     snprintf(c_str, sizeof(c_str), "%.1fG", hsize);
                 }
-                page += c_str;
+                _ADD_TD_(page, c_str)
             }
         }
-        page += "\r\n";
+        page += "    </tr>\n";
     }
-    page += R"(</pre>
+
+#undef _ADD_TD_
+
+    page += R"(  </table>
   <hr>
 </body>
-</html>)";
+</html>
+)";
 }

+ 19 - 7
http/server/http_page.h

@@ -28,13 +28,25 @@ void make_http_status_page(http_status status_code, std::string& page);
 <body>
   <h1>Index of /downloads/</h1>
   <hr>
-<pre>
-<a href="../">../</a>
-<a href="docs/">docs/</a>                                             2019-08-23 15:27:48        -
-<a href="examples/">examples/</a>                                         2019-08-23 15:27:52        -
-<a href="README.txt">README.txt</a>                                        2019-08-23 19:15:42        0
-<a href="release/">release/</a>                                          2019-08-23 15:28:52        -
-</pre>
+  <table border="0">
+    <tr>
+      <th align="left" width="30%">Name</th>
+      <th align="left" width="20%">Date</th>
+      <th align="left" width="20%">Size</th>
+    </tr>
+    <tr>
+      <td><a href="../">../</a></td>
+    </tr>
+    <tr>
+      <td><a href="libhv-vs-nginx.png">libhv-vs-nginx.png</a></td>
+      <td>2021-03-10 12:33:57</td>
+      <td>211.4K</td>
+    </tr>
+      <td><a href="中文.html">中文.html</a></td>
+      <td>2022-04-25 15:37:12</td>
+      <td>191</td>
+    </tr>
+  </table>
   <hr>
 </body>
 </html>