diff --git a/cherokee/README b/cherokee/README deleted file mode 100644 index c263833f..00000000 --- a/cherokee/README +++ /dev/null @@ -1 +0,0 @@ -the uwsgi handler is included in the official Cherokee distribution diff --git a/lighttpd/mod_uwsgi.c b/lighttpd/mod_uwsgi.c deleted file mode 100644 index d9928759..00000000 --- a/lighttpd/mod_uwsgi.c +++ /dev/null @@ -1,1356 +0,0 @@ -#include "buffer.h" -#include "server.h" -#include "keyvalue.h" -#include "log.h" - -#include "http_chunk.h" -#include "fdevent.h" -#include "connections.h" -#include "response.h" -#include "joblist.h" - -#include "plugin.h" - -#include "inet_ntop_cache.h" -#include "crc32.h" - -#include - -#include -#include -#include -#include -#include -#include -#include - -#include - -#ifdef HAVE_SYS_FILIO_H -# include -#endif - -#include "sys-socket.h" - -#define data_uwsgi data_fastcgi -#define data_uwsgi_init data_fastcgi_init - -#ifdef __linux__ -#include -#elif __sun__ -#elif __APPLE__ -#include -#else -#include -#endif - - -#ifdef __BIG_ENDIAN__ -static uint16_t uwsgi_swap16(uint16_t x) { - return (uint16_t) ((x & 0xff) << 8 | (x & 0xff00) >> 8); -} -#endif - - -/** - * - * the uwsgi module is based on the proxy module - * - * 30.12.2009 Roberto De Ioris first public release - * - */ - -typedef struct __attribute__((packed)) { - uint8_t modifier1; - uint16_t pktsize; - uint8_t modifier2; -} uwsgi_header; - -typedef struct { - array *extensions; - unsigned short debug; -} plugin_config; - -typedef struct { - PLUGIN_DATA; - - buffer *parse_response; - - plugin_config **config_storage; - - plugin_config conf; -} plugin_data; - -typedef enum { - UWSGI_STATE_INIT, - UWSGI_STATE_CONNECT, - UWSGI_STATE_PREPARE_WRITE, - UWSGI_STATE_WRITE, - UWSGI_STATE_READ, - UWSGI_STATE_ERROR -} uwsgi_connection_state_t; - -typedef struct { - uwsgi_connection_state_t state; - time_t state_timestamp; - - data_uwsgi *host; - - buffer *response; - buffer *response_header; - - chunkqueue *wb; - - int fd; /* fd to the uwsgi process */ - int fde_ndx; /* index into the fd-event buffer */ - - size_t path_info_offset; /* start of path_info in uri.path */ - - connection *remote_conn; /* dump pointer */ - plugin_data *plugin_data; /* dump pointer */ -} handler_ctx; - - -static handler_t uwsgi_handle_fdevent(void *s, void *ctx, int revents); - -static handler_ctx * handler_ctx_init() { - handler_ctx * hctx; - - - hctx = calloc(1, sizeof(*hctx)); - - hctx->state = UWSGI_STATE_INIT; - hctx->host = NULL; - - hctx->response = buffer_init(); - hctx->response_header = buffer_init(); - - hctx->wb = chunkqueue_init(); - - hctx->fd = -1; - hctx->fde_ndx = -1; - - - return hctx; -} - -static void handler_ctx_free(handler_ctx *hctx) { - buffer_free(hctx->response); - buffer_free(hctx->response_header); - chunkqueue_free(hctx->wb); - - free(hctx); -} - -INIT_FUNC(mod_uwsgi_init) { - plugin_data *p; - - p = calloc(1, sizeof(*p)); - - p->parse_response = buffer_init(); - - return p; -} - - -FREE_FUNC(mod_uwsgi_free) { - plugin_data *p = p_d; - - UNUSED(srv); - - buffer_free(p->parse_response); - - if (p->config_storage) { - size_t i; - for (i = 0; i < srv->config_context->used; i++) { - plugin_config *s = p->config_storage[i]; - - if (s) { - - array_free(s->extensions); - - free(s); - } - } - free(p->config_storage); - } - - free(p); - - return HANDLER_GO_ON; -} - -SETDEFAULTS_FUNC(mod_uwsgi_set_defaults) { - plugin_data *p = p_d; - data_unset *du; - size_t i = 0; - - config_values_t cv[] = { - { "uwsgi.server", NULL, T_CONFIG_LOCAL, T_CONFIG_SCOPE_CONNECTION }, /* 0 */ - { "uwsgi.debug", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION }, /* 1 */ - { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET } - }; - - p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *)); - - for (i = 0; i < srv->config_context->used; i++) { - plugin_config *s; - array *ca; - - s = malloc(sizeof(plugin_config)); - s->extensions = array_init(); - s->debug = 0; - - cv[0].destination = s->extensions; - cv[1].destination = &(s->debug); - - - p->config_storage[i] = s; - ca = ((data_config *)srv->config_context->data[i])->value; - - if (0 != config_insert_values_global(srv, ca, cv)) { - return HANDLER_ERROR; - } - - if (NULL != (du = array_get_element(ca, "uwsgi.server"))) { - size_t j; - data_array *da = (data_array *)du; - - if (du->type != TYPE_ARRAY) { - log_error_write(srv, __FILE__, __LINE__, "sss", - "unexpected type for key: ", "uwsgi.server", "array of strings"); - - return HANDLER_ERROR; - } - - /* - * uwsgi.server = ( "" => ..., - * "" => ... ) - */ - - for (j = 0; j < da->value->used; j++) { - data_array *da_ext = (data_array *)da->value->data[j]; - size_t n; - - if (da_ext->type != TYPE_ARRAY) { - log_error_write(srv, __FILE__, __LINE__, "sssbs", - "unexpected type for key: ", "uwsgi.server", - "[", da->value->data[j]->key, "](string)"); - - return HANDLER_ERROR; - } - - /* - * uwsgi.server = ( "" => - * ( "" => ( ... ), - * "" => ( ... ) - * ), - * "" => ... ) - */ - - for (n = 0; n < da_ext->value->used; n++) { - data_array *da_host = (data_array *)da_ext->value->data[n]; - - data_uwsgi *df; - data_array *dfa; - - config_values_t pcv[] = { - { "host", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 0 */ - { "port", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION }, /* 1 */ - { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET } - }; - - if (da_host->type != TYPE_ARRAY) { - log_error_write(srv, __FILE__, __LINE__, "ssSBS", - "unexpected type for key:", - "uwsgi.server", - "[", da_ext->value->data[n]->key, "](string)"); - - return HANDLER_ERROR; - } - - df = data_uwsgi_init(); - - df->port = 3031; - - buffer_copy_string_buffer(df->key, da_host->key); - - pcv[0].destination = df->host; - pcv[1].destination = &(df->port); - - if (0 != config_insert_values_internal(srv, da_host->value, pcv)) { - return HANDLER_ERROR; - } - - if (buffer_is_empty(df->host)) { - log_error_write(srv, __FILE__, __LINE__, "sbbbs", - "missing key (string):", - da->key, - da_ext->key, - da_host->key, - "host"); - - return HANDLER_ERROR; - } - - /* if extension already exists, take it */ - - if (NULL == (dfa = (data_array *)array_get_element(s->extensions, da_ext->key->ptr))) { - dfa = data_array_init(); - - buffer_copy_string_buffer(dfa->key, da_ext->key); - - array_insert_unique(dfa->value, (data_unset *)df); - array_insert_unique(s->extensions, (data_unset *)dfa); - } else { - array_insert_unique(dfa->value, (data_unset *)df); - } - } - } - } - } - - return HANDLER_GO_ON; -} - -static void uwsgi_connection_close(server *srv, handler_ctx *hctx) { - plugin_data *p; - connection *con; - - if (NULL == hctx) return; - - p = hctx->plugin_data; - con = hctx->remote_conn; - - if (hctx->fd != -1) { - fdevent_event_del(srv->ev, &(hctx->fde_ndx), hctx->fd); - fdevent_unregister(srv->ev, hctx->fd); - - close(hctx->fd); - srv->cur_fds--; - } - - handler_ctx_free(hctx); - con->plugin_ctx[p->id] = NULL; -} - -static int uwsgi_establish_connection(server *srv, handler_ctx *hctx) { - struct sockaddr *uwsgi_addr; - struct sockaddr_in uwsgi_addr_in; -#if defined(HAVE_IPV6) && defined(HAVE_INET_PTON) - struct sockaddr_in6 uwsgi_addr_in6; -#endif - socklen_t servlen; - - plugin_data *p = hctx->plugin_data; - data_uwsgi *host= hctx->host; - int uwsgi_fd = hctx->fd; - - -#if defined(HAVE_IPV6) && defined(HAVE_INET_PTON) - if (strstr(host->host->ptr, ":")) { - memset(&uwsgi_addr_in6, 0, sizeof(uwsgi_addr_in6)); - uwsgi_addr_in6.sin6_family = AF_INET6; - inet_pton(AF_INET6, host->host->ptr, (char *) &uwsgi_addr_in6.sin6_addr); - uwsgi_addr_in6.sin6_port = htons(host->port); - servlen = sizeof(uwsgi_addr_in6); - uwsgi_addr = (struct sockaddr *) &uwsgi_addr_in6; - } else -#endif - { - memset(&uwsgi_addr_in, 0, sizeof(uwsgi_addr_in)); - uwsgi_addr_in.sin_family = AF_INET; - uwsgi_addr_in.sin_addr.s_addr = inet_addr(host->host->ptr); - uwsgi_addr_in.sin_port = htons(host->port); - servlen = sizeof(uwsgi_addr_in); - uwsgi_addr = (struct sockaddr *) &uwsgi_addr_in; - } - - - if (-1 == connect(uwsgi_fd, uwsgi_addr, servlen)) { - if (errno == EINPROGRESS || errno == EALREADY) { - if (p->conf.debug) { - log_error_write(srv, __FILE__, __LINE__, "sd", - "connect delayed:", uwsgi_fd); - } - - return 1; - } else { - - log_error_write(srv, __FILE__, __LINE__, "sdsd", - "connect failed:", uwsgi_fd, strerror(errno), errno); - - return -1; - } - } - if (p->conf.debug) { - log_error_write(srv, __FILE__, __LINE__, "sd", - "connect succeeded: ", uwsgi_fd); - } - - return 0; -} - -static void uwsgi_add_var(buffer *b, char * key, uint16_t keylen, char *val, uint16_t vallen) { - -#ifdef __BIG_ENDIAN__ - uint16_t uwlen; - - uwlen = uwsgi_swap16(keylen); - buffer_append_memory(b, (char *) &uwlen, 2); buffer_append_memory(b, key, keylen); - uwlen = uwsgi_swap16(vallen); - buffer_append_memory(b, (char *) &uwlen, 2); buffer_append_memory(b, val, vallen); -#else - buffer_append_memory(b, (char *) &keylen, 2); buffer_append_memory(b, key, keylen); - buffer_append_memory(b, (char *) &vallen, 2); buffer_append_memory(b, val, vallen); -#endif - - -} - -static int uwsgi_create_env(server *srv, handler_ctx *hctx) { - size_t i; - - char buf[32]; - uwsgi_header *uh; - const char *s; -#ifdef HAVE_IPV6 - char b2[INET6_ADDRSTRLEN + 1]; -#endif - - - connection *con = hctx->remote_conn; - server_socket *srv_sock = con->srv_socket; - buffer *b; - - /* build header */ - - b = chunkqueue_get_append_buffer(hctx->wb); - - /* make space for uwsgi header */ - buffer_append_memory(b, "\0\0\0\0", 4); - - /* set WSGI vars */ - s = get_http_method_name(con->request.http_method); - uwsgi_add_var(b, "REQUEST_METHOD", 14, (char *) s, strlen(s)); - - if (!buffer_is_empty(con->uri.query)) { - uwsgi_add_var(b, "QUERY_STRING", 12, con->uri.query->ptr, con->uri.query->used-1); - } else { - uwsgi_add_var(b, "QUERY_STRING", 12, "", 0); - } - - s = get_http_version_name(con->request.http_version); - uwsgi_add_var(b, "SERVER_PROTOCOL", 15, (char *) s, strlen(s)); - - - if (con->server_name->used) { - size_t len = con->server_name->used - 1; - char *colon = strchr(con->server_name->ptr, ':'); - if (colon) len = colon - con->server_name->ptr; - uwsgi_add_var(b, "SERVER_NAME", 11, con->server_name->ptr, len); - - } else { -#ifdef HAVE_IPV6 - s = inet_ntop(srv_sock->addr.plain.sa_family, - srv_sock->addr.plain.sa_family == AF_INET6 ? - (const void *) &(srv_sock->addr.ipv6.sin6_addr) : - (const void *) &(srv_sock->addr.ipv4.sin_addr), - b2, sizeof(b2)-1); -#else - s = inet_ntoa(srv_sock->addr.ipv4.sin_addr); -#endif - uwsgi_add_var(b, "SERVER_NAME", 11, (char *)s, strlen(s)); - } - - LI_ltostr(buf, -#ifdef HAVE_IPV6 - ntohs(srv_sock->addr.plain.sa_family ? srv_sock->addr.ipv6.sin6_port : srv_sock->addr.ipv4.sin_port) -#else - ntohs(srv_sock->addr.ipv4.sin_port) -#endif - ); - - uwsgi_add_var(b, "SERVER_PORT", 11, buf, strlen(buf)); - uwsgi_add_var(b, "REQUEST_URI", 11, con->request.orig_uri->ptr, con->request.orig_uri->used-1); - - LI_ltostr(buf, -#ifdef HAVE_IPV6 - ntohs(con->dst_addr.plain.sa_family ? con->dst_addr.ipv6.sin6_port : con->dst_addr.ipv4.sin_port) -#else - ntohs(con->dst_addr.ipv4.sin_port) -#endif - ); - uwsgi_add_var(b, "REMOTE_PORT", 11, buf, strlen(buf)); - - if (!buffer_is_empty(con->authed_user)) { - uwsgi_add_var(b, "REMOTE_USER", 11, - CONST_BUF_LEN(con->authed_user)); - } - - - - s = inet_ntop_cache_get_ip(srv, &(con->dst_addr)); - uwsgi_add_var(b, "REMOTE_ADDR", 11, (char *)s, strlen(s)); - - if (hctx->path_info_offset > 1) { - uwsgi_add_var(b, "SCRIPT_NAME", 11, con->uri.path->ptr, hctx->path_info_offset); - if (strlen(con->uri.path->ptr + hctx->path_info_offset) > 0) { - uwsgi_add_var(b, "PATH_INFO", 9, con->uri.path->ptr + hctx->path_info_offset, strlen(con->uri.path->ptr + hctx->path_info_offset)); - } - else { - uwsgi_add_var(b, "PATH_INFO", 9, "/", 1); - } - } - else { - uwsgi_add_var(b, "SCRIPT_NAME", 11, "", 0); - uwsgi_add_var(b, "PATH_INFO", 9, con->uri.path->ptr, strlen(con->uri.path->ptr)); - } - - - for (i = 0; i < con->request.headers->used; i++) { - data_string *ds; - ds = (data_string *)con->request.headers->data[i]; - - if (ds->value->used && ds->key->used) { - size_t j; - buffer_reset(srv->tmp_buf); - if (!strcasecmp(ds->key->ptr, "CONTENT-TYPE") || !strcasecmp(ds->key->ptr, "CONTENT-LENGTH")) { - buffer_prepare_append(srv->tmp_buf, ds->key->used + 2); - } - else { - buffer_prepare_append(srv->tmp_buf, ds->key->used + 7); - buffer_append_memory(srv->tmp_buf, "HTTP_", 5); - } - for (j = 0; j < ds->key->used - 1; j++) { - srv->tmp_buf->ptr[srv->tmp_buf->used++] = light_isalpha(ds->key->ptr[j]) ? ds->key->ptr[j] & ~32 : '_'; - } - srv->tmp_buf->ptr[srv->tmp_buf->used++] = '\0'; - uwsgi_add_var(b, srv->tmp_buf->ptr, srv->tmp_buf->used-1, ds->value->ptr, ds->value->used-1); - } - } - - for (i = 0; i < con->environment->used; i++) { - data_string *ds; - ds = (data_string *)con->environment->data[i]; - if (ds->value->used && ds->key->used) { - size_t j; - buffer_reset(srv->tmp_buf); - buffer_prepare_append(srv->tmp_buf, ds->key->used + 2); - for (j = 0; j < ds->key->used - 1; j++) { - srv->tmp_buf->ptr[srv->tmp_buf->used++] = light_isalnum((unsigned char)ds->key->ptr[j]) ? toupper((unsigned char)ds->key->ptr[j]) : '_'; - } - - srv->tmp_buf->ptr[srv->tmp_buf->used++] = '\0'; - uwsgi_add_var(b, srv->tmp_buf->ptr, srv->tmp_buf->used-1, ds->value->ptr, ds->value->used-1); - } - } - - - uh = (uwsgi_header *) b->ptr; - uh->modifier1 = (uint8_t) 0; -#ifdef __BIG_ENDIAN__ - uh->pktsize = uwsgi_swap16((uint16_t) b->used - 4); -#else - uh->pktsize = b->used - 4; -#endif - uh->modifier2 = (uint8_t) 0; - - b->used++; /* fix size */ - - hctx->wb->bytes_in += b->used -1; - /* body */ - - if (con->request.content_length) { - chunkqueue *req_cq = con->request_content_queue; - chunk *req_c; - off_t offset; - - /* something to send ? */ - for (offset = 0, req_c = req_cq->first; offset != req_cq->bytes_in; req_c = req_c->next) { - off_t weWant = req_cq->bytes_in - offset; - off_t weHave = 0; - - /* we announce toWrite octects - * now take all the request_content chunk that we need to fill this request - * */ - - switch (req_c->type) { - case FILE_CHUNK: - weHave = req_c->file.length - req_c->offset; - - if (weHave > weWant) weHave = weWant; - - chunkqueue_append_file(hctx->wb, req_c->file.name, req_c->offset, weHave); - - req_c->offset += weHave; - req_cq->bytes_out += weHave; - - hctx->wb->bytes_in += weHave; - - break; - case MEM_CHUNK: - /* append to the buffer */ - weHave = req_c->mem->used - 1 - req_c->offset; - - if (weHave > weWant) weHave = weWant; - - b = chunkqueue_get_append_buffer(hctx->wb); - buffer_append_memory(b, req_c->mem->ptr + req_c->offset, weHave); - b->used++; /* add virtual \0 */ - - req_c->offset += weHave; - req_cq->bytes_out += weHave; - - hctx->wb->bytes_in += weHave; - - break; - default: - break; - } - - offset += weHave; - } - - } - - return 0; -} - -static int uwsgi_set_state(server *srv, handler_ctx *hctx, uwsgi_connection_state_t state) { - hctx->state = state; - hctx->state_timestamp = srv->cur_ts; - - return 0; -} - - -static int uwsgi_response_parse(server *srv, connection *con, plugin_data *p, buffer *in) { - char *s, *ns; - int http_response_status = -1; - - UNUSED(srv); - - /* \r\n -> \0\0 */ - - buffer_copy_string_buffer(p->parse_response, in); - - for (s = p->parse_response->ptr; NULL != (ns = strstr(s, "\r\n")); s = ns + 2) { - char *key, *value; - int key_len; - data_string *ds; - int copy_header; - - ns[0] = '\0'; - ns[1] = '\0'; - - if (-1 == http_response_status) { - /* The first line of a Response message is the Status-Line */ - - for (key=s; *key && *key != ' '; key++); - - if (*key) { - http_response_status = (int) strtol(key, NULL, 10); - if (http_response_status <= 0) http_response_status = 502; - } else { - http_response_status = 502; - } - - con->http_status = http_response_status; - con->parsed_response |= HTTP_STATUS; - continue; - } - - if (NULL == (value = strchr(s, ':'))) { - /* now we expect: ": \n" */ - - continue; - } - - key = s; - key_len = value - key; - - value++; - /* strip WS */ - while (*value == ' ' || *value == '\t') value++; - - copy_header = 1; - - switch(key_len) { - case 4: - if (0 == strncasecmp(key, "Date", key_len)) { - con->parsed_response |= HTTP_DATE; - } - break; - case 8: - if (0 == strncasecmp(key, "Location", key_len)) { - con->parsed_response |= HTTP_LOCATION; - } - break; - case 10: - if (0 == strncasecmp(key, "Connection", key_len)) { - copy_header = 0; - } - break; - case 14: - if (0 == strncasecmp(key, "Content-Length", key_len)) { - con->response.content_length = strtol(value, NULL, 10); - con->parsed_response |= HTTP_CONTENT_LENGTH; - } - break; - default: - break; - } - - if (copy_header) { - if (NULL == (ds = (data_string *)array_get_unused_element(con->response.headers, TYPE_STRING))) { - ds = data_response_init(); - } - buffer_copy_string_len(ds->key, key, key_len); - buffer_copy_string(ds->value, value); - - array_insert_unique(con->response.headers, (data_unset *)ds); - } - } - - return 0; -} - - -static int uwsgi_demux_response(server *srv, handler_ctx *hctx) { - int fin = 0; - int b; - ssize_t r; - - plugin_data *p = hctx->plugin_data; - connection *con = hctx->remote_conn; - int uwsgi_fd = hctx->fd; - - /* check how much we have to read */ - if (ioctl(hctx->fd, FIONREAD, &b)) { - log_error_write(srv, __FILE__, __LINE__, "sd", - "ioctl failed: ", - uwsgi_fd); - return -1; - } - - - if (p->conf.debug) { - log_error_write(srv, __FILE__, __LINE__, "sd", - "uwsgi - have to read:", b); - } - - if (b > 0) { - if (hctx->response->used == 0) { - /* avoid too small buffer */ - buffer_prepare_append(hctx->response, b + 1); - hctx->response->used = 1; - } else { - buffer_prepare_append(hctx->response, b); - } - - if (-1 == (r = read(hctx->fd, hctx->response->ptr + hctx->response->used - 1, b))) { - if (errno == EAGAIN) return 0; - log_error_write(srv, __FILE__, __LINE__, "sds", - "unexpected end-of-file (perhaps the uwsgi process died):", - uwsgi_fd, strerror(errno)); - return -1; - } - - /* this should be catched by the b > 0 above */ - assert(r); - - hctx->response->used += r; - hctx->response->ptr[hctx->response->used - 1] = '\0'; - -#if 0 - log_error_write(srv, __FILE__, __LINE__, "sdsbs", - "demux: Response buffer len", hctx->response->used, ":", hctx->response, ":"); -#endif - - if (0 == con->got_response) { - con->got_response = 1; - buffer_prepare_copy(hctx->response_header, 128); - } - - if (0 == con->file_started) { - char *c; - - /* search for the \r\n\r\n in the string */ - if (NULL != (c = buffer_search_string_len(hctx->response, "\r\n\r\n", 4))) { - size_t hlen = c - hctx->response->ptr + 4; - size_t blen = hctx->response->used - hlen - 1; - /* found */ - - buffer_append_string_len(hctx->response_header, hctx->response->ptr, c - hctx->response->ptr + 4); -#if 0 - log_error_write(srv, __FILE__, __LINE__, "sb", "Header:", hctx->response_header); -#endif - /* parse the response header */ - uwsgi_response_parse(srv, con, p, hctx->response_header); - - /* enable chunked-transfer-encoding */ - if (con->request.http_version == HTTP_VERSION_1_1 && - !(con->parsed_response & HTTP_CONTENT_LENGTH)) { - con->response.transfer_encoding = HTTP_TRANSFER_ENCODING_CHUNKED; - } - - con->file_started = 1; - if (blen) { - http_chunk_append_mem(srv, con, c + 4, blen + 1); - joblist_append(srv, con); - } - hctx->response->used = 0; - } - } else { - http_chunk_append_mem(srv, con, hctx->response->ptr, hctx->response->used); - joblist_append(srv, con); - hctx->response->used = 0; - } - - } else { - /* reading from upstream done */ - con->file_finished = 1; - - http_chunk_append_mem(srv, con, NULL, 0); - joblist_append(srv, con); - - fin = 1; - } - - return fin; -} - - -static handler_t uwsgi_write_request(server *srv, handler_ctx *hctx) { - data_uwsgi *host= hctx->host; - plugin_data *p = hctx->plugin_data; - connection *con = hctx->remote_conn; - - int ret; - - if (!host || - (!host->host->used || !host->port)) return -1; - - switch(hctx->state) { - case UWSGI_STATE_INIT: -#if defined(HAVE_IPV6) && defined(HAVE_INET_PTON) - if (strstr(host->host->ptr,":")) { - if (-1 == (hctx->fd = socket(AF_INET6, SOCK_STREAM, 0))) { - log_error_write(srv, __FILE__, __LINE__, "ss", "socket failed: ", strerror(errno)); - return HANDLER_ERROR; - } - } else -#endif - { - if (-1 == (hctx->fd = socket(AF_INET, SOCK_STREAM, 0))) { - log_error_write(srv, __FILE__, __LINE__, "ss", "socket failed: ", strerror(errno)); - return HANDLER_ERROR; - } - } - hctx->fde_ndx = -1; - - srv->cur_fds++; - - fdevent_register(srv->ev, hctx->fd, uwsgi_handle_fdevent, hctx); - - if (-1 == fdevent_fcntl_set(srv->ev, hctx->fd)) { - log_error_write(srv, __FILE__, __LINE__, "ss", "fcntl failed: ", strerror(errno)); - - return HANDLER_ERROR; - } - - /* fall through */ - - case UWSGI_STATE_CONNECT: - /* try to finish the connect() */ - if (hctx->state == UWSGI_STATE_INIT) { - /* first round */ - switch (uwsgi_establish_connection(srv, hctx)) { - case 1: - uwsgi_set_state(srv, hctx, UWSGI_STATE_CONNECT); - - /* connection is in progress, wait for an event and call getsockopt() below */ - - fdevent_event_add(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_OUT); - - return HANDLER_WAIT_FOR_EVENT; - case -1: - /* if ECONNREFUSED choose another connection -> FIXME */ - hctx->fde_ndx = -1; - - return HANDLER_ERROR; - default: - /* everything is ok, go on */ - break; - } - } else { - int socket_error; - socklen_t socket_error_len = sizeof(socket_error); - - /* we don't need it anymore */ - fdevent_event_del(srv->ev, &(hctx->fde_ndx), hctx->fd); - - /* try to finish the connect() */ - if (0 != getsockopt(hctx->fd, SOL_SOCKET, SO_ERROR, &socket_error, &socket_error_len)) { - log_error_write(srv, __FILE__, __LINE__, "ss", - "getsockopt failed:", strerror(errno)); - - return HANDLER_ERROR; - } - if (socket_error != 0) { - log_error_write(srv, __FILE__, __LINE__, "ss", - "establishing connection failed:", strerror(socket_error), - "port:", hctx->host->port); - - return HANDLER_ERROR; - } - if (p->conf.debug) { - log_error_write(srv, __FILE__, __LINE__, "s", "uwsgi - connect - delayed success"); - } - } - - uwsgi_set_state(srv, hctx, UWSGI_STATE_PREPARE_WRITE); - /* fall through */ - case UWSGI_STATE_PREPARE_WRITE: - uwsgi_create_env(srv, hctx); - - uwsgi_set_state(srv, hctx, UWSGI_STATE_WRITE); - - /* fall through */ - case UWSGI_STATE_WRITE:; - ret = srv->network_backend_write(srv, con, hctx->fd, hctx->wb); - - chunkqueue_remove_finished_chunks(hctx->wb); - - if (-1 == ret) { /* error on our side */ - log_error_write(srv, __FILE__, __LINE__, "ssd", "write failed:", strerror(errno), errno); - - return HANDLER_WAIT_FOR_EVENT; - } else if (-2 == ret) { /* remote close */ - log_error_write(srv, __FILE__, __LINE__, "ssd", "write failed, remote connection close:", strerror(errno), errno); - - return HANDLER_WAIT_FOR_EVENT; - } - - if (hctx->wb->bytes_out == hctx->wb->bytes_in) { - uwsgi_set_state(srv, hctx, UWSGI_STATE_READ); - - fdevent_event_del(srv->ev, &(hctx->fde_ndx), hctx->fd); - fdevent_event_add(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_IN); - } else { - fdevent_event_add(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_OUT); - - return HANDLER_WAIT_FOR_EVENT; - } - - return HANDLER_WAIT_FOR_EVENT; - case UWSGI_STATE_READ: - /* waiting for a response */ - return HANDLER_WAIT_FOR_EVENT; - default: - log_error_write(srv, __FILE__, __LINE__, "s", "(debug) unknown state"); - return HANDLER_ERROR; - } - - return HANDLER_GO_ON; -} - -#define PATCH(x) \ - p->conf.x = s->x; -static int mod_uwsgi_patch_connection(server *srv, connection *con, plugin_data *p) { - size_t i, j; - plugin_config *s = p->config_storage[0]; - - PATCH(extensions); - PATCH(debug); - - /* skip the first, the global context */ - for (i = 1; i < srv->config_context->used; i++) { - data_config *dc = (data_config *)srv->config_context->data[i]; - s = p->config_storage[i]; - - /* condition didn't match */ - if (!config_check_cond(srv, con, dc)) continue; - - /* merge config */ - for (j = 0; j < dc->value->used; j++) { - data_unset *du = dc->value->data[j]; - - if (buffer_is_equal_string(du->key, CONST_STR_LEN("uwsgi.server"))) { - PATCH(extensions); - } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("uwsgi.debug"))) { - PATCH(debug); - } - } - } - - return 0; -} -#undef PATCH - -SUBREQUEST_FUNC(mod_uwsgi_handle_subrequest) { - plugin_data *p = p_d; - - handler_ctx *hctx = con->plugin_ctx[p->id]; - data_uwsgi *host; - - if (NULL == hctx) return HANDLER_GO_ON; - - mod_uwsgi_patch_connection(srv, con, p); - - host = hctx->host; - - /* not my job */ - if (con->mode != p->id) return HANDLER_GO_ON; - - /* ok, create the request */ - switch(uwsgi_write_request(srv, hctx)) { - case HANDLER_ERROR: - log_error_write(srv, __FILE__, __LINE__, "sbdd", "uwsgi-server disabled:", - host->host, - host->port, - hctx->fd); - - /* disable this server */ - host->is_disabled = 1; - host->disable_ts = srv->cur_ts; - - uwsgi_connection_close(srv, hctx); - - /* reset the enviroment and restart the sub-request */ - buffer_reset(con->physical.path); - con->mode = DIRECT; - - joblist_append(srv, con); - - /* mis-using HANDLER_WAIT_FOR_FD to break out of the loop - * and hope that the childs will be restarted - * - */ - - return HANDLER_WAIT_FOR_FD; - case HANDLER_WAIT_FOR_EVENT: - return HANDLER_WAIT_FOR_EVENT; - case HANDLER_WAIT_FOR_FD: - return HANDLER_WAIT_FOR_FD; - default: - break; - } - - if (con->file_started == 1) { - return HANDLER_FINISHED; - } else { - return HANDLER_WAIT_FOR_EVENT; - } -} - -static handler_t uwsgi_handle_fdevent(void *s, void *ctx, int revents) { - server *srv = (server *)s; - handler_ctx *hctx = ctx; - connection *con = hctx->remote_conn; - plugin_data *p = hctx->plugin_data; - - - if ((revents & FDEVENT_IN) && - hctx->state == UWSGI_STATE_READ) { - - if (p->conf.debug) { - log_error_write(srv, __FILE__, __LINE__, "sd", - "uwsgi: fdevent-in", hctx->state); - } - - switch (uwsgi_demux_response(srv, hctx)) { - case 0: - break; - case 1: - hctx->host->usage--; - - /* we are done */ - uwsgi_connection_close(srv, hctx); - - joblist_append(srv, con); - return HANDLER_FINISHED; - case -1: - if (con->file_started == 0) { - /* nothing has been send out yet, send a 500 */ - connection_set_state(srv, con, CON_STATE_HANDLE_REQUEST); - con->http_status = 500; - con->mode = DIRECT; - } else { - /* response might have been already started, kill the connection */ - connection_set_state(srv, con, CON_STATE_ERROR); - } - - joblist_append(srv, con); - return HANDLER_FINISHED; - } - } - - if (revents & FDEVENT_OUT) { - if (p->conf.debug) { - log_error_write(srv, __FILE__, __LINE__, "sd", - "uwsgi: fdevent-out", hctx->state); - } - - if (hctx->state == UWSGI_STATE_CONNECT || - hctx->state == UWSGI_STATE_WRITE) { - /* we are allowed to send something out - * - * 1. in a unfinished connect() call - * 2. in a unfinished write() call (long POST request) - */ - return mod_uwsgi_handle_subrequest(srv, con, p); - } else { - log_error_write(srv, __FILE__, __LINE__, "sd", - "uwsgi: out", hctx->state); - } - } - - /* perhaps this issue is already handled */ - if (revents & FDEVENT_HUP) { - if (p->conf.debug) { - log_error_write(srv, __FILE__, __LINE__, "sd", - "uwsgi: fdevent-hup", hctx->state); - } - - if (hctx->state == UWSGI_STATE_CONNECT) { - /* connect() -> EINPROGRESS -> HUP */ - - /** - * what is uwsgi is doing if it can't reach the next hop ? - * - */ - - uwsgi_connection_close(srv, hctx); - joblist_append(srv, con); - - con->http_status = 503; - con->mode = DIRECT; - - return HANDLER_FINISHED; - } - - con->file_finished = 1; - - uwsgi_connection_close(srv, hctx); - joblist_append(srv, con); - } else if (revents & FDEVENT_ERR) { - /* kill all connections to the uwsgi process */ - - log_error_write(srv, __FILE__, __LINE__, "sd", "uwsgi-FDEVENT_ERR, but no HUP", revents); - - joblist_append(srv, con); - uwsgi_connection_close(srv, hctx); - } - - return HANDLER_FINISHED; -} - -static handler_t mod_uwsgi_check_extension(server *srv, connection *con, void *p_d) { - plugin_data *p = p_d; - size_t s_len; - int max_usage = INT_MAX; - int ndx = -1; - size_t k; - buffer *fn; - data_array *extension = NULL; - size_t path_info_offset; - - if (con->mode != DIRECT) return HANDLER_GO_ON; - - /* Possibly, we processed already this request */ - if (con->file_started == 1) return HANDLER_GO_ON; - - mod_uwsgi_patch_connection(srv, con, p); - - fn = con->uri.path; - - if (fn->used == 0) { - return HANDLER_ERROR; - } - - s_len = fn->used - 1; - - - path_info_offset = 0; - - if (p->conf.debug) { - log_error_write(srv, __FILE__, __LINE__, "s", "uwsgi - start"); - } - - /* check if extension matches */ - for (k = 0; k < p->conf.extensions->used; k++) { - data_array *ext = NULL; - size_t ct_len; - - ext = (data_array *)p->conf.extensions->data[k]; - - if (ext->key->used == 0) continue; - - ct_len = ext->key->used - 1; - - if (s_len < ct_len) continue; - - /* check extension in the form "/uwsgi_pattern" */ - if (*(ext->key->ptr) == '/') { - if (strncmp(fn->ptr, ext->key->ptr, ct_len) == 0) { - path_info_offset = ct_len; - extension = ext; - break; - } - } else if (0 == strncmp(fn->ptr + s_len - ct_len, ext->key->ptr, ct_len)) { - /* check extension in the form ".fcg" */ - extension = ext; - break; - } - } - - if (NULL == extension) { - return HANDLER_GO_ON; - } - - if (p->conf.debug) { - log_error_write(srv, __FILE__, __LINE__, "s", "uwsgi - ext found"); - } - - if (extension->value->used == 1) { - if ( ((data_uwsgi *)extension->value->data[0])->is_disabled ) { - ndx = -1; - } else { - ndx = 0; - } - } else if (extension->value->used != 0) { - - /* fair balancing */ - if (p->conf.debug) { - log_error_write(srv, __FILE__, __LINE__, "s", - "uwsgi - used fair balancing"); - } - - for (k = 0, ndx = -1, max_usage = INT_MAX; k < extension->value->used; k++) { - data_uwsgi *host = (data_uwsgi *)extension->value->data[k]; - - if (host->is_disabled) continue; - - if (host->usage < max_usage) { - max_usage = host->usage; - - ndx = k; - } - } - - } - - /* found a server */ - if (ndx != -1) { - data_uwsgi *host = (data_uwsgi *)extension->value->data[ndx]; - - /* - * if check-local is disabled, use the uri.path handler - * - */ - - /* init handler-context */ - handler_ctx *hctx; - hctx = handler_ctx_init(); - - hctx->path_info_offset = path_info_offset; - hctx->remote_conn = con; - hctx->plugin_data = p; - hctx->host = host; - - con->plugin_ctx[p->id] = hctx; - - host->usage++; - - con->mode = p->id; - - if (p->conf.debug) { - log_error_write(srv, __FILE__, __LINE__, "sbd", - "uwsgi - found a host", - host->host, host->port); - } - - return HANDLER_GO_ON; - } else { - /* no handler found */ - con->http_status = 500; - - log_error_write(srv, __FILE__, __LINE__, "sb", - "no uwsgi-handler found for:", - fn); - - return HANDLER_FINISHED; - } - return HANDLER_GO_ON; -} - -static handler_t mod_uwsgi_connection_close_callback(server *srv, connection *con, void *p_d) { - plugin_data *p = p_d; - - uwsgi_connection_close(srv, con->plugin_ctx[p->id]); - - return HANDLER_GO_ON; -} - -/** - * - * the trigger re-enables the disabled connections after the timeout is over - * - * */ - -TRIGGER_FUNC(mod_uwsgi_trigger) { - plugin_data *p = p_d; - - if (p->config_storage) { - size_t i, n, k; - for (i = 0; i < srv->config_context->used; i++) { - plugin_config *s = p->config_storage[i]; - - if (!s) continue; - - /* get the extensions for all configs */ - - for (k = 0; k < s->extensions->used; k++) { - data_array *extension = (data_array *)s->extensions->data[k]; - - /* get all hosts */ - for (n = 0; n < extension->value->used; n++) { - data_uwsgi *host = (data_uwsgi *)extension->value->data[n]; - - if (!host->is_disabled || - srv->cur_ts - host->disable_ts < 5) continue; - - log_error_write(srv, __FILE__, __LINE__, "sbd", - "uwsgi - re-enabled:", - host->host, host->port); - - host->is_disabled = 0; - } - } - } - } - - return HANDLER_GO_ON; -} - - -int mod_uwsgi_plugin_init(plugin *p); -int mod_uwsgi_plugin_init(plugin *p) { - p->version = LIGHTTPD_VERSION_ID; - p->name = buffer_init_string("uwsgi"); - - p->init = mod_uwsgi_init; - p->cleanup = mod_uwsgi_free; - p->set_defaults = mod_uwsgi_set_defaults; - p->connection_reset = mod_uwsgi_connection_close_callback; /* end of req-resp cycle */ - p->handle_connection_close = mod_uwsgi_connection_close_callback; /* end of client connection */ - p->handle_uri_clean = mod_uwsgi_check_extension; - p->handle_subrequest = mod_uwsgi_handle_subrequest; - p->handle_trigger = mod_uwsgi_trigger; - - p->data = NULL; - - return 0; -} diff --git a/nginx/config b/nginx/config deleted file mode 100644 index 28b3d084..00000000 --- a/nginx/config +++ /dev/null @@ -1,3 +0,0 @@ -ngx_addon_name=ngx_http_uwsgi_module -HTTP_MODULES="$HTTP_MODULES ngx_http_uwsgi_module" -NGX_ADDON_SRCS="$NGX_ADDON_SRCS $ngx_addon_dir/ngx_http_uwsgi_module.c" diff --git a/nginx/ngx_http_uwsgi_module.c b/nginx/ngx_http_uwsgi_module.c deleted file mode 100644 index 1f74d4e0..00000000 --- a/nginx/ngx_http_uwsgi_module.c +++ /dev/null @@ -1,1655 +0,0 @@ - -/* - * Copyright (C) Unbit S.a.s. 2009-2010 - * - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - - - - * heavily based on Manlio's mod_scgi, mod_fastcgi and mod_proxy of nginx 0.7.x - -*/ - - -#include -#include -#include - -#ifndef NGX_HTTP_UWSGI_TEMP_PATH -#define NGX_HTTP_UWSGI_TEMP_PATH "uwsgi_temp" -#endif - -typedef struct { - ngx_http_upstream_conf_t upstream; - - ngx_array_t *flushes; - ngx_array_t *params_len; - ngx_array_t *params; - ngx_array_t *params_source; - - ngx_array_t *uwsgi_lengths; - ngx_array_t *uwsgi_values; - - ngx_str_t uwsgi_string; - - u_char modifier1; - u_char modifier2; - -} ngx_http_uwsgi_loc_conf_t; - -typedef struct { - ngx_uint_t status; - ngx_uint_t status_count; - u_char *status_start; - u_char *status_end; -} ngx_http_uwsgi_ctx_t; - -#define NGX_HTTP_XCGI_PARSE_NO_HEADER 20 - -#ifndef NGX_HAVE_LITTLE_ENDIAN -static uint16_t -uwsgi_swap16 (uint16_t x) -{ - return (uint16_t) ((x & 0xff) << 8 | (x & 0xff00) >> 8); -} -#endif - - - -static ngx_int_t ngx_http_uwsgi_eval (ngx_http_request_t * r, - ngx_http_uwsgi_loc_conf_t * uwcf); -static ngx_int_t ngx_http_uwsgi_create_request (ngx_http_request_t * r); -static ngx_int_t ngx_http_uwsgi_reinit_request (ngx_http_request_t * r); -static ngx_int_t ngx_http_uwsgi_process_status_line (ngx_http_request_t * r); -static ngx_int_t ngx_http_uwsgi_parse_status_line (ngx_http_request_t * r, - ngx_http_uwsgi_ctx_t * - ctx); -static ngx_int_t ngx_http_uwsgi_process_header (ngx_http_request_t * r); -static ngx_int_t ngx_http_uwsgi_process_header (ngx_http_request_t * r); -static void ngx_http_uwsgi_abort_request (ngx_http_request_t * r); -static void ngx_http_uwsgi_finalize_request (ngx_http_request_t * r, - ngx_int_t rc); - -static char *ngx_http_uwsgi_modifier1 (ngx_conf_t * cf, ngx_command_t * cmd, - void *conf); - -static char *ngx_http_uwsgi_modifier2 (ngx_conf_t * cf, ngx_command_t * cmd, - void *conf); - -static ngx_int_t ngx_http_uwsgi_add_variables (ngx_conf_t * cf); -static void *ngx_http_uwsgi_create_loc_conf (ngx_conf_t * cf); -static char *ngx_http_uwsgi_merge_loc_conf (ngx_conf_t * cf, - void *parent, void *child); - -static char *ngx_http_uwsgi_pass (ngx_conf_t * cf, ngx_command_t * cmd, - void *conf); - - -static ngx_conf_bitmask_t ngx_http_uwsgi_next_upstream_masks[] = { - {ngx_string ("error"), NGX_HTTP_UPSTREAM_FT_ERROR}, - {ngx_string ("timeout"), NGX_HTTP_UPSTREAM_FT_TIMEOUT}, - {ngx_string ("invalid_header"), NGX_HTTP_UPSTREAM_FT_INVALID_HEADER}, - {ngx_string ("http_500"), NGX_HTTP_UPSTREAM_FT_HTTP_500}, - {ngx_string ("http_502"), NGX_HTTP_UPSTREAM_FT_HTTP_502}, - {ngx_string ("http_503"), NGX_HTTP_UPSTREAM_FT_HTTP_503}, - {ngx_string ("http_504"), NGX_HTTP_UPSTREAM_FT_HTTP_504}, - {ngx_string ("http_404"), NGX_HTTP_UPSTREAM_FT_HTTP_404}, - {ngx_string ("updating"), NGX_HTTP_UPSTREAM_FT_UPDATING}, - {ngx_string ("off"), NGX_HTTP_UPSTREAM_FT_OFF}, - {ngx_null_string, 0} -}; - - -static ngx_conf_bitmask_t ngx_http_uwsgi_ignore_headers_masks[] = { - {ngx_string ("X-Accel-Redirect"), NGX_HTTP_UPSTREAM_IGN_XA_REDIRECT}, - {ngx_string ("X-Accel-Expires"), NGX_HTTP_UPSTREAM_IGN_XA_EXPIRES}, - {ngx_string ("Expires"), NGX_HTTP_UPSTREAM_IGN_EXPIRES}, - {ngx_string ("Cache-Control"), NGX_HTTP_UPSTREAM_IGN_CACHE_CONTROL}, - {ngx_null_string, 0} -}; - - -ngx_module_t ngx_http_uwsgi_module; - - -static ngx_command_t ngx_http_uwsgi_commands[] = { - - {ngx_string ("uwsgi_pass"), - NGX_HTTP_LOC_CONF | NGX_HTTP_LIF_CONF | NGX_CONF_TAKE1, - ngx_http_uwsgi_pass, - NGX_HTTP_LOC_CONF_OFFSET, - 0, - NULL}, - - {ngx_string ("uwsgi_modifier1"), - NGX_HTTP_MAIN_CONF | NGX_HTTP_SRV_CONF | NGX_HTTP_LOC_CONF | - NGX_CONF_TAKE1, - ngx_http_uwsgi_modifier1, - NGX_HTTP_LOC_CONF_OFFSET, - 0, - NULL}, - - {ngx_string ("uwsgi_modifier2"), - NGX_HTTP_MAIN_CONF | NGX_HTTP_SRV_CONF | NGX_HTTP_LOC_CONF | - NGX_CONF_TAKE1, - ngx_http_uwsgi_modifier2, - NGX_HTTP_LOC_CONF_OFFSET, - 0, - NULL}, - - {ngx_string ("uwsgi_ignore_client_abort"), - NGX_HTTP_MAIN_CONF | NGX_HTTP_SRV_CONF | NGX_HTTP_LOC_CONF | - NGX_CONF_FLAG, - ngx_conf_set_flag_slot, - NGX_HTTP_LOC_CONF_OFFSET, - offsetof (ngx_http_uwsgi_loc_conf_t, upstream.ignore_client_abort), - NULL}, - - {ngx_string ("uwsgi_connect_timeout"), - NGX_HTTP_MAIN_CONF | NGX_HTTP_SRV_CONF | NGX_HTTP_LOC_CONF | - NGX_CONF_TAKE1, - ngx_conf_set_msec_slot, - NGX_HTTP_LOC_CONF_OFFSET, - offsetof (ngx_http_uwsgi_loc_conf_t, upstream.connect_timeout), - NULL}, - - {ngx_string ("uwsgi_send_timeout"), - NGX_HTTP_MAIN_CONF | NGX_HTTP_SRV_CONF | NGX_HTTP_LOC_CONF | - NGX_CONF_TAKE1, - ngx_conf_set_msec_slot, - NGX_HTTP_LOC_CONF_OFFSET, - offsetof (ngx_http_uwsgi_loc_conf_t, upstream.send_timeout), - NULL}, - - {ngx_string ("uwsgi_buffer_size"), - NGX_HTTP_MAIN_CONF | NGX_HTTP_SRV_CONF | NGX_HTTP_LOC_CONF | - NGX_CONF_TAKE1, - ngx_conf_set_size_slot, - NGX_HTTP_LOC_CONF_OFFSET, - offsetof (ngx_http_uwsgi_loc_conf_t, upstream.buffer_size), - NULL}, - - {ngx_string ("uwsgi_pass_request_headers"), - NGX_HTTP_MAIN_CONF | NGX_HTTP_SRV_CONF | NGX_HTTP_LOC_CONF | - NGX_CONF_FLAG, - ngx_conf_set_flag_slot, - NGX_HTTP_LOC_CONF_OFFSET, - offsetof (ngx_http_uwsgi_loc_conf_t, upstream.pass_request_headers), - NULL}, - - {ngx_string ("uwsgi_pass_request_body"), - NGX_HTTP_MAIN_CONF | NGX_HTTP_SRV_CONF | NGX_HTTP_LOC_CONF | - NGX_CONF_FLAG, - ngx_conf_set_flag_slot, - NGX_HTTP_LOC_CONF_OFFSET, - offsetof (ngx_http_uwsgi_loc_conf_t, upstream.pass_request_body), - NULL}, - - {ngx_string ("uwsgi_intercept_errors"), - NGX_HTTP_MAIN_CONF | NGX_HTTP_SRV_CONF | NGX_HTTP_LOC_CONF | - NGX_CONF_FLAG, - ngx_conf_set_flag_slot, - NGX_HTTP_LOC_CONF_OFFSET, - offsetof (ngx_http_uwsgi_loc_conf_t, upstream.intercept_errors), - NULL}, - - {ngx_string ("uwsgi_read_timeout"), - NGX_HTTP_MAIN_CONF | NGX_HTTP_SRV_CONF | NGX_HTTP_LOC_CONF | - NGX_CONF_TAKE1, - ngx_conf_set_msec_slot, - NGX_HTTP_LOC_CONF_OFFSET, - offsetof (ngx_http_uwsgi_loc_conf_t, upstream.read_timeout), - NULL}, - - {ngx_string ("uwsgi_buffers"), - NGX_HTTP_MAIN_CONF | NGX_HTTP_SRV_CONF | NGX_HTTP_LOC_CONF | - NGX_CONF_TAKE2, - ngx_conf_set_bufs_slot, - NGX_HTTP_LOC_CONF_OFFSET, - offsetof (ngx_http_uwsgi_loc_conf_t, upstream.bufs), - NULL}, - - {ngx_string ("uwsgi_busy_buffers_size"), - NGX_HTTP_MAIN_CONF | NGX_HTTP_SRV_CONF | NGX_HTTP_LOC_CONF | - NGX_CONF_TAKE1, - ngx_conf_set_size_slot, - NGX_HTTP_LOC_CONF_OFFSET, - offsetof (ngx_http_uwsgi_loc_conf_t, upstream.busy_buffers_size_conf), - NULL}, - - {ngx_string ("uwsgi_temp_path"), - NGX_HTTP_MAIN_CONF | NGX_HTTP_SRV_CONF | NGX_HTTP_LOC_CONF | - NGX_CONF_TAKE1234, - ngx_conf_set_path_slot, - NGX_HTTP_LOC_CONF_OFFSET, - offsetof (ngx_http_uwsgi_loc_conf_t, upstream.temp_path), - NULL}, - - {ngx_string ("uwsgi_max_temp_file_size"), - NGX_HTTP_MAIN_CONF | NGX_HTTP_SRV_CONF | NGX_HTTP_LOC_CONF | - NGX_CONF_TAKE1, - ngx_conf_set_size_slot, - NGX_HTTP_LOC_CONF_OFFSET, - offsetof (ngx_http_uwsgi_loc_conf_t, upstream.max_temp_file_size_conf), - NULL}, - - {ngx_string ("uwsgi_temp_file_write_size"), - NGX_HTTP_MAIN_CONF | NGX_HTTP_SRV_CONF | NGX_HTTP_LOC_CONF | - NGX_CONF_TAKE1, - ngx_conf_set_size_slot, - NGX_HTTP_LOC_CONF_OFFSET, - offsetof (ngx_http_uwsgi_loc_conf_t, upstream.temp_file_write_size_conf), - NULL}, - - {ngx_string ("uwsgi_next_upstream"), - NGX_HTTP_MAIN_CONF | NGX_HTTP_SRV_CONF | NGX_HTTP_LOC_CONF | - NGX_CONF_1MORE, - ngx_conf_set_bitmask_slot, - NGX_HTTP_LOC_CONF_OFFSET, - offsetof (ngx_http_uwsgi_loc_conf_t, upstream.next_upstream), - &ngx_http_uwsgi_next_upstream_masks}, - - {ngx_string ("uwsgi_param"), - NGX_HTTP_MAIN_CONF | NGX_HTTP_SRV_CONF | NGX_HTTP_LOC_CONF | - NGX_CONF_TAKE2, - ngx_conf_set_keyval_slot, - NGX_HTTP_LOC_CONF_OFFSET, - offsetof (ngx_http_uwsgi_loc_conf_t, params_source), - NULL}, - - { ngx_string("uwsgi_string"), - NGX_HTTP_MAIN_CONF | NGX_HTTP_SRV_CONF | NGX_HTTP_LOC_CONF | - NGX_CONF_TAKE1, - ngx_conf_set_str_slot, - NGX_HTTP_LOC_CONF_OFFSET, - offsetof(ngx_http_uwsgi_loc_conf_t, uwsgi_string), - NULL }, - - {ngx_string ("uwsgi_pass_header"), - NGX_HTTP_MAIN_CONF | NGX_HTTP_SRV_CONF | NGX_HTTP_LOC_CONF | - NGX_CONF_FLAG, - ngx_conf_set_str_array_slot, - NGX_HTTP_LOC_CONF_OFFSET, - offsetof (ngx_http_uwsgi_loc_conf_t, upstream.pass_headers), - NULL}, - - {ngx_string ("uwsgi_hide_header"), - NGX_HTTP_MAIN_CONF | NGX_HTTP_SRV_CONF | NGX_HTTP_LOC_CONF | - NGX_CONF_FLAG, - ngx_conf_set_str_array_slot, - NGX_HTTP_LOC_CONF_OFFSET, - offsetof (ngx_http_uwsgi_loc_conf_t, upstream.hide_headers), - NULL}, - - {ngx_string ("uwsgi_ignore_headers"), - NGX_HTTP_MAIN_CONF | NGX_HTTP_SRV_CONF | NGX_HTTP_LOC_CONF | - NGX_CONF_1MORE, - ngx_conf_set_bitmask_slot, - NGX_HTTP_LOC_CONF_OFFSET, - offsetof (ngx_http_uwsgi_loc_conf_t, upstream.ignore_headers), - &ngx_http_uwsgi_ignore_headers_masks}, - - ngx_null_command -}; - - -static ngx_http_module_t ngx_http_uwsgi_module_ctx = { - ngx_http_uwsgi_add_variables, /* preconfiguration */ - NULL, /* postconfiguration */ - - NULL, /* create main configuration */ - NULL, /* init main configuration */ - - NULL, /* create server configuration */ - NULL, /* merge server configuration */ - - ngx_http_uwsgi_create_loc_conf, /* create location configuration */ - ngx_http_uwsgi_merge_loc_conf /* merge location configuration */ -}; - - -ngx_module_t ngx_http_uwsgi_module = { - NGX_MODULE_V1, - &ngx_http_uwsgi_module_ctx, /* module context */ - ngx_http_uwsgi_commands, /* module directives */ - NGX_HTTP_MODULE, /* module type */ - NULL, /* init master */ - NULL, /* init module */ - NULL, /* init process */ - NULL, /* init thread */ - NULL, /* exit thread */ - NULL, /* exit process */ - NULL, /* exit master */ - NGX_MODULE_V1_PADDING -}; - - -static ngx_http_variable_t ngx_http_uwsgi_vars[] = { - - {ngx_null_string, NULL, NULL, 0, 0, 0} -}; - - -static ngx_str_t ngx_http_uwsgi_hide_headers[] = { - ngx_string ("Status"), - ngx_string ("X-Accel-Expires"), - ngx_string ("X-Accel-Redirect"), - ngx_string ("X-Accel-Limit-Rate"), - ngx_string ("X-Accel-Buffering"), - ngx_string ("X-Accel-Charset"), - ngx_null_string -}; - - -static ngx_path_init_t ngx_http_uwsgi_temp_path = { - ngx_string (NGX_HTTP_UWSGI_TEMP_PATH), {1, 2, 0} -}; - - -static ngx_int_t -ngx_http_uwsgi_handler (ngx_http_request_t * r) -{ - ngx_int_t rc; - ngx_http_upstream_t *u; - ngx_http_uwsgi_ctx_t *f; - ngx_http_uwsgi_loc_conf_t *uwcf; - - if (r->subrequest_in_memory) { - ngx_log_error (NGX_LOG_ALERT, r->connection->log, 0, - "ngx_http_uwsgi_module does not support " - "subrequest in memory"); - return NGX_HTTP_INTERNAL_SERVER_ERROR; - } - - if (ngx_http_upstream_create (r) != NGX_OK) { - return NGX_HTTP_INTERNAL_SERVER_ERROR; - } - - f = ngx_pcalloc (r->pool, sizeof (ngx_http_uwsgi_ctx_t)); - if (f == NULL) { - return NGX_HTTP_INTERNAL_SERVER_ERROR; - } - - ngx_http_set_ctx (r, f, ngx_http_uwsgi_module); - - uwcf = ngx_http_get_module_loc_conf (r, ngx_http_uwsgi_module); - - if (uwcf->uwsgi_lengths) { - if (ngx_http_uwsgi_eval (r, uwcf) != NGX_OK) { - return NGX_HTTP_INTERNAL_SERVER_ERROR; - } - } - - u = r->upstream; - - u->schema.len = sizeof ("uwsgi://") - 1; - u->schema.data = (u_char *) "uwsgi://"; - - u->output.tag = (ngx_buf_tag_t) & ngx_http_uwsgi_module; - - u->conf = &uwcf->upstream; - - u->create_request = ngx_http_uwsgi_create_request; - u->reinit_request = ngx_http_uwsgi_reinit_request; - u->process_header = ngx_http_uwsgi_process_status_line; - u->abort_request = ngx_http_uwsgi_abort_request; - u->finalize_request = ngx_http_uwsgi_finalize_request; - - u->buffering = 1; - - u->pipe = ngx_pcalloc (r->pool, sizeof (ngx_event_pipe_t)); - if (u->pipe == NULL) { - return NGX_HTTP_INTERNAL_SERVER_ERROR; - } - - u->pipe->input_filter = ngx_event_pipe_copy_input_filter; - u->pipe->input_ctx = r; - - rc = ngx_http_read_client_request_body (r, ngx_http_upstream_init); - - if (rc >= NGX_HTTP_SPECIAL_RESPONSE) { - return rc; - } - - return NGX_DONE; -} - - -static ngx_int_t -ngx_http_uwsgi_eval (ngx_http_request_t * r, ngx_http_uwsgi_loc_conf_t * uwcf) -{ - ngx_url_t u; - - ngx_memzero (&u, sizeof (ngx_url_t)); - - if (ngx_http_script_run (r, &u.url, uwcf->uwsgi_lengths->elts, 0, - uwcf->uwsgi_values->elts) == NULL) { - return NGX_ERROR; - } - - u.no_resolve = 1; - - if (ngx_parse_url (r->pool, &u) != NGX_OK) { - if (u.err) { - ngx_log_error (NGX_LOG_ERR, r->connection->log, 0, - "%s in upstream \"%V\"", u.err, &u.url); - } - - return NGX_ERROR; - } - - if (u.no_port) { - ngx_log_error (NGX_LOG_ERR, r->connection->log, 0, - "no port in upstream \"%V\"", &u.url); - return NGX_ERROR; - } - - r->upstream->resolved = ngx_pcalloc (r->pool, - sizeof - (ngx_http_upstream_resolved_t)); - if (r->upstream->resolved == NULL) { - return NGX_ERROR; - } - - if (u.addrs && u.addrs[0].sockaddr) { - r->upstream->resolved->sockaddr = u.addrs[0].sockaddr; - r->upstream->resolved->socklen = u.addrs[0].socklen; - r->upstream->resolved->naddrs = 1; - r->upstream->resolved->host = u.addrs[0].name; - - } - else { - r->upstream->resolved->host = u.host; - r->upstream->resolved->port = u.port; - } - - return NGX_OK; -} - - -static ngx_int_t -ngx_http_uwsgi_create_request (ngx_http_request_t * r) -{ - u_char ch, *pos, tmp[2]; - size_t key_len, val_len; - uint16_t uwsgi_pkt_size, uwsgi_strlen; - ngx_uint_t i, n; - ngx_buf_t *b; - ngx_chain_t *cl, *body; - ngx_list_part_t *part; - ngx_table_elt_t *header; - ngx_http_script_code_pt code; - ngx_http_script_engine_t e, le; - ngx_http_uwsgi_loc_conf_t *uwcf; - ngx_http_script_len_code_pt lcode; - - uwsgi_pkt_size = 0; - - uwcf = ngx_http_get_module_loc_conf (r, ngx_http_uwsgi_module); - - if (uwcf->params_len) { - ngx_memzero (&le, sizeof (ngx_http_script_engine_t)); - - ngx_http_script_flush_no_cacheable_variables (r, uwcf->flushes); - le.flushed = 1; - - le.ip = uwcf->params_len->elts; - le.request = r; - - while (*(uintptr_t *) le.ip) { - - lcode = *(ngx_http_script_len_code_pt *) le.ip; - key_len = lcode (&le); - - for (val_len = 0; *(uintptr_t *) le.ip; val_len += lcode (&le)) { - lcode = *(ngx_http_script_len_code_pt *) le.ip; - } - le.ip += sizeof (uintptr_t); - - uwsgi_pkt_size += 2 + key_len + 2 + val_len; - } - } - - if (uwcf->upstream.pass_request_headers) { - - part = &r->headers_in.headers.part; - header = part->elts; - - for (i = 0; /* void */; i++) { - - if (i >= part->nelts) { - if (part->next == NULL) { - break; - } - - part = part->next; - header = part->elts; - i = 0; - } - - uwsgi_pkt_size += - 2 + 5 + header[i].key.len + 2 + header[i].value.len; - } - } - - if (uwcf->uwsgi_string.data && uwcf->uwsgi_string.len) { - uwsgi_pkt_size += uwcf->uwsgi_string.len; - } - - - /* allow custom uwsgi packet - if (uwsgi_pkt_size > 0 && uwsgi_pkt_size < 2) { - ngx_log_error (NGX_LOG_ALERT, r->connection->log, 0, - "uwsgi request is too little: %uz", uwsgi_pkt_size); - return NGX_ERROR; - } - */ - - b = ngx_create_temp_buf (r->pool, uwsgi_pkt_size + 4); - if (b == NULL) { - return NGX_ERROR; - } - - cl = ngx_alloc_chain_link (r->pool); - if (cl == NULL) { - return NGX_ERROR; - } - - cl->buf = b; - - *b->pos = uwcf->modifier1; -#ifndef NGX_HAVE_LITTLE_ENDIAN - uwsgi_pkt_size = uwsgi_swap16 (uwsgi_pkt_size); -#endif - b->last = ngx_cpymem (b->pos + 1, &uwsgi_pkt_size, 2); - *(b->pos + 3) = uwcf->modifier2; - b->last++; - - if (uwcf->params_len) { - ngx_memzero (&e, sizeof (ngx_http_script_engine_t)); - - e.ip = uwcf->params->elts; - e.pos = b->last; - e.request = r; - e.flushed = 1; - - le.ip = uwcf->params_len->elts; - - while (*(uintptr_t *) le.ip) { - - lcode = *(ngx_http_script_len_code_pt *) le.ip; - key_len = (u_char) lcode (&le); - - for (val_len = 0; *(uintptr_t *) le.ip; val_len += lcode (&le)) { - lcode = *(ngx_http_script_len_code_pt *) le.ip; - } - le.ip += sizeof (uintptr_t); - -#ifndef NGX_HAVE_LITTLE_ENDIAN - uwsgi_strlen = uwsgi_swap16 (key_len); -#else - uwsgi_strlen = key_len; -#endif - e.pos = ngx_cpymem (e.pos, &uwsgi_strlen, 2); - - while (*(uintptr_t *) e.ip) { - code = *(ngx_http_script_code_pt *) e.ip; - code ((ngx_http_script_engine_t *) & e); - } - - pos = e.pos - val_len; - /* move memory */ - for (i = 0; i < val_len; i += 2) { - e.pos = ngx_cpymem (tmp, pos + (i) + 2, 2); - e.pos = ngx_cpymem (pos + (i) + 2, pos, 2); - e.pos = ngx_cpymem (pos, tmp, 2); - } - - e.pos = pos; - -#ifndef NGX_HAVE_LITTLE_ENDIAN - uwsgi_strlen = uwsgi_swap16 (val_len); -#else - uwsgi_strlen = val_len; -#endif - e.pos = ngx_cpymem (e.pos, &uwsgi_strlen, 2); - e.pos += val_len; - - e.ip += sizeof (uintptr_t); - - - } - - b->last = e.pos; - } - - - if (uwcf->upstream.pass_request_headers) { - - part = &r->headers_in.headers.part; - header = part->elts; - - for (i = 0; /* void */; i++) { - - if (i >= part->nelts) { - if (part->next == NULL) { - break; - } - - part = part->next; - header = part->elts; - i = 0; - } - -#ifndef NGX_HAVE_LITTLE_ENDIAN - uwsgi_strlen = uwsgi_swap16 (5 + header[i].key.len); -#else - uwsgi_strlen = 5 + header[i].key.len; -#endif - b->last = ngx_cpymem (b->last, &uwsgi_strlen, 2); - b->last = ngx_cpymem (b->last, "HTTP_", 5); - for (n = 0; n < header[i].key.len; n++) { - ch = header[i].key.data[n]; - - if (ch >= 'a' && ch <= 'z') { - ch &= ~0x20; - - } - else if (ch == '-') { - ch = '_'; - } - - *b->last++ = ch; - } -#ifndef NGX_HAVE_LITTLE_ENDIAN - uwsgi_strlen = uwsgi_swap16 (header[i].value.len); -#else - uwsgi_strlen = header[i].value.len; -#endif - b->last = ngx_cpymem (b->last, &uwsgi_strlen, 2); - b->last = - ngx_copy (b->last, header[i].value.data, header[i].value.len); - - - } - } - - - - if (uwcf->uwsgi_string.data && uwcf->uwsgi_string.len) { - b->last = ngx_copy(b->last, uwcf->uwsgi_string.data, uwcf->uwsgi_string.len); - } - - if (uwcf->upstream.pass_request_body) { - body = r->upstream->request_bufs; - r->upstream->request_bufs = cl; - - while (body) { - b = ngx_alloc_buf (r->pool); - if (b == NULL) { - return NGX_ERROR; - } - - ngx_memcpy (b, body->buf, sizeof (ngx_buf_t)); - - cl->next = ngx_alloc_chain_link (r->pool); - if (cl->next == NULL) { - return NGX_ERROR; - } - - cl = cl->next; - cl->buf = b; - - body = body->next; - } - - b->flush = 1; - - } - else { - r->upstream->request_bufs = cl; - } - - cl->next = NULL; - - return NGX_OK; -} - - -static ngx_int_t -ngx_http_uwsgi_reinit_request (ngx_http_request_t * r) -{ - - ngx_http_uwsgi_ctx_t *s; - - s = ngx_http_get_module_ctx (r, ngx_http_uwsgi_module); - - if (s == NULL) { - return NGX_OK; - } - - s->status = 0; - s->status_count = 0; - s->status_start = NULL; - s->status_end = NULL; - - r->upstream->process_header = ngx_http_uwsgi_process_status_line; - - return NGX_OK; -} - -static ngx_int_t -ngx_http_uwsgi_parse_status_line (ngx_http_request_t * r, - ngx_http_uwsgi_ctx_t * ctx) -{ - u_char ch; - u_char *p; - ngx_http_upstream_t *u; - enum { - sw_start = 0, - sw_H, - sw_HT, - sw_HTT, - sw_HTTP, - sw_first_major_digit, - sw_major_digit, - sw_first_minor_digit, - sw_minor_digit, - sw_status, - sw_space_after_status, - sw_status_text, - sw_almost_done - } state; - - u = r->upstream; - - state = r->state; - - for (p = u->buffer.pos; p < u->buffer.last; p++) { - ch = *p; - - switch (state) { - - /* "HTTP/" */ - case sw_start: - switch (ch) { - case 'H': - state = sw_H; - break; - default: - return NGX_HTTP_XCGI_PARSE_NO_HEADER; - } - break; - - case sw_H: - switch (ch) { - case 'T': - state = sw_HT; - break; - default: - return NGX_HTTP_XCGI_PARSE_NO_HEADER; - } - break; - - case sw_HT: - switch (ch) { - case 'T': - state = sw_HTT; - break; - default: - return NGX_HTTP_XCGI_PARSE_NO_HEADER; - } - break; - - case sw_HTT: - switch (ch) { - case 'P': - state = sw_HTTP; - break; - default: - return NGX_HTTP_XCGI_PARSE_NO_HEADER; - } - break; - - case sw_HTTP: - switch (ch) { - case '/': - state = sw_first_major_digit; - break; - default: - return NGX_HTTP_XCGI_PARSE_NO_HEADER; - } - break; - - /* the first digit of major HTTP version */ - case sw_first_major_digit: - if (ch < '1' || ch > '9') { - return NGX_HTTP_XCGI_PARSE_NO_HEADER; - } - - state = sw_major_digit; - break; - - /* the major HTTP version or dot */ - case sw_major_digit: - if (ch == '.') { - state = sw_first_minor_digit; - break; - } - - if (ch < '0' || ch > '9') { - return NGX_HTTP_XCGI_PARSE_NO_HEADER; - } - - break; - - /* the first digit of minor HTTP version */ - case sw_first_minor_digit: - if (ch < '0' || ch > '9') { - return NGX_HTTP_XCGI_PARSE_NO_HEADER; - } - - state = sw_minor_digit; - break; - - /* the minor HTTP version or the end of the request line */ - case sw_minor_digit: - if (ch == ' ') { - state = sw_status; - break; - } - - if (ch < '0' || ch > '9') { - return NGX_HTTP_XCGI_PARSE_NO_HEADER; - } - - break; - - /* HTTP status code */ - case sw_status: - if (ch == ' ') { - break; - } - - if (ch < '0' || ch > '9') { - return NGX_HTTP_XCGI_PARSE_NO_HEADER; - } - - ctx->status = ctx->status * 10 + ch - '0'; - - if (++ctx->status_count == 3) { - state = sw_space_after_status; - ctx->status_start = p - 2; - } - - break; - - /* space or end of line */ - case sw_space_after_status: - switch (ch) { - case ' ': - state = sw_status_text; - break; - case '.': /* IIS may send 403.1, 403.2, etc */ - state = sw_status_text; - break; - case CR: - state = sw_almost_done; - break; - case LF: - goto done; - default: - return NGX_HTTP_XCGI_PARSE_NO_HEADER; - } - break; - - /* any text until end of line */ - case sw_status_text: - switch (ch) { - case CR: - state = sw_almost_done; - - break; - case LF: - goto done; - } - break; - - /* end of status line */ - case sw_almost_done: - ctx->status_end = p - 1; - switch (ch) { - case LF: - goto done; - default: - return NGX_HTTP_XCGI_PARSE_NO_HEADER; - } - } - } - - u->buffer.pos = p; - r->state = state; - - return NGX_AGAIN; - -done: - - u->buffer.pos = p + 1; - - if (ctx->status_end == NULL) { - ctx->status_end = p; - } - - r->state = sw_start; - - return NGX_OK; -} - - -static ngx_int_t -ngx_http_uwsgi_process_status_line (ngx_http_request_t * r) -{ - ngx_int_t rc; - ngx_http_upstream_t *u; - ngx_http_uwsgi_ctx_t *ctx; - - ctx = ngx_http_get_module_ctx (r, ngx_http_uwsgi_module); - - if (ctx == NULL) { - return NGX_ERROR; - } - - rc = ngx_http_uwsgi_parse_status_line (r, ctx); - - if (rc == NGX_AGAIN) { - return rc; - } - - u = r->upstream; - - if (rc == NGX_HTTP_XCGI_PARSE_NO_HEADER) { - - ngx_log_error (NGX_LOG_ERR, r->connection->log, 0, - "upstream sent no valid HTTP/1.0 header"); - - r->http_version = NGX_HTTP_VERSION_9; - u->headers_in.status_n = NGX_HTTP_OK; - u->state->status = NGX_HTTP_OK; - - return NGX_OK; - } - - if (u->state) { - u->state->status = ctx->status; - } - - u->headers_in.status_n = ctx->status; - - u->headers_in.status_line.len = ctx->status_end - ctx->status_start; - u->headers_in.status_line.data = ngx_pnalloc (r->pool, - u->headers_in. - status_line.len); - if (u->headers_in.status_line.data == NULL) { - return NGX_ERROR; - } - - ngx_memcpy (u->headers_in.status_line.data, ctx->status_start, - u->headers_in.status_line.len); - - ngx_log_debug2 (NGX_LOG_DEBUG_HTTP, r->connection->log, 0, - "http uwsgi status %ui \"%V\"", - u->headers_in.status_n, &u->headers_in.status_line); - - u->process_header = ngx_http_uwsgi_process_header; - - return ngx_http_uwsgi_process_header (r); -} - - -static ngx_int_t -ngx_http_uwsgi_process_header (ngx_http_request_t * r) -{ - ngx_int_t rc; - ngx_table_elt_t *h; - ngx_http_upstream_header_t *hh; - ngx_http_upstream_main_conf_t *umcf; - - umcf = ngx_http_get_module_main_conf (r, ngx_http_upstream_module); - - for (;;) { - - rc = ngx_http_parse_header_line (r, &r->upstream->buffer, 1); - - if (rc == NGX_OK) { - - /* a header line has been parsed successfully */ - - h = ngx_list_push (&r->upstream->headers_in.headers); - if (h == NULL) { - return NGX_ERROR; - } - - h->hash = r->header_hash; - - h->key.len = r->header_name_end - r->header_name_start; - h->value.len = r->header_end - r->header_start; - - h->key.data = ngx_pnalloc (r->pool, - h->key.len + 1 + h->value.len + 1 + - h->key.len); - if (h->key.data == NULL) { - return NGX_ERROR; - } - - h->value.data = h->key.data + h->key.len + 1; - h->lowcase_key = h->key.data + h->key.len + 1 + h->value.len + 1; - - ngx_cpystrn (h->key.data, r->header_name_start, h->key.len + 1); - ngx_cpystrn (h->value.data, r->header_start, h->value.len + 1); - - if (h->key.len == r->lowcase_index) { - ngx_memcpy (h->lowcase_key, r->lowcase_header, h->key.len); - - } - else { - ngx_strlow (h->lowcase_key, h->key.data, h->key.len); - } - - hh = ngx_hash_find (&umcf->headers_in_hash, h->hash, - h->lowcase_key, h->key.len); - - if (hh && hh->handler (r, h, hh->offset) != NGX_OK) { - return NGX_ERROR; - } - - ngx_log_debug2 (NGX_LOG_DEBUG_HTTP, r->connection->log, 0, - "http uwsgi header: \"%V: %V\"", - &h->key, &h->value); - - continue; - } - - if (rc == NGX_HTTP_PARSE_HEADER_DONE) { - - /* a whole header has been parsed successfully */ - - ngx_log_debug0 (NGX_LOG_DEBUG_HTTP, r->connection->log, 0, - "http uwsgi header done"); - - /* - * if no "Server" and "Date" in header line, - * then add the special empty headers - */ - - if (r->upstream->headers_in.server == NULL) { - h = ngx_list_push (&r->upstream->headers_in.headers); - if (h == NULL) { - return NGX_ERROR; - } - - h->hash = - ngx_hash (ngx_hash - (ngx_hash - (ngx_hash (ngx_hash ('s', 'e'), 'r'), - 'v'), 'e'), 'r'); - - h->key.len = sizeof ("Server") - 1; - h->key.data = (u_char *) "Server"; - h->value.len = 0; - h->value.data = NULL; - h->lowcase_key = (u_char *) "server"; - } - - if (r->upstream->headers_in.date == NULL) { - h = ngx_list_push (&r->upstream->headers_in.headers); - if (h == NULL) { - return NGX_ERROR; - } - - h->hash = ngx_hash (ngx_hash (ngx_hash ('d', 'a'), 't'), 'e'); - - h->key.len = sizeof ("Date") - 1; - h->key.data = (u_char *) "Date"; - h->value.len = 0; - h->value.data = NULL; - h->lowcase_key = (u_char *) "date"; - } - - return NGX_OK; - } - - if (rc == NGX_AGAIN) { - return NGX_AGAIN; - } - - /* there was error while a header line parsing */ - - ngx_log_error (NGX_LOG_ERR, r->connection->log, 0, - "upstream sent invalid header"); - - return NGX_HTTP_UPSTREAM_INVALID_HEADER; - } -} - - -static void -ngx_http_uwsgi_abort_request (ngx_http_request_t * r) -{ - ngx_log_debug0 (NGX_LOG_DEBUG_HTTP, r->connection->log, 0, - "abort http uwsgi request"); - - return; -} - - -static void -ngx_http_uwsgi_finalize_request (ngx_http_request_t * r, ngx_int_t rc) -{ - ngx_log_debug0 (NGX_LOG_DEBUG_HTTP, r->connection->log, 0, - "finalize http uwsgi request"); - - return; -} - - -static ngx_int_t -ngx_http_uwsgi_add_variables (ngx_conf_t * cf) -{ - ngx_http_variable_t *var, *v; - - for (v = ngx_http_uwsgi_vars; v->name.len; v++) { - var = ngx_http_add_variable (cf, &v->name, v->flags); - if (var == NULL) { - return NGX_ERROR; - } - - var->get_handler = v->get_handler; - var->data = v->data; - } - - return NGX_OK; -} - - -static void * -ngx_http_uwsgi_create_loc_conf (ngx_conf_t * cf) -{ - ngx_http_uwsgi_loc_conf_t *conf; - - conf = ngx_pcalloc (cf->pool, sizeof (ngx_http_uwsgi_loc_conf_t)); - if (conf == NULL) { - return NULL; - } - - conf->upstream.store = NGX_CONF_UNSET; - conf->upstream.store_access = NGX_CONF_UNSET_UINT; - conf->upstream.buffering = NGX_CONF_UNSET; - conf->upstream.ignore_client_abort = NGX_CONF_UNSET; - - conf->upstream.connect_timeout = NGX_CONF_UNSET_MSEC; - conf->upstream.send_timeout = NGX_CONF_UNSET_MSEC; - conf->upstream.read_timeout = NGX_CONF_UNSET_MSEC; - - conf->upstream.send_lowat = NGX_CONF_UNSET_SIZE; - conf->upstream.buffer_size = NGX_CONF_UNSET_SIZE; - - conf->upstream.busy_buffers_size_conf = NGX_CONF_UNSET_SIZE; - conf->upstream.max_temp_file_size_conf = NGX_CONF_UNSET_SIZE; - conf->upstream.temp_file_write_size_conf = NGX_CONF_UNSET_SIZE; - - conf->upstream.pass_request_headers = NGX_CONF_UNSET; - conf->upstream.pass_request_body = NGX_CONF_UNSET; - - conf->upstream.hide_headers = NGX_CONF_UNSET_PTR; - conf->upstream.pass_headers = NGX_CONF_UNSET_PTR; - - conf->upstream.intercept_errors = NGX_CONF_UNSET; - - /* "uwsgi_cyclic_temp_file" is disabled */ - conf->upstream.cyclic_temp_file = 0; - - return conf; -} - -static char * -ngx_http_uwsgi_merge_loc_conf (ngx_conf_t * cf, void *parent, void *child) -{ - ngx_http_uwsgi_loc_conf_t *prev = parent; - ngx_http_uwsgi_loc_conf_t *conf = child; - - u_char *p; - size_t size; - uintptr_t *code; - ngx_uint_t i; - ngx_keyval_t *src; - ngx_hash_init_t hash; - ngx_http_script_compile_t sc; - ngx_http_script_copy_code_t *copy; - - if (conf->upstream.store != 0) { - ngx_conf_merge_value (conf->upstream.store, prev->upstream.store, 0); - - if (conf->upstream.store_lengths == NULL) { - conf->upstream.store_lengths = prev->upstream.store_lengths; - conf->upstream.store_values = prev->upstream.store_values; - } - } - - ngx_conf_merge_uint_value (conf->upstream.store_access, - prev->upstream.store_access, 0600); - - ngx_conf_merge_value (conf->upstream.buffering, - prev->upstream.buffering, 1); - - ngx_conf_merge_value (conf->upstream.ignore_client_abort, - prev->upstream.ignore_client_abort, 0); - - ngx_conf_merge_msec_value (conf->upstream.connect_timeout, - prev->upstream.connect_timeout, 60000); - - ngx_conf_merge_msec_value (conf->upstream.send_timeout, - prev->upstream.send_timeout, 60000); - - ngx_conf_merge_msec_value (conf->upstream.read_timeout, - prev->upstream.read_timeout, 60000); - - ngx_conf_merge_size_value (conf->upstream.send_lowat, - prev->upstream.send_lowat, 0); - - ngx_conf_merge_size_value (conf->upstream.buffer_size, - prev->upstream.buffer_size, - (size_t) ngx_pagesize); - - - ngx_conf_merge_bufs_value (conf->upstream.bufs, prev->upstream.bufs, - 8, ngx_pagesize); - - if (conf->upstream.bufs.num < 2) { - ngx_conf_log_error (NGX_LOG_EMERG, cf, 0, - "there must be at least 2 \"uwsgi_buffers\""); - return NGX_CONF_ERROR; - } - - - size = conf->upstream.buffer_size; - if (size < conf->upstream.bufs.size) { - size = conf->upstream.bufs.size; - } - - - ngx_conf_merge_size_value (conf->upstream.busy_buffers_size_conf, - prev->upstream.busy_buffers_size_conf, - NGX_CONF_UNSET_SIZE); - - if (conf->upstream.busy_buffers_size_conf == NGX_CONF_UNSET_SIZE) { - conf->upstream.busy_buffers_size = 2 * size; - } - else { - conf->upstream.busy_buffers_size = - conf->upstream.busy_buffers_size_conf; - } - - if (conf->upstream.busy_buffers_size < size) { - ngx_conf_log_error (NGX_LOG_EMERG, cf, 0, - "\"uwsgi_busy_buffers_size\" must be equal or bigger than " - "maximum of the value of \"uwsgi_buffer_size\" and " - "one of the \"uwsgi_buffers\""); - - return NGX_CONF_ERROR; - } - - if (conf->upstream.busy_buffers_size - > (conf->upstream.bufs.num - 1) * conf->upstream.bufs.size) { - ngx_conf_log_error (NGX_LOG_EMERG, cf, 0, - "\"uwsgi_busy_buffers_size\" must be less than " - "the size of all \"uwsgi_buffers\" minus one buffer"); - - return NGX_CONF_ERROR; - } - - - ngx_conf_merge_size_value (conf->upstream.temp_file_write_size_conf, - prev->upstream.temp_file_write_size_conf, - NGX_CONF_UNSET_SIZE); - - if (conf->upstream.temp_file_write_size_conf == NGX_CONF_UNSET_SIZE) { - conf->upstream.temp_file_write_size = 2 * size; - } - else { - conf->upstream.temp_file_write_size = - conf->upstream.temp_file_write_size_conf; - } - - if (conf->upstream.temp_file_write_size < size) { - ngx_conf_log_error (NGX_LOG_EMERG, cf, 0, - "\"uwsgi_temp_file_write_size\" must be equal or bigger than " - "maximum of the value of \"uwsgi_buffer_size\" and " - "one of the \"uwsgi_buffers\""); - - return NGX_CONF_ERROR; - } - - - ngx_conf_merge_size_value (conf->upstream.max_temp_file_size_conf, - prev->upstream.max_temp_file_size_conf, - NGX_CONF_UNSET_SIZE); - - if (conf->upstream.max_temp_file_size_conf == NGX_CONF_UNSET_SIZE) { - conf->upstream.max_temp_file_size = 1024 * 1024 * 1024; - } - else { - conf->upstream.max_temp_file_size = - conf->upstream.max_temp_file_size_conf; - } - - if (conf->upstream.max_temp_file_size != 0 - && conf->upstream.max_temp_file_size < size) { - ngx_conf_log_error (NGX_LOG_EMERG, cf, 0, - "\"uwsgi_max_temp_file_size\" must be equal to zero to disable " - "the temporary files usage or must be equal or bigger than " - "maximum of the value of \"uwsgi_buffer_size\" and " - "one of the \"uwsgi_buffers\""); - - return NGX_CONF_ERROR; - } - - - ngx_conf_merge_bitmask_value (conf->upstream.ignore_headers, - prev->upstream.ignore_headers, - NGX_CONF_BITMASK_SET); - - - ngx_conf_merge_bitmask_value (conf->upstream.next_upstream, - prev->upstream.next_upstream, - (NGX_CONF_BITMASK_SET - | NGX_HTTP_UPSTREAM_FT_ERROR - | NGX_HTTP_UPSTREAM_FT_TIMEOUT)); - - if (conf->upstream.next_upstream & NGX_HTTP_UPSTREAM_FT_OFF) { - conf->upstream.next_upstream = NGX_CONF_BITMASK_SET - | NGX_HTTP_UPSTREAM_FT_OFF; - } - - if (ngx_conf_merge_path_value (cf, &conf->upstream.temp_path, - prev->upstream.temp_path, - &ngx_http_uwsgi_temp_path) != NGX_OK) { - return NGX_CONF_ERROR; - } - - ngx_conf_merge_value (conf->upstream.pass_request_headers, - prev->upstream.pass_request_headers, 1); - ngx_conf_merge_value (conf->upstream.pass_request_body, - prev->upstream.pass_request_body, 1); - - ngx_conf_merge_value (conf->upstream.intercept_errors, - prev->upstream.intercept_errors, 0); - - ngx_conf_merge_str_value(conf->uwsgi_string, prev->uwsgi_string, ""); - - hash.max_size = 512; - hash.bucket_size = ngx_align (64, ngx_cacheline_size); - hash.name = "uwsgi_hide_headers_hash"; - - if (ngx_http_upstream_hide_headers_hash (cf, &conf->upstream, - &prev->upstream, - ngx_http_uwsgi_hide_headers, - &hash) != NGX_OK) { - return NGX_CONF_ERROR; - } - - if (conf->upstream.upstream == NULL) { - conf->upstream.upstream = prev->upstream.upstream; - } - - if (conf->uwsgi_lengths == NULL) { - conf->uwsgi_lengths = prev->uwsgi_lengths; - conf->uwsgi_values = prev->uwsgi_values; - } - - if (conf->modifier1 == 0) { - conf->modifier1 = prev->modifier1; - } - - if (conf->modifier2 == 0) { - conf->modifier2 = prev->modifier2; - } - - if (conf->params_source == NULL) { - conf->flushes = prev->flushes; - conf->params_len = prev->params_len; - conf->params = prev->params; - conf->params_source = prev->params_source; - - if (conf->params_source == NULL) { - return NGX_CONF_OK; - } - } - - conf->params_len = ngx_array_create (cf->pool, 64, 1); - if (conf->params_len == NULL) { - return NGX_CONF_ERROR; - } - - conf->params = ngx_array_create (cf->pool, 512, 1); - if (conf->params == NULL) { - return NGX_CONF_ERROR; - } - - src = conf->params_source->elts; - for (i = 0; i < conf->params_source->nelts; i++) { - - if (ngx_http_script_variables_count (&src[i].value) == 0) { - copy = ngx_array_push_n (conf->params_len, - sizeof (ngx_http_script_copy_code_t)); - if (copy == NULL) { - return NGX_CONF_ERROR; - } - - copy->code = (ngx_http_script_code_pt) - ngx_http_script_copy_len_code; - copy->len = src[i].key.len; - - - copy = ngx_array_push_n (conf->params_len, - sizeof (ngx_http_script_copy_code_t)); - if (copy == NULL) { - return NGX_CONF_ERROR; - } - - copy->code = (ngx_http_script_code_pt) - ngx_http_script_copy_len_code; - copy->len = src[i].value.len; - - - size = (sizeof (ngx_http_script_copy_code_t) - + src[i].key.len + src[i].value.len - + sizeof (uintptr_t) - 1) & ~(sizeof (uintptr_t) - 1); - - copy = ngx_array_push_n (conf->params, size); - if (copy == NULL) { - return NGX_CONF_ERROR; - } - - copy->code = ngx_http_script_copy_code; - copy->len = src[i].key.len + src[i].value.len; - - p = (u_char *) copy + sizeof (ngx_http_script_copy_code_t); - - p = ngx_cpymem (p, src[i].key.data, src[i].key.len); - ngx_memcpy (p, src[i].value.data, src[i].value.len); - - } - else { - copy = ngx_array_push_n (conf->params_len, - sizeof (ngx_http_script_copy_code_t)); - if (copy == NULL) { - return NGX_CONF_ERROR; - } - - copy->code = (ngx_http_script_code_pt) - ngx_http_script_copy_len_code; - copy->len = src[i].key.len; - - - size = (sizeof (ngx_http_script_copy_code_t) - + src[i].key.len + sizeof (uintptr_t) - 1) - & ~(sizeof (uintptr_t) - 1); - - copy = ngx_array_push_n (conf->params, size); - if (copy == NULL) { - return NGX_CONF_ERROR; - } - - copy->code = ngx_http_script_copy_code; - copy->len = src[i].key.len; - - p = (u_char *) copy + sizeof (ngx_http_script_copy_code_t); - ngx_memcpy (p, src[i].key.data, src[i].key.len); - - - ngx_memzero (&sc, sizeof (ngx_http_script_compile_t)); - - sc.cf = cf; - sc.source = &src[i].value; - sc.flushes = &conf->flushes; - sc.lengths = &conf->params_len; - sc.values = &conf->params; - - if (ngx_http_script_compile (&sc) != NGX_OK) { - return NGX_CONF_ERROR; - } - } - - code = ngx_array_push_n (conf->params_len, sizeof (uintptr_t)); - if (code == NULL) { - return NGX_CONF_ERROR; - } - - *code = (uintptr_t) NULL; - - - code = ngx_array_push_n (conf->params, sizeof (uintptr_t)); - if (code == NULL) { - return NGX_CONF_ERROR; - } - - *code = (uintptr_t) NULL; - } - - code = ngx_array_push_n (conf->params_len, sizeof (uintptr_t)); - if (code == NULL) { - return NGX_CONF_ERROR; - } - - *code = (uintptr_t) NULL; - - return NGX_CONF_OK; -} - - -static char * -ngx_http_uwsgi_pass (ngx_conf_t * cf, ngx_command_t * cmd, void *conf) -{ - ngx_http_uwsgi_loc_conf_t *uwcf = conf; - - ngx_url_t u; - ngx_str_t *value, *url; - ngx_uint_t n; - ngx_http_core_loc_conf_t *clcf; - ngx_http_script_compile_t sc; - - if (uwcf->upstream.upstream || uwcf->uwsgi_lengths) { - return "is duplicate"; - } - - clcf = ngx_http_conf_get_module_loc_conf (cf, ngx_http_core_module); - clcf->handler = ngx_http_uwsgi_handler; - - value = cf->args->elts; - - url = &value[1]; - - n = ngx_http_script_variables_count (url); - - if (n) { - - ngx_memzero (&sc, sizeof (ngx_http_script_compile_t)); - - sc.cf = cf; - sc.source = url; - sc.lengths = &uwcf->uwsgi_lengths; - sc.values = &uwcf->uwsgi_values; - sc.variables = n; - sc.complete_lengths = 1; - sc.complete_values = 1; - - if (ngx_http_script_compile (&sc) != NGX_OK) { - return NGX_CONF_ERROR; - } - - return NGX_CONF_OK; - } - - ngx_memzero (&u, sizeof (ngx_url_t)); - - u.url = value[1]; - u.no_resolve = 1; - - uwcf->upstream.upstream = ngx_http_upstream_add (cf, &u, 0); - if (uwcf->upstream.upstream == NULL) { - return NGX_CONF_ERROR; - } - - if (clcf->name.data[clcf->name.len - 1] == '/') { - clcf->auto_redirect = 1; - } - - return NGX_CONF_OK; -} - -static char * -ngx_http_uwsgi_modifier1 (ngx_conf_t * cf, ngx_command_t * cmd, void *conf) -{ - ngx_http_uwsgi_loc_conf_t *uwcf = conf; - ngx_str_t *value; - - value = cf->args->elts; - - uwcf->modifier1 = (u_char) ngx_atoi (value[1].data, value[1].len); - - return NGX_CONF_OK; -} - -static char * -ngx_http_uwsgi_modifier2 (ngx_conf_t * cf, ngx_command_t * cmd, void *conf) -{ - ngx_http_uwsgi_loc_conf_t *uwcf = conf; - - ngx_str_t *value; - - value = cf->args->elts; - - uwcf->modifier2 = (u_char) ngx_atoi (value[1].data, value[1].len); - return NGX_CONF_OK; -} - diff --git a/nginx/uwsgi_params b/nginx/uwsgi_params deleted file mode 100644 index 510d5ed3..00000000 --- a/nginx/uwsgi_params +++ /dev/null @@ -1,16 +0,0 @@ - -uwsgi_param QUERY_STRING $query_string; -uwsgi_param REQUEST_METHOD $request_method; -uwsgi_param CONTENT_TYPE $content_type; -uwsgi_param CONTENT_LENGTH $content_length; - -uwsgi_param REQUEST_URI $request_uri; -uwsgi_param PATH_INFO $document_uri; -uwsgi_param DOCUMENT_ROOT $document_root; -uwsgi_param SERVER_PROTOCOL $server_protocol; - -uwsgi_param REMOTE_ADDR $remote_addr; -uwsgi_param REMOTE_PORT $remote_port; -uwsgi_param SERVER_ADDR $server_addr; -uwsgi_param SERVER_PORT $server_port; -uwsgi_param SERVER_NAME $server_name;