diff --git a/core/errors.c b/core/errors.c index 741e79f8..f09ef392 100644 --- a/core/errors.c +++ b/core/errors.c @@ -7,3 +7,33 @@ void uwsgi_500(struct wsgi_request *wsgi_req) { uwsgi_response_write_body_do(wsgi_req, "Internal Server Error", 21); } + +void uwsgi_404(struct wsgi_request *wsgi_req) { + if (uwsgi_response_prepare_headers(wsgi_req, "404 Not Found", 13)) return; + if (uwsgi_response_add_header(wsgi_req, "Content-Type", 12, "text/plain", 10)) return; + uwsgi_response_write_body_do(wsgi_req, "Not Found", 9); +} + +void uwsgi_403(struct wsgi_request *wsgi_req) { + if (uwsgi_response_prepare_headers(wsgi_req, "403 Forbidden", 13)) return; + if (uwsgi_response_add_header(wsgi_req, "Content-Type", 12, "text/plain", 10)) return; + uwsgi_response_write_body_do(wsgi_req, "Forbidden", 9); +} + +void uwsgi_redirect_to_slash(struct wsgi_request *wsgi_req) { + + if (uwsgi_response_prepare_headers(wsgi_req, "301 Moved Permanently", 21)) return; + struct uwsgi_buffer *ub = uwsgi_buffer_new(wsgi_req->path_info_len + 1 + wsgi_req->query_string_len + 1 + 8); + if (uwsgi_buffer_append(ub, wsgi_req->path_info, wsgi_req->path_info_len)) goto end; + if (uwsgi_buffer_append(ub, "/", 1)) goto end; + + if (wsgi_req->query_string_len > 0) { + if (uwsgi_buffer_append(ub, "?", 1)) goto end; + if (uwsgi_buffer_append(ub, wsgi_req->query_string, wsgi_req->query_string_len)) goto end; + } + uwsgi_response_add_header(wsgi_req, "Location", 8, ub->buf, ub->pos); +end: + uwsgi_buffer_destroy(ub); + return; +} + diff --git a/plugins/cgi/cgi_plugin.c b/plugins/cgi/cgi_plugin.c index 814b22b4..4557380a 100644 --- a/plugins/cgi/cgi_plugin.c +++ b/plugins/cgi/cgi_plugin.c @@ -66,23 +66,6 @@ struct uwsgi_option uwsgi_cgi_options[] = { }; -void uwsgi_cgi_redirect_to_slash(struct wsgi_request *wsgi_req) { - - if (uwsgi_response_prepare_headers(wsgi_req, "301 Moved Permanently", 21)) return; - struct uwsgi_buffer *ub = uwsgi_buffer_new(wsgi_req->path_info_len + 1 + wsgi_req->query_string_len + 1 + 8); - if (uwsgi_buffer_append(ub, wsgi_req->path_info, wsgi_req->path_info_len)) goto end; - if (uwsgi_buffer_append(ub, "/", 1)) goto end; - - if (wsgi_req->query_string_len > 0) { - if (uwsgi_buffer_append(ub, "?", 1)) goto end; - if (uwsgi_buffer_append(ub, wsgi_req->query_string, wsgi_req->query_string_len)) goto end; - } - uwsgi_response_add_header(wsgi_req, "Location", 8, ub->buf, ub->pos); -end: - uwsgi_buffer_destroy(ub); - return; -} - void uwsgi_cgi_apps() { struct uwsgi_dyn_dict *udd = uc.mountpoint; @@ -497,7 +480,7 @@ int uwsgi_cgi_request(struct wsgi_request *wsgi_req) { // add / to directories if (wsgi_req->path_info_len == 0 || (wsgi_req->path_info_len > 0 && wsgi_req->path_info[wsgi_req->path_info_len-1] != '/')) { - uwsgi_cgi_redirect_to_slash(wsgi_req); + uwsgi_redirect_to_slash(wsgi_req); if (need_free) free(docroot); return UWSGI_OK; diff --git a/plugins/php/php_plugin.c b/plugins/php/php_plugin.c index 1c16b3bc..e25e1d9d 100644 --- a/plugins/php/php_plugin.c +++ b/plugins/php/php_plugin.c @@ -62,49 +62,12 @@ struct uwsgi_option uwsgi_php_options[] = { }; -void uwsgi_php_redirect_to_slash(struct wsgi_request *wsgi_req) { - - struct iovec iov[6]; - - wsgi_req->status = 301; - iov[0].iov_base = wsgi_req->protocol; - iov[0].iov_len = wsgi_req->protocol_len; - iov[1].iov_base = " 301 Moved Permanently\r\n"; - iov[1].iov_len = 24; - wsgi_req->headers_size += wsgi_req->socket->proto_writev_header(wsgi_req, iov, 2); - - iov[0].iov_base = "Location: "; - iov[0].iov_len = 10; - iov[1].iov_base = wsgi_req->path_info; - iov[1].iov_len = wsgi_req->path_info_len; - iov[2].iov_base = "/"; - iov[2].iov_len = 1; - - if (wsgi_req->query_string_len > 0) { - iov[3].iov_base = "?"; - iov[3].iov_len = 1; - iov[4].iov_base = wsgi_req->query_string; - iov[4].iov_len = wsgi_req->query_string_len; - iov[5].iov_base = "\r\n\r\n"; - iov[5].iov_len = 4; - wsgi_req->headers_size += wsgi_req->socket->proto_writev_header(wsgi_req, iov, 6); - wsgi_req->header_cnt++; - } - else { - iov[3].iov_base = "\r\n\r\n"; - iov[3].iov_len = 4; - wsgi_req->headers_size += wsgi_req->socket->proto_writev_header(wsgi_req, iov, 4); - wsgi_req->header_cnt++; - } -} - - static int sapi_uwsgi_ub_write(const char *str, uint str_length TSRMLS_DC) { struct wsgi_request *wsgi_req = (struct wsgi_request *) SG(server_context); - wsgi_req->response_size += wsgi_req->socket->proto_write(wsgi_req, (char *) str, str_length); + uwsgi_response_write_body_do(wsgi_req, (char *) str, str_length); if (wsgi_req->write_errors > uwsgi.write_errors_tolerance) { php_handle_aborted_connection(); return -1; @@ -112,117 +75,35 @@ static int sapi_uwsgi_ub_write(const char *str, uint str_length TSRMLS_DC) return str_length; } -void uwsgi_php_404(struct wsgi_request *wsgi_req) { - - wsgi_req->status = 404; - wsgi_req->headers_size += wsgi_req->socket->proto_write(wsgi_req, "HTTP/1.0 404 Not Found\r\nContent-Type: text/plain\r\n\r\nNot Found", 61); -} - -void uwsgi_php_403(struct wsgi_request *wsgi_req) { - - wsgi_req->status = 403; - wsgi_req->headers_size += wsgi_req->socket->proto_write(wsgi_req, "HTTP/1.0 403 Forbidden\r\nContent-Type: text/plain\r\n\r\nForbidden", 61); - -} - - static int sapi_uwsgi_send_headers(sapi_headers_struct *sapi_headers) { sapi_header_struct *h; zend_llist_position pos; - struct iovec iov[6]; - char status[4]; - struct http_status_codes *http_sc; if (SG(request_info).no_headers == 1) { return SAPI_HEADER_SENT_SUCCESSFULLY; } struct wsgi_request *wsgi_req = (struct wsgi_request *) SG(server_context); - wsgi_req->status = SG(sapi_headers).http_response_code; - if (!wsgi_req->status) wsgi_req->status = 200; if (!SG(sapi_headers).http_status_line) { - - iov[0].iov_base = wsgi_req->protocol; - iov[0].iov_len = wsgi_req->protocol_len; - - - iov[1].iov_base = " "; - iov[1].iov_len = 1; - - uwsgi_num2str2n(wsgi_req->status, status, 4); - - iov[2].iov_base = status; - iov[2].iov_len = 3; - - iov[3].iov_base = " "; - iov[3].iov_len = 1; - - // get the status code - for (http_sc = hsc; http_sc->message != NULL; http_sc++) { - if (!strncmp(http_sc->key, status, 3)) { - iov[4].iov_base = (char *) http_sc->message; - iov[4].iov_len = http_sc->message_size; - break; - } - } - - if (iov[4].iov_len == 0) { - iov[4].iov_base = "Unknown"; - iov[4].iov_len = 7; - } - - iov[5].iov_base = "\r\n"; - iov[5].iov_len = 2; - - wsgi_req->headers_size += wsgi_req->socket->proto_writev_header(wsgi_req, iov, 6); + char status[4]; + int hrc = SG(sapi_headers).http_response_code; + if (!hrc) hrc = 200; + uwsgi_num2str2n(hrc, status, 4); + uwsgi_response_prepare_headers(wsgi_req, status, 3); } else { - iov[0].iov_base = SG(sapi_headers).http_status_line; - iov[0].iov_len = strlen(iov[0].iov_base); - iov[1].iov_base = "\r\n"; - iov[1].iov_len = 2; - wsgi_req->headers_size += wsgi_req->socket->proto_writev_header(wsgi_req, iov, 2); + char *sl = SG(sapi_headers).http_status_line; + uwsgi_response_prepare_headers(wsgi_req, sl, strlen(sl)); } h = zend_llist_get_first_ex(&sapi_headers->headers, &pos); while (h) { - iov[0].iov_base = h->header; - iov[0].iov_len = h->header_len; - iov[1].iov_base = "\r\n"; - iov[1].iov_len = 2; - - wsgi_req->headers_size += wsgi_req->socket->proto_writev_header(wsgi_req, iov, 2); - wsgi_req->header_cnt++; + uwsgi_response_add_header(wsgi_req, NULL, 0, h->header, h->header_len); h = zend_llist_get_next_ex(&sapi_headers->headers, &pos); } - struct uwsgi_string_list *ah = uwsgi.additional_headers; - while(ah) { - iov[0].iov_base = ah->value; - iov[0].iov_len = ah->len; - iov[1].iov_base = "\r\n"; - iov[1].iov_len = 2; - wsgi_req->headers_size += wsgi_req->socket->proto_writev_header(wsgi_req, iov, 2); - wsgi_req->header_cnt++; - ah = ah->next; - } - - ah = wsgi_req->additional_headers; - while(ah) { - iov[0].iov_base = ah->value; - iov[0].iov_len = ah->len; - iov[1].iov_base = "\r\n"; - iov[1].iov_len = 2; - wsgi_req->headers_size += wsgi_req->socket->proto_writev_header(wsgi_req, iov, 2); - wsgi_req->header_cnt++; - ah = ah->next; - } - - - wsgi_req->headers_size += wsgi_req->socket->proto_write_header(wsgi_req, "\r\n", 2); - return SAPI_HEADER_SENT_SUCCESSFULLY; } @@ -851,7 +732,7 @@ oldstyle: filename = uwsgi_str(uphp.fallback); } else { - uwsgi_php_404(wsgi_req); + uwsgi_404(wsgi_req); return -1; } } @@ -872,7 +753,7 @@ oldstyle: if (!realpath(filename, real_filename)) { free(filename); - uwsgi_php_404(wsgi_req); + uwsgi_404(wsgi_req); return -1; } @@ -887,7 +768,7 @@ oldstyle: } usl = usl->next; } - uwsgi_php_403(wsgi_req); + uwsgi_403(wsgi_req); uwsgi_log("PHP security error: %s is not under an allowed docroot\n", real_filename); return -1; } @@ -895,7 +776,7 @@ oldstyle: secure: if (stat(real_filename, &php_stat)) { - uwsgi_php_404(wsgi_req); + uwsgi_404(wsgi_req); return UWSGI_OK; } @@ -905,7 +786,7 @@ secure: if (orig_path_info_len == 0 || (orig_path_info_len > 0 && orig_path_info[orig_path_info_len-1] != '/')) { wsgi_req->path_info = orig_path_info; wsgi_req->path_info_len = orig_path_info_len; - uwsgi_php_redirect_to_slash(wsgi_req); + uwsgi_redirect_to_slash(wsgi_req); return UWSGI_OK; } struct uwsgi_string_list *upi = uphp.index; @@ -926,7 +807,7 @@ secure: } if (!found) { - uwsgi_php_404(wsgi_req); + uwsgi_404(wsgi_req); return UWSGI_OK; } @@ -945,7 +826,7 @@ secure: } usl = usl->next; } - uwsgi_php_403(wsgi_req); + uwsgi_403(wsgi_req); uwsgi_log("PHP security error: %s does not end with an allowed extension\n", real_filename); return -1; } @@ -963,7 +844,7 @@ secure2: } usl = usl->next; } - uwsgi_php_403(wsgi_req); + uwsgi_403(wsgi_req); uwsgi_log("PHP security error: %s is not an allowed script\n", real_filename); return -1; } @@ -1008,7 +889,7 @@ secure3: file_handle.opened_path = NULL; if (php_request_startup(TSRMLS_C) == FAILURE) { - internal_server_error(wsgi_req, "unable to start php request"); + uwsgi_500(wsgi_req); return -1; } diff --git a/uwsgi.h b/uwsgi.h index a1027eda..35b2e8bb 100644 --- a/uwsgi.h +++ b/uwsgi.h @@ -2405,6 +2405,7 @@ void uwsgi_xml_config(char *, struct wsgi_request *, char *[]); void uwsgi_500(struct wsgi_request *); void uwsgi_403(struct wsgi_request *); void uwsgi_404(struct wsgi_request *); +void uwsgi_redirect_to_slash(struct wsgi_request *); #ifdef UWSGI_SNMP void manage_snmp(int, uint8_t *, int, struct sockaddr_in *);