Selaa lähdekoodia

Add HttpMessage::cookies

hewei.it 4 vuotta sitten
vanhempi
commit
3778cfd780
5 muutettua tiedostoa jossa 45 lisäystä ja 24 poistoa
  1. 1 1
      examples/http_server_test.cpp
  2. 1 1
      examples/httpd/router.h
  3. 5 8
      http/Http1Parser.h
  4. 22 7
      http/HttpMessage.cpp
  5. 16 7
      http/HttpMessage.h

+ 1 - 1
examples/http_server_test.cpp

@@ -38,7 +38,7 @@ int main(int argc, char** argv) {
 
     router.GET("/data", [](HttpRequest* req, HttpResponse* resp) {
         static char data[] = "0123456789";
-        return resp->Data(data, 10);
+        return resp->Data(data, 10 /*, false */);
     });
 
     router.GET("/paths", [&router](HttpRequest* req, HttpResponse* resp) {

+ 1 - 1
examples/httpd/router.h

@@ -23,7 +23,7 @@ public:
         // curl -v http://ip:port/data
         router.GET("/data", [](HttpRequest* req, HttpResponse* resp) {
             static char data[] = "0123456789";
-            return resp->Data(data, 10);
+            return resp->Data(data, 10 /*, false */);
         });
 
         // curl -v http://ip:port/html/index.html

+ 5 - 8
http/Http1Parser.h

@@ -35,16 +35,13 @@ public:
 
     void handle_header() {
         if (header_field.size() != 0 && header_value.size() != 0) {
-#if 0
-            if (stricmp(header_field.c_str(), "Set-CooKie") == 0) {
-                // combine multiple Set-Cookie
-                std::string cookie = parsed->GetHeader("Set-Cookie");
-                if (!cookie.empty()) {
-                    header_value += "; ";
-                    header_value += cookie;
+            if (stricmp(header_field.c_str(), "Set-CooKie") == 0 ||
+                stricmp(header_field.c_str(), "Cookie") == 0) {
+                HttpCookie cookie;
+                if (cookie.parse(header_value)) {
+                    parsed->cookies.emplace_back(cookie);
                 }
             }
-#endif
             parsed->headers[header_field] = header_value;
             header_field.clear();
             header_value.clear();

+ 22 - 7
http/HttpMessage.cpp

@@ -323,6 +323,8 @@ bool HttpMessage::IsKeepAlive() {
 void HttpMessage::DumpHeaders(std::string& str) {
     FillContentType();
     FillContentLength();
+
+    // headers
     for (auto& header: headers) {
         // http2 :method :path :scheme :authority :status
         if (*str.c_str() != ':') {
@@ -333,6 +335,18 @@ void HttpMessage::DumpHeaders(std::string& str) {
             str += "\r\n";
         }
     }
+
+    // cookies
+    const char* cookie_field = "Cookie";
+    if (type == HTTP_RESPONSE) {
+        cookie_field = "Set-Cookie";
+    }
+    for (auto& cookie : cookies) {
+        str += cookie_field;
+        str += ": ";
+        str += cookie.dump();
+        str += "\r\n";
+    }
 }
 
 void HttpMessage::DumpBody() {
@@ -503,11 +517,11 @@ void HttpRequest::ParseUrl() {
 std::string HttpRequest::Dump(bool is_dump_headers, bool is_dump_body) {
     ParseUrl();
 
-    char c_str[256] = {0};
     std::string str;
+    str.reserve(MAX(512, path.size() + 128));
     // GET / HTTP/1.1\r\n
-    snprintf(c_str, sizeof(c_str), "%s %s HTTP/%d.%d\r\n", http_method_str(method), path.c_str(), http_major, http_minor);
-    str += c_str;
+    str = asprintf("%s %s HTTP/%d.%d\r\n",
+            http_method_str(method), path.c_str(), http_major, http_minor);
     if (is_dump_headers) {
         // Host:
         if (headers.find("Host") == headers.end()) {
@@ -517,8 +531,7 @@ std::string HttpRequest::Dump(bool is_dump_headers, bool is_dump_body) {
                 headers["Host"] = host;
             }
             else {
-                snprintf(c_str, sizeof(c_str), "%s:%d", host.c_str(), port);
-                headers["Host"] = c_str;
+                headers["Host"] = asprintf("%s:%d", host.c_str(), port);
             }
         }
         DumpHeaders(str);
@@ -533,9 +546,11 @@ std::string HttpRequest::Dump(bool is_dump_headers, bool is_dump_body) {
 std::string HttpResponse::Dump(bool is_dump_headers, bool is_dump_body) {
     char c_str[256] = {0};
     std::string str;
+    str.reserve(512);
     // HTTP/1.1 200 OK\r\n
-    snprintf(c_str, sizeof(c_str), "HTTP/%d.%d %d %s\r\n", http_major, http_minor, status_code, http_status_str(status_code));
-    str += c_str;
+    snprintf(c_str, sizeof(c_str), "HTTP/%d.%d %d %s\r\n",
+            http_major, http_minor, status_code, http_status_str(status_code));
+    str = c_str;
     if (is_dump_headers) {
         if (*s_date) {
             headers["Date"] = s_date;

+ 16 - 7
http/HttpMessage.h

@@ -39,9 +39,6 @@
 #include "httpdef.h"
 #include "http_content.h"
 
-typedef std::map<std::string, std::string, StringCaseLess>  http_headers;
-typedef std::string                                         http_body;
-
 struct HNetAddr {
     std::string     ip;
     int             port;
@@ -62,7 +59,7 @@ struct HV_EXPORT HttpCookie {
     bool        httponly;
 
     HttpCookie() {
-        max_age = 0;
+        max_age = 86400;
         secure = false;
         httponly = false;
     }
@@ -71,6 +68,10 @@ struct HV_EXPORT HttpCookie {
     std::string dump() const;
 };
 
+typedef std::map<std::string, std::string, StringCaseLess>  http_headers;
+typedef std::vector<HttpCookie>                             http_cookies;
+typedef std::string                                         http_body;
+
 class HV_EXPORT HttpMessage {
 public:
     static char         s_date[32];
@@ -79,6 +80,7 @@ public:
     unsigned short      http_minor;
 
     http_headers        headers;
+    http_cookies        cookies;
     http_body           body;
 
     // structured content
@@ -241,10 +243,17 @@ public:
         return 200;
     }
 
-    int Data(void* data, int len) {
+    int Data(void* data, int len, bool nocopy = true) {
         content_type = APPLICATION_OCTET_STREAM;
-        content = data;
-        content_length = len;
+        if (nocopy) {
+            content = data;
+            content_length = len;
+        } else {
+            content_length = body.size();
+            body.resize(content_length + len);
+            memcpy((void*)(body.data() + content_length), data, len);
+            content_length += len;
+        }
         return 200;
     }