int connection_proxy_reply_parse(Connection *conn) { int rc = 0; int total = 0; Proxy *proxy = Request_get_action(conn->req, proxy); httpclient_parser *client = conn->client; rc = Proxy_read_and_parse(conn); check(rc != -1, "Failed to read from proxy server: %s:%d", bdata(proxy->server), proxy->port); if(client->chunked) { // send the http header we have so far rc = IOBuf_stream(conn->proxy_iob, conn->iob, client->body_start); check_debug(rc != -1, "Failed streaming header to client."); // then just stream out the chunks we've got, as long as // Proxy_stream_chunks return 0 it means we've got more to send do { rc = Proxy_stream_chunks(conn); check(rc != -1, "Failed to stream chunked encoding to client."); } while(rc == 0); } else if(client->content_len >= 0) { total = client->body_start + client->content_len; rc = IOBuf_stream(conn->proxy_iob, conn->iob, total); check(rc != -1, "Failed streaming non-chunked response."); } else if(client->status == 204 || client->status == 304) { // According to the RFC, these MUST NOT incude a body. // Proxy might keep the connection open but not send content-length. rc = IOBuf_stream(conn->proxy_iob, conn->iob, client->body_start); check(rc != -1, "Failed streaming non-chunked response."); } else if(client->close || client->content_len == -1) { debug("Response requested a read until close."); Proxy_stream_to_close(conn); } else { sentinel("Should not reach this code, Tell Zed."); } Log_request(conn, client->status, client->content_len); if(client->close) { return REMOTE_CLOSE; } else { return REQ_RECV; } error: return FAILED; }
int connection_http_to_handler(Connection *conn) { int content_len = Request_content_length(conn->req); int rc = 0; char *body = NULL; Handler *handler = Request_get_action(conn->req, handler); error_unless(handler, conn, 404, "No action for request: %s", bdata(Request_path(conn->req))); // we don't need the header anymore, so commit the buffer and deal with the body IOBuf_read_commit(conn->iob, Request_header_length(conn->req)); if(content_len == 0) { body = ""; rc = Connection_send_to_handler(conn, handler, body, content_len); check_debug(rc == 0, "Failed to deliver to the handler."); } else if(content_len > MAX_CONTENT_LENGTH) { rc = Upload_file(conn, handler, content_len); check(rc == 0, "Failed to upload file."); } else { if(content_len > conn->iob->len) { // temporarily grow the buffer IOBuf_resize(conn->iob, content_len); } debug("READ ALL CALLED with content_len: %d, and MAX_CONTENT_LENGTH: %d", content_len, MAX_CONTENT_LENGTH); body = IOBuf_read_all(conn->iob, content_len, CLIENT_READ_RETRIES); check(body != NULL, "Client closed the connection during upload."); rc = Connection_send_to_handler(conn, handler, body, content_len); check_debug(rc == 0, "Failed to deliver to the handler."); } Log_request(conn, 200, content_len); return REQ_SENT; error: return CLOSE; }
int connection_http_to_directory(Connection *conn) { Dir *dir = Request_get_action(conn->req, dir); int rc = Dir_serve_file(dir, conn->req, conn); check_debug(rc == 0, "Failed to serve file: %s", bdata(Request_path(conn->req))); IOBuf_read_commit(conn->iob, Request_header_length(conn->req) + Request_content_length(conn->req)); Log_request(conn, conn->req->status_code, conn->req->response_size); if(conn->close) { return CLOSE; } else { return RESP_SENT; } error: return CLOSE; }
int connection_http_to_handler(Connection *conn) { int content_len = Request_content_length(conn->req); int rc = 0; char *body = NULL; Handler *handler = Request_get_action(conn->req, handler); error_unless(handler, conn, 404, "No action for request: %s", bdata(Request_path(conn->req))); bstring expects = Request_get(conn->req, &HTTP_EXPECT); if (expects != NULL) { if (biseqcstr(expects, "100-continue")) { Response_send_status(conn, &HTTP_100); } else { Response_send_status(conn, &HTTP_417); log_info("Client requested unsupported expectation: %s.", bdata(expects)); goto error; } } // we don't need the header anymore, so commit the buffer and deal with the body check(IOBuf_read_commit(conn->iob, Request_header_length(conn->req)) != -1, "Finaly commit failed streaming the connection to http handlers."); if(is_websocket(conn)) { bstring wsKey = Request_get(conn->req, &WS_SEC_WS_KEY); bstring response= websocket_challenge(wsKey); conn->handler = handler; //Response_send_status(conn,response); bdestroy(conn->req->request_method); conn->req->request_method=bfromcstr("WEBSOCKET_HANDSHAKE"); Connection_send_to_handler(conn, handler, bdata(response), blength(response)); bdestroy(response); bdestroy(conn->req->request_method); conn->req->request_method=bfromcstr("WEBSOCKET"); return REQ_SENT; } if(content_len == 0) { body = ""; rc = Connection_send_to_handler(conn, handler, body, content_len); check_debug(rc == 0, "Failed to deliver to the handler."); } else if(content_len > MAX_CONTENT_LENGTH) { rc = Upload_file(conn, handler, content_len); check(rc == 0, "Failed to upload file."); } else { debug("READ ALL CALLED with content_len: %d, and MAX_CONTENT_LENGTH: %d", content_len, MAX_CONTENT_LENGTH); body = IOBuf_read_all(conn->iob, content_len, CLIENT_READ_RETRIES); check(body != NULL, "Client closed the connection during upload."); rc = Connection_send_to_handler(conn, handler, body, content_len); check_debug(rc == 0, "Failed to deliver to the handler."); } Log_request(conn, 200, content_len); return REQ_SENT; error: return CLOSE; }