Browse Source

HttpResponseWriter::WriteResponse

hewei.it 4 years ago
parent
commit
5c5e835ce8
3 changed files with 41 additions and 21 deletions
  1. 2 2
      examples/httpd/handler.h
  2. 13 9
      examples/httpd/router.h
  3. 26 10
      http/server/HttpResponseWriter.h

+ 2 - 2
examples/httpd/handler.h

@@ -55,14 +55,14 @@ public:
     }
 
     static void setTimeout(const HttpRequestPtr& req, const HttpResponseWriterPtr& writer) {
-        writer->resp->Set("start_ms", gettimeofday_ms());
+        writer->response->Set("start_ms", gettimeofday_ms());
         std::string strTime = req->GetParam("t");
         if (!strTime.empty()) {
             int ms = atoi(strTime.c_str());
             if (ms > 0) {
                 hv::setTimeout(ms, [writer](hv::TimerID timerID){
                     writer->Begin();
-                    HttpResponse* resp = writer->resp.get();
+                    HttpResponse* resp = writer->response.get();
                     resp->Set("end_ms", gettimeofday_ms());
                     response_status(resp, 0, "OK");
                     writer->End();

+ 13 - 9
examples/httpd/router.h

@@ -52,27 +52,31 @@ public:
 
         // curl -v http://ip:port/async
         router.GET("/async", [](const HttpRequestPtr& req, const HttpResponseWriterPtr& writer) {
-            writer->resp->headers["X-Request-tid"] = hv::to_string(hv_gettid());
+            writer->response->headers["X-Request-tid"] = hv::to_string(hv_gettid());
             std::async([req, writer](){
                 writer->Begin();
                 std::string resp_tid = hv::to_string(hv_gettid());
-                writer->resp->headers["X-Response-tid"] = hv::to_string(hv_gettid());
+                writer->response->headers["X-Response-tid"] = hv::to_string(hv_gettid());
                 writer->WriteHeader("Content-Type", "text/plain");
                 writer->WriteBody("This is an async response.\n");
                 writer->End();
             });
         });
 
-        // curl -v http://ip:port/www/*
-        // curl -v http://ip:port/www/example.com
-        // curl -v http://ip:port/www/example/com
-        router.GET("/www/*", [](const HttpRequestPtr& req, const HttpResponseWriterPtr& writer) {
+        // curl -v http://ip:port/www.*
+        // curl -v http://ip:port/www.example.com
+        router.GET("/www.*", [](const HttpRequestPtr& req, const HttpResponseWriterPtr& writer) {
             HttpRequestPtr req2(new HttpRequest);
-            req2->url = replace(req->path.substr(1), "/", ".");
-            // printf("url=%s\n", req2->url.c_str());
+            req2->url = req->path.substr(1);
             http_client_send_async(req2, [writer](const HttpResponsePtr& resp2){
                 writer->Begin();
-                writer->resp = resp2;
+                if (resp2 == NULL) {
+                    writer->WriteStatus(HTTP_STATUS_NOT_FOUND);
+                    writer->WriteHeader("Content-Type", "text/html");
+                    writer->WriteBody("<center><h1>404 Not Found</h1></center>");
+                } else {
+                    writer->WriteResponse(resp2.get());
+                }
                 writer->End();
             });
         });

+ 26 - 10
http/server/HttpResponseWriter.h

@@ -8,41 +8,46 @@ namespace hv {
 
 class HttpResponseWriter : public SocketChannel {
 public:
-    HttpResponsePtr resp;
+    HttpResponsePtr response;
     enum State {
         SEND_BEGIN,
         SEND_HEADER,
         SEND_BODY,
         SEND_END,
     } state;
-    HttpResponseWriter(hio_t* io, const HttpResponsePtr& _resp)
+    HttpResponseWriter(hio_t* io, const HttpResponsePtr& resp)
         : SocketChannel(io)
-        , resp(_resp)
+        , response(resp)
         , state(SEND_BEGIN)
     {}
     ~HttpResponseWriter() {}
 
+    // Begin -> End
+    // Begin -> WriteResponse -> End
+    // Begin -> WriteStatus -> WriteHeader -> WriteBody -> End
+    // Begin -> WriteHeader -> EndHeaders -> WriteBody -> WriteBody -> ... -> End
+
     int Begin() {
         state = SEND_BEGIN;
         return 0;
     }
 
     int WriteStatus(http_status status_codes) {
-        resp->status_code = status_codes;
+        response->status_code = status_codes;
         return 0;
     }
 
     int WriteHeader(const char* key, const char* value) {
-        resp->headers[key] = value;
+        response->headers[key] = value;
         return 0;
     }
 
     int EndHeaders(const char* key = NULL, const char* value = NULL) {
         if (state != SEND_BEGIN) return -1;
         if (key && value) {
-            resp->headers[key] = value;
+            response->headers[key] = value;
         }
-        std::string headers = resp->Dump(true, false);
+        std::string headers = response->Dump(true, false);
         state = SEND_HEADER;
         return write(headers);
     }
@@ -50,7 +55,7 @@ public:
     int WriteBody(const char* buf, int len = -1) {
         if (len == -1) len = strlen(buf);
         if (state == SEND_BEGIN) {
-            resp->body.append(buf, len);
+            response->body.append(buf, len);
             return len;
         } else {
             state = SEND_BODY;
@@ -62,6 +67,17 @@ public:
         return WriteBody(str.c_str(), str.size());
     }
 
+    int WriteResponse(HttpResponse* resp) {
+        if (resp == NULL) {
+            response->status_code = HTTP_STATUS_INTERNAL_SERVER_ERROR;
+            return 0;
+        }
+        bool is_dump_headers = state == SEND_BEGIN ? true : false;
+        std::string msg = resp->Dump(is_dump_headers, true);
+        state = SEND_BODY;
+        return write(msg);
+    }
+
     int End(const char* buf = NULL, int len = -1) {
         if (state == SEND_END) return 0;
         int ret = 0;
@@ -77,11 +93,11 @@ public:
             is_dump_body = false;
         }
         if (is_dump_body) {
-            std::string msg = resp->Dump(is_dump_headers, is_dump_body);
+            std::string msg = response->Dump(is_dump_headers, is_dump_body);
             ret = write(msg);
         }
         state = SEND_END;
-        if (!resp->IsKeepAlive()) {
+        if (!response->IsKeepAlive()) {
             close();
         }
         return ret;