diff --git a/cherokee/admin/ModuleUwsgi.py b/cherokee/admin/ModuleUwsgi.py index f85e18c2..afdbcb32 100644 --- a/cherokee/admin/ModuleUwsgi.py +++ b/cherokee/admin/ModuleUwsgi.py @@ -16,7 +16,11 @@ HELPS = [ class ModuleUwsgi (ModuleCgiBase): PROPERTIES = ModuleCgiBase.PROPERTIES + [ - 'balancer' + 'balancer', + 'modifier1', + 'modifier2', + 'pass_wsgi_vars', + 'pass_request_body' ] def __init__ (self, cfg, prefix, submit): @@ -32,13 +36,45 @@ class ModuleUwsgi (ModuleCgiBase): txt += '

%s

' % (_('UWSGI specific')) table = TableProps() - prefix = "%s!balancer" % (self._prefix) - e = self.AddPropOptions_Reload_Module (table, _("Balancer"), prefix, + + + opt = "%s!modifier1" % (self._prefix) + self.AddPropEntry(table, _('Modifier1'), opt, 'a number between 0 and 255', size=3); + + opt = "%s!modifier2" % (self._prefix) + self.AddPropEntry(table, _('Modifier2'), opt, 'a number between 0 and 255', size=3); + + opt = "%s!pass_wsgi_vars" % (self._prefix) + self.AddPropCheck (table, _("Pass WSGI vars"), opt, True, 'pass all the wsgi vars to the application') + + opt = "%s!pass_request_body" % (self._prefix) + self.AddPropCheck (table, _("Pass Request body"), opt, True, 'pass the request body to the application') + + opt = "%s!balancer" % (self._prefix) + e = self.AddPropOptions_Reload_Module (table, _("Balancer"), opt, modules_available(BALANCERS), _(NOTE_BALANCER)) + txt += self.Indent(str(table) + e) + return txt def _op_apply_changes (self, uri, post): + + # Apply modifier1 + opt = "%s!modifier1" % (self._prefix) + mod1 = post.pop(opt) + if mod1: + self._cfg[opt] = mod1 + + # Apply modifier2 + opt = "%s!modifier2" % (self._prefix) + mod2 = post.pop(opt) + if mod2: + self._cfg[opt] = mod2 + + # Apply pass_request_body and pass_wsgi_vars + self.ApplyChangesPrefix (self._prefix, ['pass_wsgi_vars','pass_request_body'], post) + # Apply balancer changes pre = "%s!balancer" % (self._prefix) diff --git a/cherokee/handler_uwsgi.c b/cherokee/handler_uwsgi.c index 36489a37..935cfad4 100644 --- a/cherokee/handler_uwsgi.c +++ b/cherokee/handler_uwsgi.c @@ -20,7 +20,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * 02110-1301, USA. - */ + */ #include "common-internal.h" #include "handler_uwsgi.h" @@ -38,9 +38,15 @@ */ CGI_LIB_INIT (uwsgi, http_all_methods); +#if BYTE_ORDER == BIG_ENDIAN +static uint16_t uwsgi_swap16(uint16_t x) { + return (uint16_t) ((x & 0xff) << 8 | (x & 0xff00) >> 8); +} +#endif + /* Methods implementation */ -static ret_t +static ret_t props_free (cherokee_handler_uwsgi_props_t *props) { if (props->balancer) @@ -49,27 +55,31 @@ props_free (cherokee_handler_uwsgi_props_t *props) return cherokee_handler_cgi_base_props_free (PROP_CGI_BASE(props)); } -ret_t +ret_t cherokee_handler_uwsgi_configure (cherokee_config_node_t *conf, cherokee_server_t *srv, cherokee_module_props_t **_props) { ret_t ret; cherokee_list_t *i; cherokee_handler_uwsgi_props_t *props; - + /* Instance a new property object */ if (*_props == NULL) { CHEROKEE_NEW_STRUCT (n, handler_uwsgi_props); - cherokee_handler_cgi_base_props_init_base (PROP_CGI_BASE(n), + cherokee_handler_cgi_base_props_init_base (PROP_CGI_BASE(n), MODULE_PROPS_FREE(props_free)); n->balancer = NULL; + n->modifier1 = 0 ; + n->modifier2 = 0 ; + n->pass_wsgi_vars = true; + n->pass_request_body = true; *_props = MODULE_PROPS(n); } - props = PROP_UWSGI(*_props); + props = PROP_UWSGI(*_props); /* Parse the configuration tree */ @@ -77,9 +87,21 @@ cherokee_handler_uwsgi_configure (cherokee_config_node_t *conf, cherokee_server_ cherokee_config_node_t *subconf = CONFIG_NODE(i); if (equal_buf_str (&subconf->key, "balancer")) { - ret = cherokee_balancer_instance (&subconf->val, subconf, srv, &props->balancer); + ret = cherokee_balancer_instance (&subconf->val, subconf, srv, &props->balancer); if (ret != ret_ok) return ret; } + else if (equal_buf_str (&subconf->key, "modifier1")) { + props->modifier1 = (uint8_t) atoi(subconf->val.buf); + } + else if (equal_buf_str (&subconf->key, "modifier2")) { + props->modifier2 = (uint8_t) atoi(subconf->val.buf); + } + else if (equal_buf_str (&subconf->key, "pass_wsgi_vars")) { + props->pass_wsgi_vars = !! atoi (subconf->val.buf); + } + else if (equal_buf_str (&subconf->key, "pass_request_body")) { + props->pass_request_body = !! atoi (subconf->val.buf); + } } /* Init base class @@ -90,7 +112,7 @@ cherokee_handler_uwsgi_configure (cherokee_config_node_t *conf, cherokee_server_ /* Final checks */ if (props->balancer == NULL) { - LOG_CRITICAL_S ("ERROR: UWSGI handler needs a balancer\n"); + LOG_CRITICAL_S (CHEROKEE_ERROR_HANDLER_NO_BALANCER); return ret_error; } @@ -98,24 +120,35 @@ cherokee_handler_uwsgi_configure (cherokee_config_node_t *conf, cherokee_server_ } -static void -add_env_pair (cherokee_handler_cgi_base_t *cgi_base, - const char *key, int key_len, +static void +add_env_pair (cherokee_handler_cgi_base_t *cgi_base, + const char *key, int key_len, const char *val, int val_len) { cherokee_handler_uwsgi_t *uwsgi = HDL_UWSGI(cgi_base); - unsigned short u_key_len = (unsigned short) key_len ; - unsigned short u_val_len = (unsigned short) val_len ; + uint16_t u_key_len = (uint16_t) key_len ; + uint16_t u_val_len = (uint16_t) val_len ; /* 2 bytes for every string (16 bit le) */ cherokee_buffer_ensure_size (&uwsgi->header, uwsgi->header.len + key_len + val_len + 4); - /* TODO: force to le if cherokee is big-endian */ - + /* force to le if cherokee is big-endian */ +#if BYTE_ORDER == BIG_ENDIAN + u_key_len = uwsgi_swap16(u_key_len); +#endif cherokee_buffer_add (&uwsgi->header, (const char *) &u_key_len, 2); +#if BYTE_ORDER == BIG_ENDIAN + u_key_len = uwsgi_swap16(u_key_len); +#endif cherokee_buffer_add (&uwsgi->header, key, key_len); +#if BYTE_ORDER == BIG_ENDIAN + u_val_len = uwsgi_swap16(u_val_len); +#endif cherokee_buffer_add (&uwsgi->header, (const char *) &u_val_len, 2); +#if BYTE_ORDER == BIG_ENDIAN + u_val_len = uwsgi_swap16(u_val_len); +#endif cherokee_buffer_add (&uwsgi->header, val, val_len); } @@ -126,12 +159,12 @@ read_from_uwsgi (cherokee_handler_cgi_base_t *cgi_base, cherokee_buffer_t *buffe ret_t ret; size_t read = 0; cherokee_handler_uwsgi_t *uwsgi = HDL_UWSGI(cgi_base); - + ret = cherokee_socket_bufread (&uwsgi->socket, buffer, 4096, &read); switch (ret) { case ret_eagain: - cherokee_thread_deactive_to_polling (HANDLER_THREAD(cgi_base), HANDLER_CONN(cgi_base), + cherokee_thread_deactive_to_polling (HANDLER_THREAD(cgi_base), HANDLER_CONN(cgi_base), uwsgi->socket.socket, 0, false); return ret_eagain; @@ -149,20 +182,20 @@ read_from_uwsgi (cherokee_handler_cgi_base_t *cgi_base, cherokee_buffer_t *buffe } SHOULDNT_HAPPEN; - return ret_error; + return ret_error; } -ret_t +ret_t cherokee_handler_uwsgi_new (cherokee_handler_t **hdl, void *cnt, cherokee_module_props_t *props) { CHEROKEE_NEW_STRUCT (n, handler_uwsgi); - + /* Init the base class */ cherokee_handler_cgi_base_init ( HDL_CGI_BASE(n), cnt, - PLUGIN_INFO_HANDLER_PTR(uwsgi), + PLUGIN_INFO_HANDLER_PTR(uwsgi), HANDLER_PROPS(props), add_env_pair, read_from_uwsgi); @@ -187,11 +220,11 @@ cherokee_handler_uwsgi_new (cherokee_handler_t **hdl, void *cnt, cherokee_module /* Return the object */ *hdl = HANDLER(n); - return ret_ok; + return ret_ok; } -ret_t +ret_t cherokee_handler_uwsgi_free (cherokee_handler_uwsgi_t *hdl) { /* Free the rest of the handler CGI memory @@ -210,14 +243,18 @@ cherokee_handler_uwsgi_free (cherokee_handler_uwsgi_t *hdl) static ret_t -uwsgi_fix_packet (cherokee_buffer_t *buf) +uwsgi_fix_packet (cherokee_buffer_t *buf, uint8_t modifier1, uint8_t modifier2) { uwsgi_header uh; - uh.arg1 = 0 ; - uh.arg2 = 0 ; - uh.env_size = (unsigned short) buf->len ; + uh.modifier1 = modifier1 ; + uh.modifier2 = modifier2 ; +#if BYTE_ORDER == BIG_ENDIAN + uh.env_size = uwsgi_swap16((uint16_t) buf->len) ; +#else + uh.env_size = (uint16_t) buf->len ; +#endif /* TODO: check endianess */ @@ -231,22 +268,27 @@ uwsgi_fix_packet (cherokee_buffer_t *buf) static ret_t build_header (cherokee_handler_uwsgi_t *hdl) { + + cherokee_handler_uwsgi_props_t *props = HANDLER_UWSGI_PROPS(hdl); cuint_t len; char tmp[64]; - len = snprintf (tmp, sizeof(tmp), FMT_OFFSET, (CST_OFFSET)hdl->post_len); + if (props->pass_request_body == true && props->pass_wsgi_vars == true) { + len = snprintf (tmp, sizeof(tmp), FMT_OFFSET, (CST_OFFSET)hdl->post_len); + add_env_pair(HDL_CGI_BASE(hdl), "CONTENT_LENGTH", 14, tmp, len); + } - add_env_pair(HDL_CGI_BASE(hdl), "CONTENT_LENGTH", 14, tmp, len); + if (props->pass_wsgi_vars == true) { + cherokee_handler_cgi_base_build_envp (HDL_CGI_BASE(hdl), HANDLER_CONN(hdl)); + } - cherokee_handler_cgi_base_build_envp (HDL_CGI_BASE(hdl), HANDLER_CONN(hdl)); - - return uwsgi_fix_packet (&hdl->header); + return uwsgi_fix_packet (&hdl->header, props->modifier1, props->modifier2); } -static ret_t +static ret_t connect_to_server (cherokee_handler_uwsgi_t *hdl) { ret_t ret; @@ -284,14 +326,14 @@ send_header (cherokee_handler_uwsgi_t *hdl) ret_t ret; size_t written = 0; cherokee_connection_t *conn = HANDLER_CONN(hdl); - + ret = cherokee_socket_bufwrite (&hdl->socket, &hdl->header, &written); if (ret != ret_ok) { conn->error_code = http_bad_gateway; return ret; } -#if 0 +#if 0 cherokee_buffer_print_debug (&hdl->header, -1); #endif cherokee_buffer_move_to_begin (&hdl->header, written); @@ -300,7 +342,7 @@ send_header (cherokee_handler_uwsgi_t *hdl) if (! cherokee_buffer_is_empty (&hdl->header)) return ret_eagain; - + return ret_ok; } @@ -312,9 +354,9 @@ send_post (cherokee_handler_uwsgi_t *hdl) int e_fd = -1; int mode = 0; cherokee_connection_t *conn = HANDLER_CONN(hdl); - + ret = cherokee_post_walk_to_fd (&conn->post, hdl->socket.socket, &e_fd, &mode); - + switch (ret) { case ret_ok: break; @@ -331,24 +373,25 @@ send_post (cherokee_handler_uwsgi_t *hdl) } -ret_t +ret_t cherokee_handler_uwsgi_init (cherokee_handler_uwsgi_t *hdl) { ret_t ret; cherokee_connection_t *conn = HANDLER_CONN(hdl); + cherokee_handler_uwsgi_props_t *props = HANDLER_UWSGI_PROPS(hdl); switch (HDL_CGI_BASE(hdl)->init_phase) { case hcgi_phase_build_headers: TRACE (ENTRIES, "Init: %s\n", "begins"); - /* Extracts PATH_INFO and filename from request uri + /* Extracts PATH_INFO and filename from request uri */ ret = cherokee_handler_cgi_base_extract_path (HDL_CGI_BASE(hdl), false); if (unlikely (ret < ret_ok)) { conn->error_code = http_internal_error; return ret_error; } - + /* Prepare Post */ if (! cherokee_post_is_empty (&conn->post)) { @@ -369,7 +412,7 @@ cherokee_handler_uwsgi_init (cherokee_handler_uwsgi_t *hdl) case hcgi_phase_connect: TRACE (ENTRIES, "Init: %s\n", "connect"); - /* Connect + /* Connect */ ret = connect_to_server (hdl); switch (ret) { @@ -384,7 +427,7 @@ cherokee_handler_uwsgi_init (cherokee_handler_uwsgi_t *hdl) conn->error_code = http_service_unavailable; return ret_error; } - + HDL_CGI_BASE(hdl)->init_phase = hcgi_phase_send_headers; case hcgi_phase_send_headers: @@ -393,7 +436,7 @@ cherokee_handler_uwsgi_init (cherokee_handler_uwsgi_t *hdl) /* Send the header */ ret = send_header (hdl); - if (ret != ret_ok) + if (ret != ret_ok) return ret; HDL_CGI_BASE(hdl)->init_phase = hcgi_phase_send_post; @@ -401,7 +444,7 @@ cherokee_handler_uwsgi_init (cherokee_handler_uwsgi_t *hdl) case hcgi_phase_send_post: /* Send the Post */ - if (hdl->post_len > 0) { + if (hdl->post_len > 0 && props->pass_request_body == true) { return send_post (hdl); } break; diff --git a/cherokee/handler_uwsgi.h b/cherokee/handler_uwsgi.h index a666ec7b..2283c027 100644 --- a/cherokee/handler_uwsgi.h +++ b/cherokee/handler_uwsgi.h @@ -20,7 +20,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * 02110-1301, USA. - */ + */ #ifndef CHEROKEE_HANDLER_UWSGI_H #define CHEROKEE_HANDLER_UWSGI_H @@ -35,15 +35,19 @@ #include "balancer.h" typedef struct __attribute__((packed)) { - unsigned char arg1; - unsigned short env_size; - unsigned char arg2; + uint8_t modifier1; + uint16_t env_size; + uint8_t modifier2; } uwsgi_header ; typedef struct { cherokee_handler_cgi_base_t base; cherokee_balancer_t *balancer; + uint8_t modifier1; + uint8_t modifier2; + cherokee_boolean_t pass_wsgi_vars; + cherokee_boolean_t pass_request_body; } cherokee_handler_uwsgi_props_t; @@ -60,7 +64,7 @@ typedef struct { #define PROP_UWSGI(x) ((cherokee_handler_uwsgi_props_t *)(x)) #define HANDLER_UWSGI_PROPS(x) (PROP_UWSGI(MODULE(x)->props)) - + /* Library init function */ void PLUGIN_INIT_NAME(uwsgi) (cherokee_plugin_loader_t *loader); diff --git a/uwsgi.c b/uwsgi.c index f0da0d68..af6883f1 100644 --- a/uwsgi.c +++ b/uwsgi.c @@ -1413,7 +1413,6 @@ int main(int argc, char *argv[], char *envp[]) { continue; } - if (wsgi_req.modifier == UWSGI_MODIFIER_FASTFUNC) { zero = PyList_GetItem(uwsgi_fastfuncslist, wsgi_req.modifier_arg) ; if (zero) { diff --git a/uwsgi.h b/uwsgi.h index 5a8e59fd..f0377685 100644 --- a/uwsgi.h +++ b/uwsgi.h @@ -103,9 +103,9 @@ struct __attribute__((packed)) uwsgi_worker { }; struct __attribute__((packed)) wsgi_request { - unsigned char modifier; - unsigned short size ; - unsigned char modifier_arg; + uint8_t modifier; + uint16_t size ; + uint8_t modifier_arg; // temporary attr #ifndef ROCK_SOLID int app_id ;