diff --git a/plugins/psgi/psgi_response.c b/plugins/psgi/psgi_response.c index 29c5ee0c..aaeac897 100644 --- a/plugins/psgi/psgi_response.c +++ b/plugins/psgi/psgi_response.c @@ -2,52 +2,7 @@ extern struct uwsgi_server uwsgi; -/* statistically ordered */ -struct http_status_codes hsc[] = { - {"200", "OK"}, - {"302", "Found"}, - {"404", "Not Found"}, - {"500", "Internal Server Error"}, - {"301", "Moved Permanently"}, - {"304", "Not Modified"}, - {"303", "See Other"}, - {"403", "Forbidden"}, - {"307", "Temporary Redirect"}, - {"401", "Unauthorized"}, - {"400", "Bad Request"}, - {"405", "Method Not Allowed"}, - {"408", "Request Timeout"}, - - {"100", "Continue"}, - {"101", "Switching Protocols"}, - {"201", "Created"}, - {"202", "Accepted"}, - {"203", "Non-Authoritative Information"}, - {"204", "No Content"}, - {"205", "Reset Content"}, - {"206", "Partial Content"}, - {"300", "Multiple Choices"}, - {"305", "Use Proxy"}, - {"402", "Payment Required"}, - {"406", "Not Acceptable"}, - {"407", "Proxy Authentication Required"}, - {"409", "Conflict"}, - {"410", "Gone"}, - {"411", "Length Required"}, - {"412", "Precondition Failed"}, - {"413", "Request Entity Too Large"}, - {"414", "Request-URI Too Long"}, - {"415", "Unsupported Media Type"}, - {"416", "Requested Range Not Satisfiable"}, - {"417", "Expectation Failed"}, - {"501", "Not Implemented"}, - {"502", "Bad Gateway"}, - {"503", "Service Unavailable"}, - {"504", "Gateway Timeout"}, - {"505", "HTTP Version Not Supported"}, - { "", NULL }, -}; - +extern struct http_status_codes hsc[]; int psgi_response(struct wsgi_request *wsgi_req, PerlInterpreter *my_perl, AV *response) { diff --git a/plugins/python/pump_subhandler.c b/plugins/python/pump_subhandler.c index 31ba1ba1..87281a5f 100644 --- a/plugins/python/pump_subhandler.c +++ b/plugins/python/pump_subhandler.c @@ -4,6 +4,10 @@ extern struct uwsgi_server uwsgi; extern struct uwsgi_python up; extern PyTypeObject uwsgi_InputType; + +extern struct http_status_codes hsc[]; + + void *uwsgi_request_subhandler_pump(struct wsgi_request *wsgi_req, struct uwsgi_app *wi) { PyObject *zero; @@ -176,6 +180,9 @@ int uwsgi_response_subhandler_pump(struct wsgi_request *wsgi_req) { PyObject *pychunk; ssize_t wsize; + struct http_status_codes *http_sc; + char sc[4]; + UWSGI_GET_GIL // ok its a yield @@ -185,18 +192,88 @@ int uwsgi_response_subhandler_pump(struct wsgi_request *wsgi_req) { PyObject *status = PyDict_GetItemString((PyObject *)wsgi_req->async_result, "status"); if (!status) { - uwsgi_log("invalid Pump response.\n"); + uwsgi_log("invalid Pump response (status code).\n"); goto clear; } PyObject *headers = PyDict_GetItemString((PyObject *)wsgi_req->async_result, "headers"); if (!headers) { - uwsgi_log("invalid Pump response.\n"); + uwsgi_log("invalid Pump response (headers).\n"); goto clear; } wsgi_req->async_placeholder = PyDict_GetItemString((PyObject *)wsgi_req->async_result, "body"); + if (!wsgi_req->async_placeholder) { + uwsgi_log("invalid Pump response (body).\n"); + goto clear; + } + + // get the status code + if (!PyInt_Check(status)) { + uwsgi_log("invalid Pump response (status code).\n"); + goto clear; + } + + if (uwsgi_num2str2n(PyInt_AsLong(status), sc, 4) != 3) { + uwsgi_log("invalid Pump response (status code).\n"); + goto clear; + } + + int found = 0; + for (http_sc = hsc; http_sc->message != NULL; http_sc++) { + if (http_sc->key[0] == sc[0] && http_sc->key[1] == sc[1] && http_sc->key[2] == sc[2]) { + wsgi_req->hvec[4].iov_base = (char *) http_sc->message; + wsgi_req->hvec[4].iov_len = http_sc->message_size; + found = 1; + break; + } + } + + if (!found) { + uwsgi_log("invalid Pump response (status code).\n"); + goto clear; + } + + wsgi_req->hvec[0].iov_base = wsgi_req->protocol; + wsgi_req->hvec[0].iov_len = wsgi_req->protocol_len; + wsgi_req->hvec[1].iov_base = " "; + wsgi_req->hvec[1].iov_len = 1; + wsgi_req->hvec[2].iov_base = sc; + wsgi_req->hvec[2].iov_len = 3; + wsgi_req->hvec[3].iov_base = " "; + wsgi_req->hvec[3].iov_len = 1; + wsgi_req->hvec[5].iov_base = "\r\n"; + wsgi_req->hvec[5].iov_len = 2; + + UWSGI_RELEASE_GIL + wsize = wsgi_req->socket->proto_writev_header(wsgi_req, wsgi_req->hvec, 6); + UWSGI_GET_GIL + if (wsize < 0) { + uwsgi_error("writev()"); + } + wsgi_req->headers_size += wsize; + + PyObject *hhkey, *hhvalue; + Py_ssize_t hhpos = 0; + while (PyDict_Next(headers, &hhpos, &hhkey, &hhvalue)) { + if (!PyString_Check(hhkey)) continue; + + wsgi_req->hvec[0].iov_base = PyString_AsString(hhkey); + wsgi_req->hvec[0].iov_len = PyString_Size(hhkey); + + wsgi_req->hvec[1].iov_base = ": "; + wsgi_req->hvec[1].iov_len = 2; + + wsgi_req->hvec[2].iov_base = "\r\n"; + wsgi_req->hvec[2].iov_len = 2; + if (PyList_Check(hhvalue)) { + } + else if (PyString_Check(hhvalue)) { + } + } + + wsgi_req->socket->proto_write(wsgi_req, "\r\n", 2); Py_INCREF(wsgi_req->async_placeholder); if (PyString_Check((PyObject *)wsgi_req->async_placeholder)) { diff --git a/plugins/python/python_plugin.c b/plugins/python/python_plugin.c index fb52444e..27c8d2d1 100644 --- a/plugins/python/python_plugin.c +++ b/plugins/python/python_plugin.c @@ -3,6 +3,8 @@ extern struct uwsgi_server uwsgi; struct uwsgi_python up; +extern struct http_status_codes hsc[]; + #include extern PyTypeObject uwsgi_InputType; @@ -810,6 +812,8 @@ char *uwsgi_pythonize(char *orig) { void uwsgi_python_init_apps() { + struct http_status_codes *http_sc; + if (uwsgi.async > 1) { up.current_recursion_depth = uwsgi_malloc(sizeof(int)*uwsgi.async); @@ -918,6 +922,10 @@ void uwsgi_python_init_apps() { } if (up.pump != NULL) { init_uwsgi_app(LOADER_UWSGI, up.pump, uwsgi.wsgi_req, up.main_thread, PYTHON_APP_TYPE_PUMP); + // filling http status codes + for (http_sc = hsc; http_sc->message != NULL; http_sc++) { + http_sc->message_size = (int) strlen(http_sc->message); + } } if (up.wsgi_lite != NULL) { init_uwsgi_app(LOADER_UWSGI, up.wsgi_lite, uwsgi.wsgi_req, up.main_thread, PYTHON_APP_TYPE_WSGI_LITE); diff --git a/plugins/rack/rack_plugin.c b/plugins/rack/rack_plugin.c index 5338894a..19c97f11 100644 --- a/plugins/rack/rack_plugin.c +++ b/plugins/rack/rack_plugin.c @@ -32,53 +32,7 @@ void uwsgi_ruby_exception(void) { -/* statistically ordered */ -static struct http_status_codes hsc[] = { - - {"200", "OK"}, - {"302", "Found"}, - {"404", "Not Found"}, - {"500", "Internal Server Error"}, - {"301", "Moved Permanently"}, - {"304", "Not Modified"}, - {"303", "See Other"}, - {"403", "Forbidden"}, - {"307", "Temporary Redirect"}, - {"401", "Unauthorized"}, - {"400", "Bad Request"}, - {"405", "Method Not Allowed"}, - {"408", "Request Timeout"}, - - {"100", "Continue"}, - {"101", "Switching Protocols"}, - {"201", "Created"}, - {"202", "Accepted"}, - {"203", "Non-Authoritative Information"}, - {"204", "No Content"}, - {"205", "Reset Content"}, - {"206", "Partial Content"}, - {"300", "Multiple Choices"}, - {"305", "Use Proxy"}, - {"402", "Payment Required"}, - {"406", "Not Acceptable"}, - {"407", "Proxy Authentication Required"}, - {"409", "Conflict"}, - {"410", "Gone"}, - {"411", "Length Required"}, - {"412", "Precondition Failed"}, - {"413", "Request Entity Too Large"}, - {"414", "Request-URI Too Long"}, - {"415", "Unsupported Media Type"}, - {"416", "Requested Range Not Satisfiable"}, - {"417", "Expectation Failed"}, - {"501", "Not Implemented"}, - {"502", "Bad Gateway"}, - {"503", "Service Unavailable"}, - {"504", "Gateway Timeout"}, - {"505", "HTTP Version Not Supported"}, - { "", NULL }, -}; - +extern struct http_status_codes hsc[]; VALUE rb_uwsgi_io_new(VALUE class, VALUE wr) { @@ -680,7 +634,21 @@ int uwsgi_rack_request(struct wsgi_request *wsgi_req) { rb_ary_store(rbv, 1, INT2NUM(1)); rb_hash_aset(env, rb_str_new2("rack.version"), rbv); - rb_hash_aset(env, rb_str_new2("rack.url_scheme"), rb_str_new2("http")); + if (wsgi_req->scheme_len > 0) { + rb_hash_aset(env, rb_str_new2("rack.url_scheme"), rb_str_new(wsgi_req->scheme, wsgi_req->scheme_len)); + } + else if (wsgi_req->https_len > 0) { + if (!strncasecmp(wsgi_req->https, "on", 2) || wsgi_req->https[0] == '1') { + rb_hash_aset(env, rb_str_new2("rack.url_scheme"), rb_str_new2("https")); + } + else { + rb_hash_aset(env, rb_str_new2("rack.url_scheme"), rb_str_new2("http")); + } + } + else { + rb_hash_aset(env, rb_str_new2("rack.url_scheme"), rb_str_new2("http")); + } + rb_hash_aset(env, rb_str_new2("rack.multithread"), Qfalse); rb_hash_aset(env, rb_str_new2("rack.multiprocess"), Qtrue); diff --git a/utils.c b/utils.c index e4e2f17d..647e9160 100644 --- a/utils.c +++ b/utils.c @@ -3,6 +3,54 @@ extern struct uwsgi_server uwsgi; +/* statistically ordered */ +struct http_status_codes hsc[] = { + {"200", "OK"}, + {"302", "Found"}, + {"404", "Not Found"}, + {"500", "Internal Server Error"}, + {"301", "Moved Permanently"}, + {"304", "Not Modified"}, + {"303", "See Other"}, + {"403", "Forbidden"}, + {"307", "Temporary Redirect"}, + {"401", "Unauthorized"}, + {"400", "Bad Request"}, + {"405", "Method Not Allowed"}, + {"408", "Request Timeout"}, + + {"100", "Continue"}, + {"101", "Switching Protocols"}, + {"201", "Created"}, + {"202", "Accepted"}, + {"203", "Non-Authoritative Information"}, + {"204", "No Content"}, + {"205", "Reset Content"}, + {"206", "Partial Content"}, + {"300", "Multiple Choices"}, + {"305", "Use Proxy"}, + {"402", "Payment Required"}, + {"406", "Not Acceptable"}, + {"407", "Proxy Authentication Required"}, + {"409", "Conflict"}, + {"410", "Gone"}, + {"411", "Length Required"}, + {"412", "Precondition Failed"}, + {"413", "Request Entity Too Large"}, + {"414", "Request-URI Too Long"}, + {"415", "Unsupported Media Type"}, + {"416", "Requested Range Not Satisfiable"}, + {"417", "Expectation Failed"}, + {"501", "Not Implemented"}, + {"502", "Bad Gateway"}, + {"503", "Service Unavailable"}, + {"504", "Gateway Timeout"}, + {"505", "HTTP Version Not Supported"}, + { "", NULL }, +}; + + + #ifdef __BIG_ENDIAN__ uint16_t uwsgi_swap16(uint16_t x) { return (uint16_t) ((x & 0xff) << 8 | (x & 0xff00) >> 8); @@ -2110,6 +2158,10 @@ int uwsgi_num2str2(int num, char *ptr) { return snprintf(ptr, 11, "%d", num); } +int uwsgi_num2str2n(int num, char *ptr, int size) { + return snprintf(ptr, size, "%d", num); +} + int is_unix(char *socket_name, int len) { int i; for (i = 0; i < len; i++) { diff --git a/uwsgi.c b/uwsgi.c index 1dc998d4..c06224bc 100644 --- a/uwsgi.c +++ b/uwsgi.c @@ -1869,7 +1869,9 @@ skipzero: uwsgi_sock->proto_close = uwsgi_proto_base_close; } else if (requested_protocol && (!strcmp("fastcgi", requested_protocol) || !strcmp("fcgi", requested_protocol))) { - uwsgi.shared->options[UWSGI_OPTION_CGI_MODE] = 1; + if (!strcmp(uwsgi.protocol, "fastcgi") || !strcmp(uwsgi.protocol, "fcgi")) { + uwsgi.shared->options[UWSGI_OPTION_CGI_MODE] = 1; + } uwsgi_sock->proto = uwsgi_proto_fastcgi_parser; uwsgi_sock->proto_accept = uwsgi_proto_base_accept; uwsgi_sock->proto_write = uwsgi_proto_fastcgi_write; diff --git a/uwsgi.h b/uwsgi.h index 13db10a1..441361b6 100644 --- a/uwsgi.h +++ b/uwsgi.h @@ -2117,6 +2117,7 @@ void uwsgi_chown(char *, char *); char *uwsgi_get_binary_path(char *); char *uwsgi_lower(char *, size_t); +int uwsgi_num2str2n(int, char *, int); #ifdef __cplusplus }