}
- 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);
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;
}
if (status != 200)
return MK_PLUGIN_RET_END;
- sr->close_now = MK_TRUE;
+ sr->headers.cgi = SH_CGI;
return MK_PLUGIN_RET_CONTINUE;
}
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);
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);
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);
}
/* 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);