Hi

I had a bit of trouble with this, but seems to be in good condition now.

 plugins/cgi/cgi.c     |   15 ++++++--
 plugins/cgi/cgi.h     |   10 ++++-
 plugins/cgi/event.c   |   96 ++++++++++++++++++++++++++++++++++++++++++------
 plugins/cgi/request.c |    5 ++-
 4 files changed, 108 insertions(+), 18 deletions(-)

- Lauri
>From 93baa9a15c94aa8c7599e5e701cfd814a37edf05 Mon Sep 17 00:00:00 2001
From: Lauri Kasanen <[email protected]>
Date: Fri, 6 Jul 2012 14:49:25 +0300
Subject: [PATCH] cgi: Pass headers through monkey, support chunked encoding


Signed-off-by: Lauri Kasanen <[email protected]>
---
 plugins/cgi/cgi.c     |   15 ++++++--
 plugins/cgi/cgi.h     |   10 ++++-
 plugins/cgi/event.c   |   96 ++++++++++++++++++++++++++++++++++++++++++------
 plugins/cgi/request.c |    5 ++-
 4 files changed, 108 insertions(+), 18 deletions(-)

diff --git a/plugins/cgi/cgi.c b/plugins/cgi/cgi.c
index 41865b4..409a71a 100644
--- a/plugins/cgi/cgi.c
+++ b/plugins/cgi/cgi.c
@@ -233,9 +233,18 @@ static int do_cgi(const char * const __restrict__ file, 
const char * const __res
     }
 
 
-    struct cgi_request *r = cgi_req_create(readpipe[0], socket);
+    struct cgi_request *r = cgi_req_create(readpipe[0], socket, sr, cs);
     if (!r) return 403;
 
+    if (r->sr->protocol >= HTTP_PROTOCOL_11 &&
+        (r->sr->headers.status < MK_REDIR_MULTIPLE ||
+         r->sr->headers.status > MK_REDIR_USE_PROXY))
+    {
+        r->sr->headers.transfer_encoding = MK_HEADER_TE_TYPE_CHUNKED;
+        r->chunked = 1;
+    }
+
+
     cgi_req_add(r);
     mk_api->event_add(readpipe[0], MK_EPOLL_READ, plugin, cs, sr, 
MK_EPOLL_LEVEL_TRIGGERED);
 
@@ -243,7 +252,7 @@ static int do_cgi(const char * const __restrict__ file, 
const char * const __res
     requests_by_socket[socket] = r;
 
     /* We have nothing to write yet */
-    mk_api->event_socket_change_mode(socket, MK_EPOLL_READ, 
MK_EPOLL_LEVEL_TRIGGERED);
+    mk_api->event_socket_change_mode(socket, MK_EPOLL_SLEEP, 
MK_EPOLL_LEVEL_TRIGGERED);
 
     return 200;
 }
@@ -402,7 +411,7 @@ int _mkp_stage_30(struct plugin *plugin, struct 
client_session *cs,
     if (status != 200)
         return MK_PLUGIN_RET_END;
 
-    sr->close_now = MK_TRUE;
+    sr->headers.cgi = SH_CGI;
 
     return MK_PLUGIN_RET_CONTINUE;
 }
diff --git a/plugins/cgi/cgi.h b/plugins/cgi/cgi.h
index 38a1bf9..cd7bbd8 100644
--- a/plugins/cgi/cgi.h
+++ b/plugins/cgi/cgi.h
@@ -43,19 +43,25 @@ struct cgi_request {
 
     struct mk_list _head;
 
+    struct session_request *sr;
+    struct client_session *cs;
+
     unsigned int in_len;
 
     int fd;                    /* From the CGI app */
     int socket;
 
-    unsigned char headers_done;
+    unsigned char status_done;
+    unsigned char all_headers_done;
+    unsigned char chunked;
 };
 
 extern struct cgi_request **requests_by_socket;
 
 int swrite(const int fd, const void *buf, const size_t count);
 
-struct cgi_request *cgi_req_create(int fd, int socket);
+struct cgi_request *cgi_req_create(int fd, int socket, struct session_request 
*sr,
+                                       struct client_session *cs);
 void cgi_req_add(struct cgi_request *r);
 int cgi_req_del(struct cgi_request *r);
 
diff --git a/plugins/cgi/event.c b/plugins/cgi/event.c
index f14c12f..d8f4389 100644
--- a/plugins/cgi/event.c
+++ b/plugins/cgi/event.c
@@ -30,6 +30,11 @@ static int hangup(int socket)
 
         mk_api->event_del(r->fd);
 
+        if (r->chunked)
+        {
+            swrite(r->socket, "0\r\n\r\n", 5);
+        }
+
         mk_api->http_request_end(r->socket);
         mk_api->socket_close(r->fd);
 
@@ -52,26 +57,90 @@ int _mkp_event_write(int socket)
 
         mk_api->socket_cork_flag(socket, TCP_CORK_ON);
 
-        const char *buf = r->in_buf, *outptr = r->in_buf;
+        const char * const buf = r->in_buf, *outptr = r->in_buf;
+
+        if (!r->status_done && r->in_len >= 8) {
+            if (memcmp(buf, "Status: ", 8) == 0) {
+                int status = atoi(buf + 8);
+                mk_api->header_set_http_status(r->sr, status);
+
+                char *endl = memchr(buf + 8, '\n', r->in_len - 8);
+                if (!endl) {
+                    return MK_PLUGIN_RET_EVENT_OWNED;
+                }
+                else {
+                    endl++;
+                    outptr = endl;
+                    r->in_len -= endl - buf;
+                }
 
-        if (!r->headers_done) {
-            if (r->in_len >= 8 && memcmp(buf, "Status: ", 8) == 0) {
-                swrite(socket, "HTTP/1.0 ", 9);
-                outptr += 8;
-                r->in_len -= 8;
-                r->headers_done = 1;
             }
-            else if (r->in_len >= 4) {
-                if (memcmp(buf, "HTTP", 4) != 0) {
-                    swrite(socket, "HTTP/1.0 200 OK\r\n", sizeof("HTTP/1.0 200 
OK\r\n") - 1);
+            else if (memcmp(buf, "HTTP", 4) == 0) {
+                int status = atoi(buf + 9);
+                mk_api->header_set_http_status(r->sr, status);
+
+                char *endl = memchr(buf + 8, '\n', r->in_len - 8);
+                if (!endl) {
+                    return MK_PLUGIN_RET_EVENT_OWNED;
+                }
+                else {
+                    endl++;
+                    outptr = endl;
+                    r->in_len -= endl - buf;
                 }
-                r->headers_done = 1;
             }
+
+            mk_api->header_send(socket, r->cs, r->sr);
+
+            r->status_done = 1;
+        }
+
+        if (!r->all_headers_done)
+        {
+            // Write the rest of the headers without chunking
+            char *end = strstr(outptr, MK_IOV_CRLFCRLF);
+            if (!end) end = strstr(outptr, MK_IOV_LFLFLFLF);
+            if (!end)
+            {
+                swrite(socket, outptr, r->in_len);
+                r->in_len = 0;
+                mk_api->event_socket_change_mode(socket, MK_EPOLL_SLEEP, 
MK_EPOLL_LEVEL_TRIGGERED);
+                return MK_PLUGIN_RET_EVENT_OWNED;
+            }
+
+            end += 4;
+
+            int len = end - outptr;
+
+            swrite(socket, outptr, len);
+            outptr += len;
+            r->in_len -= len;
+
+            r->all_headers_done = 1;
+
+            if (r->in_len == 0)
+            {
+                mk_api->event_socket_change_mode(socket, MK_EPOLL_SLEEP, 
MK_EPOLL_LEVEL_TRIGGERED);
+                return MK_PLUGIN_RET_EVENT_OWNED;
+            }
+        }
+
+        if (r->chunked)
+        {
+            char tmp[16];
+            int len = snprintf(tmp, 16, "%x%s", r->in_len, MK_CRLF);
+            swrite(socket, tmp, len);
         }
 
         swrite(socket, outptr, r->in_len);
         r->in_len = 0;
-        mk_api->event_socket_change_mode(socket, MK_EPOLL_READ, 
MK_EPOLL_LEVEL_TRIGGERED);
+        mk_api->event_socket_change_mode(socket, MK_EPOLL_SLEEP, 
MK_EPOLL_LEVEL_TRIGGERED);
+        mk_api->event_socket_change_mode(r->fd, MK_EPOLL_READ, 
MK_EPOLL_LEVEL_TRIGGERED);
+
+        if (r->chunked)
+        {
+            swrite(socket, MK_CRLF, 2);
+        }
 
         mk_api->socket_cork_flag(socket, TCP_CORK_OFF);
     }
@@ -88,7 +157,10 @@ int _mkp_event_read(int fd)
 
     /* Too much to read? Start writing. */
     if (count < 1)
+    {
+        mk_api->event_socket_change_mode(r->fd, MK_EPOLL_SLEEP, 
MK_EPOLL_LEVEL_TRIGGERED);
         goto out;
+    }
 
     int n = read(r->fd, r->in_buf + r->in_len, count);
 
diff --git a/plugins/cgi/request.c b/plugins/cgi/request.c
index 614df1d..20be3d4 100644
--- a/plugins/cgi/request.c
+++ b/plugins/cgi/request.c
@@ -19,13 +19,16 @@
 
 #include "cgi.h"
 
-struct cgi_request *cgi_req_create(int fd, int socket)
+struct cgi_request *cgi_req_create(int fd, int socket, struct session_request 
*sr,
+                                       struct client_session *cs)
 {
     struct cgi_request *newcgi = mk_api->mem_alloc_z(sizeof(struct 
cgi_request));
     if (!newcgi) return NULL;
 
     newcgi->fd = fd;
     newcgi->socket = socket;
+    newcgi->sr = sr;
+    newcgi->cs = cs;
 
     return newcgi;
 }
-- 
1.7.2.1

_______________________________________________
Monkey mailing list
[email protected]
http://lists.monkey-project.com/listinfo/monkey

Reply via email to