mirror of
https://github.com/apache/httpd.git
synced 2025-08-08 15:02:10 +03:00
Fold in ALv2 licensed UWSGI proxy (sub)module as acknowledged via
https://github.com/unbit/uwsgi/issues/1636 git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@1810358 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
78
docs/manual/mod/mod_proxy_uwsgi.xml
Normal file
78
docs/manual/mod/mod_proxy_uwsgi.xml
Normal file
@@ -0,0 +1,78 @@
|
||||
<?xml version="1.0"?>
|
||||
<!DOCTYPE modulesynopsis SYSTEM "../style/modulesynopsis.dtd">
|
||||
<?xml-stylesheet type="text/xsl" href="../style/manual.en.xsl"?>
|
||||
<!-- $LastChangedRevision: 1755335 $ -->
|
||||
|
||||
<!--
|
||||
Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
contributor license agreements. See the NOTICE file distributed with
|
||||
this work for additional information regarding copyright ownership.
|
||||
The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
(the "License"); you may not use this file except in compliance with
|
||||
the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
|
||||
<modulesynopsis metafile="mod_proxy_uwsgi.xml.meta">
|
||||
|
||||
<name>mod_proxy_uwsgi</name>
|
||||
<description>UWSGI gateway module for <module>mod_proxy</module></description>
|
||||
<status>Extension</status>
|
||||
<sourcefile>mod_proxy_uwsgi.c</sourcefile>
|
||||
<identifier>proxy_uwsgi_module</identifier>
|
||||
|
||||
<summary>
|
||||
<p>This module <em>requires</em> the service of <module
|
||||
>mod_proxy</module>. It provides support for the
|
||||
<a href="http://uwsgi-docs.readthedocs.io/en/latest/index.html">UWSGI protocol</a>.</p>
|
||||
|
||||
<p>Thus, in order to get the ability of handling the UWSGI protocol,
|
||||
<module>mod_proxy</module> and <module>mod_proxy_uwsgi</module> have to
|
||||
be present in the server.</p>
|
||||
|
||||
<note type="warning"><title>Warning</title>
|
||||
<p>Do not enable proxying until you have <a
|
||||
href="mod_proxy.html#access">secured your server</a>. Open proxy
|
||||
servers are dangerous both to your network and to the Internet at
|
||||
large.</p>
|
||||
</note>
|
||||
</summary>
|
||||
|
||||
<seealso><module>mod_proxy</module></seealso>
|
||||
<seealso><module>mod_proxy_balancer</module></seealso>
|
||||
|
||||
<section id="examples"><title>Examples</title>
|
||||
<p>Remember, in order to make the following examples work, you have to
|
||||
enable <module>mod_proxy</module> and <module>mod_proxy_uwsgi</module>.</p>
|
||||
|
||||
<example><title>Simple gateway</title>
|
||||
<highlight language="config">
|
||||
ProxyPass "/uwsgi-bin/" "uwsgi://localhost:4000/"
|
||||
</highlight>
|
||||
</example>
|
||||
|
||||
<p>The balanced gateway needs <module>mod_proxy_balancer</module> and
|
||||
at least one load balancer algorithm module, such as
|
||||
<module>mod_lbmethod_byrequests</module>, in addition to the proxy
|
||||
modules listed above. <module>mod_lbmethod_byrequests</module> is the
|
||||
default, and will be used for this example configuration.</p>
|
||||
|
||||
<example><title>Balanced gateway</title>
|
||||
<highlight language="config">
|
||||
ProxyPass "/uwsgi-bin/" "balancer://somecluster/"
|
||||
<Proxy balancer://somecluster>
|
||||
BalancerMember uwsgi://localhost:4000
|
||||
BalancerMember uwsgi://localhost:4001
|
||||
</Proxy>
|
||||
</highlight>
|
||||
</example>
|
||||
</section>
|
||||
|
||||
</modulesynopsis>
|
12
docs/manual/mod/mod_proxy_uwsgi.xml.meta
Normal file
12
docs/manual/mod/mod_proxy_uwsgi.xml.meta
Normal file
@@ -0,0 +1,12 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<!-- GENERATED FROM XML: DO NOT EDIT -->
|
||||
|
||||
<metafile reference="mod_proxy_uwsgi.xml">
|
||||
<basename>mod_proxy_uwsgi</basename>
|
||||
<path>/mod/</path>
|
||||
<relpath>..</relpath>
|
||||
|
||||
<variants>
|
||||
<variant>en</variant>
|
||||
</variants>
|
||||
</metafile>
|
@@ -10,6 +10,7 @@ proxy_ftp_objs="mod_proxy_ftp.lo"
|
||||
proxy_http_objs="mod_proxy_http.lo"
|
||||
proxy_fcgi_objs="mod_proxy_fcgi.lo"
|
||||
proxy_scgi_objs="mod_proxy_scgi.lo"
|
||||
proxy_uwsgi_objs="mod_proxy_uwsgi.lo"
|
||||
proxy_fdpass_objs="mod_proxy_fdpass.lo"
|
||||
proxy_ajp_objs="mod_proxy_ajp.lo ajp_header.lo ajp_link.lo ajp_msg.lo ajp_utils.lo"
|
||||
proxy_wstunnel_objs="mod_proxy_wstunnel.lo"
|
||||
@@ -24,6 +25,7 @@ case "$host" in
|
||||
proxy_http_objs="$proxy_http_objs mod_proxy.la"
|
||||
proxy_fcgi_objs="$proxy_fcgi_objs mod_proxy.la"
|
||||
proxy_scgi_objs="$proxy_scgi_objs mod_proxy.la"
|
||||
proxy_uwsgi_objs="$proxy_uwsgi_objs mod_proxy.la"
|
||||
proxy_fdpass_objs="$proxy_fdpass_objs mod_proxy.la"
|
||||
proxy_ajp_objs="$proxy_ajp_objs mod_proxy.la"
|
||||
proxy_wstunnel_objs="$proxy_wstunnel_objs mod_proxy.la"
|
||||
@@ -36,6 +38,7 @@ APACHE_MODULE(proxy_ftp, Apache proxy FTP module. Requires --enable-proxy., $pr
|
||||
APACHE_MODULE(proxy_http, Apache proxy HTTP module. Requires --enable-proxy., $proxy_http_objs, , most, , proxy)
|
||||
APACHE_MODULE(proxy_fcgi, Apache proxy FastCGI module. Requires --enable-proxy., $proxy_fcgi_objs, , most, , proxy)
|
||||
APACHE_MODULE(proxy_scgi, Apache proxy SCGI module. Requires --enable-proxy., $proxy_scgi_objs, , most, , proxy)
|
||||
APACHE_MODULE(proxy_uwsgi, Apache proxy UWSGI module. Requires --enable-proxy., $proxy_uwsgi_objs, , most, , proxy)
|
||||
APACHE_MODULE(proxy_fdpass, Apache proxy to Unix Daemon Socket module. Requires --enable-proxy., $proxy_fdpass_objs, , most, [
|
||||
AC_CHECK_DECL(CMSG_DATA,,, [
|
||||
#include <sys/types.h>
|
||||
|
520
modules/proxy/mod_proxy_uwsgi.c
Normal file
520
modules/proxy/mod_proxy_uwsgi.c
Normal file
@@ -0,0 +1,520 @@
|
||||
/* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/*
|
||||
|
||||
*** mod_proxy_uwsgi ***
|
||||
|
||||
Copyright 2009-2017 Unbit S.a.s. <info@unbit.it>
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
*/
|
||||
|
||||
#define APR_WANT_MEMFUNC
|
||||
#define APR_WANT_STRFUNC
|
||||
#include "apr_strings.h"
|
||||
#include "apr_hooks.h"
|
||||
#include "apr_optional_hooks.h"
|
||||
#include "apr_buckets.h"
|
||||
|
||||
#include "httpd.h"
|
||||
#include "http_config.h"
|
||||
#include "http_log.h"
|
||||
#include "http_protocol.h"
|
||||
#include "http_request.h"
|
||||
#include "util_script.h"
|
||||
|
||||
#include "mod_proxy.h"
|
||||
|
||||
|
||||
#define UWSGI_SCHEME "uwsgi"
|
||||
#define UWSGI_DEFAULT_PORT 3031
|
||||
|
||||
module AP_MODULE_DECLARE_DATA proxy_uwsgi_module;
|
||||
|
||||
|
||||
static int uwsgi_canon(request_rec *r, char *url)
|
||||
{
|
||||
char *host, sport[sizeof(":65535")];
|
||||
const char *err, *path;
|
||||
apr_port_t port = UWSGI_DEFAULT_PORT;
|
||||
|
||||
if (strncasecmp(url, UWSGI_SCHEME "://", sizeof(UWSGI_SCHEME) + 2)) {
|
||||
return DECLINED;
|
||||
}
|
||||
url += sizeof(UWSGI_SCHEME); /* Keep slashes */
|
||||
|
||||
err = ap_proxy_canon_netloc(r->pool, &url, NULL, NULL, &host, &port);
|
||||
if (err) {
|
||||
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
|
||||
"error parsing URL %s: %s", url, err);
|
||||
return HTTP_BAD_REQUEST;
|
||||
}
|
||||
|
||||
if (port != UWSGI_DEFAULT_PORT)
|
||||
apr_snprintf(sport, sizeof(sport), ":%u", port);
|
||||
else
|
||||
sport[0] = '\0';
|
||||
|
||||
if (ap_strchr(host, ':')) { /* if literal IPv6 address */
|
||||
host = apr_pstrcat(r->pool, "[", host, "]", NULL);
|
||||
}
|
||||
|
||||
path = ap_proxy_canonenc(r->pool, url, strlen(url), enc_path, 0,
|
||||
r->proxyreq);
|
||||
if (!path) {
|
||||
return HTTP_BAD_REQUEST;
|
||||
}
|
||||
|
||||
r->filename = apr_pstrcat(r->pool, "proxy:" UWSGI_SCHEME "://", host, sport, "/",
|
||||
path, NULL);
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
|
||||
static int uwsgi_send(proxy_conn_rec *conn, const char *buf, apr_size_t length,
|
||||
request_rec *r)
|
||||
{
|
||||
apr_status_t rv;
|
||||
apr_size_t written;
|
||||
|
||||
while (length > 0) {
|
||||
written = length;
|
||||
if ((rv = apr_socket_send(conn->sock, buf, &written)) != APR_SUCCESS) {
|
||||
ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r,
|
||||
"sending data to %s:%u failed",
|
||||
conn->hostname, conn->port);
|
||||
return HTTP_SERVICE_UNAVAILABLE;
|
||||
}
|
||||
|
||||
/* count for stats */
|
||||
conn->worker->s->transferred += written;
|
||||
buf += written;
|
||||
length -= written;
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Send uwsgi header block
|
||||
*/
|
||||
static int uwsgi_send_headers(request_rec *r, proxy_conn_rec *conn)
|
||||
{
|
||||
char *buf, *ptr;
|
||||
|
||||
const apr_array_header_t *env_table;
|
||||
const apr_table_entry_t *env;
|
||||
|
||||
int j;
|
||||
|
||||
apr_size_t headerlen = 4;
|
||||
uint16_t pktsize, keylen, vallen;
|
||||
|
||||
ap_add_common_vars(r);
|
||||
ap_add_cgi_vars(r);
|
||||
|
||||
// this is not a security problem (in Linux) as uWSGI destroy the env memory area readable in /proc
|
||||
// and generally if you host untrusted apps in your server and allows them to read others uid /proc/<pid>
|
||||
// files you have higher problems...
|
||||
const char *auth = apr_table_get(r->headers_in, "Authorization");
|
||||
if (auth) {
|
||||
apr_table_setn(r->subprocess_env, "HTTP_AUTHORIZATION", auth);
|
||||
}
|
||||
|
||||
const char *script_name = apr_table_get(r->subprocess_env, "SCRIPT_NAME");
|
||||
const char *path_info = apr_table_get(r->subprocess_env, "PATH_INFO");
|
||||
|
||||
if (script_name && path_info) {
|
||||
if (strcmp(path_info, "/")) {
|
||||
apr_table_set(r->subprocess_env, "SCRIPT_NAME", apr_pstrndup(r->pool, script_name, strlen(script_name)-strlen(path_info)));
|
||||
}
|
||||
else {
|
||||
if (!strcmp(script_name, "/")) {
|
||||
apr_table_set(r->subprocess_env, "SCRIPT_NAME", "");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
env_table = apr_table_elts(r->subprocess_env);
|
||||
env = (apr_table_entry_t *)env_table->elts;
|
||||
|
||||
for (j = 0; j < env_table->nelts; ++j) {
|
||||
headerlen += 2 + strlen(env[j].key) + 2 + strlen(env[j].val) ;
|
||||
}
|
||||
|
||||
ptr = buf = apr_palloc(r->pool, headerlen);
|
||||
|
||||
ptr+=4;
|
||||
|
||||
for (j = 0; j < env_table->nelts; ++j) {
|
||||
keylen = strlen(env[j].key);
|
||||
*ptr++= (uint8_t) (keylen & 0xff);
|
||||
*ptr++= (uint8_t) ((keylen >> 8) & 0xff);
|
||||
memcpy(ptr, env[j].key, keylen) ; ptr+=keylen;
|
||||
|
||||
vallen = strlen(env[j].val);
|
||||
*ptr++= (uint8_t) (vallen & 0xff);
|
||||
*ptr++= (uint8_t) ((vallen >> 8) & 0xff);
|
||||
memcpy(ptr, env[j].val, vallen) ; ptr+=vallen;
|
||||
}
|
||||
|
||||
pktsize = headerlen-4;
|
||||
|
||||
buf[0] = 0;
|
||||
buf[1] = (uint8_t) (pktsize & 0xff);
|
||||
buf[2] = (uint8_t) ((pktsize >> 8) & 0xff);
|
||||
buf[3] = 0;
|
||||
|
||||
return uwsgi_send(conn, buf, headerlen, r);
|
||||
}
|
||||
|
||||
|
||||
static int uwsgi_send_body(request_rec *r, proxy_conn_rec *conn)
|
||||
{
|
||||
if (ap_should_client_block(r)) {
|
||||
char *buf = apr_palloc(r->pool, AP_IOBUFSIZE);
|
||||
int status;
|
||||
apr_size_t readlen;
|
||||
|
||||
readlen = ap_get_client_block(r, buf, AP_IOBUFSIZE);
|
||||
while (readlen > 0) {
|
||||
status = uwsgi_send(conn, buf, readlen, r);
|
||||
if (status != OK) {
|
||||
return HTTP_SERVICE_UNAVAILABLE;
|
||||
}
|
||||
readlen = ap_get_client_block(r, buf, AP_IOBUFSIZE);
|
||||
}
|
||||
if (readlen == -1) {
|
||||
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
|
||||
"receiving request body failed");
|
||||
return HTTP_INTERNAL_SERVER_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
static request_rec *make_fake_req(conn_rec *c, request_rec *r)
|
||||
{
|
||||
apr_pool_t *pool;
|
||||
request_rec *rp;
|
||||
|
||||
apr_pool_create(&pool, c->pool);
|
||||
|
||||
rp = apr_pcalloc(pool, sizeof(*r));
|
||||
|
||||
rp->pool = pool;
|
||||
rp->status = HTTP_OK;
|
||||
|
||||
rp->headers_in = apr_table_make(pool, 50);
|
||||
rp->subprocess_env = apr_table_make(pool, 50);
|
||||
rp->headers_out = apr_table_make(pool, 12);
|
||||
rp->err_headers_out = apr_table_make(pool, 5);
|
||||
rp->notes = apr_table_make(pool, 5);
|
||||
|
||||
rp->server = r->server;
|
||||
rp->log = r->log;
|
||||
rp->proxyreq = r->proxyreq;
|
||||
rp->request_time = r->request_time;
|
||||
rp->connection = c;
|
||||
rp->output_filters = c->output_filters;
|
||||
rp->input_filters = c->input_filters;
|
||||
rp->proto_output_filters = c->output_filters;
|
||||
rp->proto_input_filters = c->input_filters;
|
||||
rp->useragent_ip = c->client_ip;
|
||||
rp->useragent_addr = c->client_addr;
|
||||
|
||||
rp->request_config = ap_create_request_config(pool);
|
||||
proxy_run_create_req(r, rp);
|
||||
|
||||
return rp;
|
||||
}
|
||||
|
||||
static int uwsgi_response(request_rec *r, proxy_conn_rec *backend, proxy_server_conf *conf)
|
||||
{
|
||||
|
||||
char buffer[HUGE_STRING_LEN];
|
||||
const char *buf;
|
||||
char *value, *end;
|
||||
int len;
|
||||
int backend_broke = 0;
|
||||
apr_status_t rc;
|
||||
conn_rec *c = r->connection;
|
||||
apr_off_t readbytes;
|
||||
apr_status_t rv;
|
||||
apr_bucket *e;
|
||||
apr_read_type_e mode = APR_NONBLOCK_READ;
|
||||
|
||||
request_rec *rp = make_fake_req(backend->connection, r);
|
||||
rp->proxyreq = PROXYREQ_RESPONSE;
|
||||
|
||||
apr_bucket_brigade *bb = apr_brigade_create(r->pool, c->bucket_alloc);
|
||||
apr_bucket_brigade *pass_bb = apr_brigade_create(r->pool, c->bucket_alloc);
|
||||
|
||||
len = ap_getline(buffer, sizeof(buffer), rp, 1);
|
||||
|
||||
if (len <= 0) {
|
||||
// oops
|
||||
return HTTP_INTERNAL_SERVER_ERROR;
|
||||
}
|
||||
|
||||
backend->worker->s->read += len;
|
||||
|
||||
if (len >= sizeof(buffer)-1) {
|
||||
// oops
|
||||
return HTTP_INTERNAL_SERVER_ERROR;
|
||||
}
|
||||
/* Position of http status code */
|
||||
int status_start;
|
||||
if (apr_date_checkmask(buffer, "HTTP/#.# ###*")) {
|
||||
status_start = 9;
|
||||
} else if (apr_date_checkmask(buffer, "HTTP/# ###*")) {
|
||||
status_start = 7;
|
||||
} else {
|
||||
// oops
|
||||
return HTTP_INTERNAL_SERVER_ERROR;
|
||||
}
|
||||
int status_end = status_start + 3;
|
||||
|
||||
char keepchar = buffer[status_end];
|
||||
buffer[status_end] = '\0';
|
||||
r->status = atoi(&buffer[status_start]);
|
||||
|
||||
if (keepchar != '\0') {
|
||||
buffer[status_end] = keepchar;
|
||||
} else {
|
||||
/* 2616 requires the space in Status-Line; the origin
|
||||
* server may have sent one but ap_rgetline_core will
|
||||
* have stripped it. */
|
||||
buffer[status_end] = ' ';
|
||||
buffer[status_end+1] = '\0';
|
||||
}
|
||||
r->status_line = apr_pstrdup(r->pool, &buffer[status_start]);
|
||||
|
||||
// start parsing headers;
|
||||
while ((len = ap_getline(buffer, sizeof(buffer), rp, 1)) > 0) {
|
||||
value = strchr(buffer, ':');
|
||||
// invalid header skip
|
||||
if (!value) continue;
|
||||
*value = '\0';
|
||||
++value;
|
||||
while (apr_isspace(*value)) ++value;
|
||||
for (end = &value[strlen(value)-1]; end > value && apr_isspace(*end); --end) *end = '\0';
|
||||
apr_table_add(r->headers_out, buffer, value);
|
||||
}
|
||||
|
||||
if ((buf = apr_table_get(r->headers_out, "Content-Type"))) {
|
||||
ap_set_content_type(r, apr_pstrdup(r->pool, buf));
|
||||
}
|
||||
|
||||
// honor ProxyErrorOverride and ErrorDocument
|
||||
#if AP_MODULE_MAGIC_AT_LEAST(20101106,0)
|
||||
proxy_dir_conf *dconf = ap_get_module_config(r->per_dir_config, &proxy_module);
|
||||
if (dconf->error_override && ap_is_HTTP_ERROR(r->status)) {
|
||||
#else
|
||||
if (conf->error_override && ap_is_HTTP_ERROR(r->status)) {
|
||||
#endif
|
||||
int status = r->status;
|
||||
r->status = HTTP_OK;
|
||||
r->status_line = NULL;
|
||||
|
||||
apr_brigade_cleanup(bb);
|
||||
apr_brigade_cleanup(pass_bb);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
int finish = 0;
|
||||
while(!finish) {
|
||||
rv = ap_get_brigade(rp->input_filters, bb,
|
||||
AP_MODE_READBYTES, mode,
|
||||
conf->io_buffer_size);
|
||||
if (APR_STATUS_IS_EAGAIN(rv)
|
||||
|| (rv == APR_SUCCESS && APR_BRIGADE_EMPTY(bb)) ) {
|
||||
e = apr_bucket_flush_create(c->bucket_alloc);
|
||||
APR_BRIGADE_INSERT_TAIL(bb, e);
|
||||
if (ap_pass_brigade(r->output_filters, bb) || c->aborted) {
|
||||
break;
|
||||
}
|
||||
apr_brigade_cleanup(bb);
|
||||
mode = APR_BLOCK_READ;
|
||||
continue;
|
||||
}
|
||||
else if (rv == APR_EOF) {
|
||||
break;
|
||||
}
|
||||
else if (rv != APR_SUCCESS) {
|
||||
ap_proxy_backend_broke(r, bb);
|
||||
ap_pass_brigade(r->output_filters, bb);
|
||||
backend_broke = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
mode = APR_NONBLOCK_READ;
|
||||
apr_brigade_length(bb, 0, &readbytes);
|
||||
backend->worker->s->read += readbytes;
|
||||
|
||||
if (APR_BRIGADE_EMPTY(bb)) {
|
||||
apr_brigade_cleanup(bb);
|
||||
break;
|
||||
}
|
||||
|
||||
ap_proxy_buckets_lifetime_transform(r, bb, pass_bb);
|
||||
|
||||
// found the last brigade?
|
||||
if (APR_BUCKET_IS_EOS(APR_BRIGADE_LAST(bb))) finish = 1;
|
||||
|
||||
// do not pass chunk if it is zero_sized
|
||||
apr_brigade_length(pass_bb, 0, &readbytes);
|
||||
|
||||
if ((readbytes > 0 && ap_pass_brigade(r->output_filters, pass_bb) != APR_SUCCESS) || c->aborted) {
|
||||
finish = 1;
|
||||
}
|
||||
|
||||
apr_brigade_cleanup(bb);
|
||||
apr_brigade_cleanup(pass_bb);
|
||||
}
|
||||
|
||||
e = apr_bucket_eos_create(c->bucket_alloc);
|
||||
APR_BRIGADE_INSERT_TAIL(bb, e);
|
||||
ap_pass_brigade(r->output_filters, bb);
|
||||
|
||||
apr_brigade_cleanup(bb);
|
||||
|
||||
if (c->aborted || backend_broke) {
|
||||
return DONE;
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
static int uwsgi_handler(request_rec *r, proxy_worker *worker,
|
||||
proxy_server_conf *conf, char *url,
|
||||
const char *proxyname, apr_port_t proxyport)
|
||||
{
|
||||
int status;
|
||||
proxy_conn_rec *backend = NULL;
|
||||
apr_pool_t *p = r->pool;
|
||||
apr_uri_t *uri = apr_palloc(r->pool, sizeof(*uri));
|
||||
char server_portstr[32];
|
||||
|
||||
if (strncasecmp(url, UWSGI_SCHEME "://", sizeof(UWSGI_SCHEME) + 2)) {
|
||||
ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,
|
||||
"declining URL %s", url);
|
||||
return DECLINED;
|
||||
}
|
||||
|
||||
// ADD PATH_INFO
|
||||
#if AP_MODULE_MAGIC_AT_LEAST(20111130,0)
|
||||
size_t w_len = strlen(worker->s->name);
|
||||
#else
|
||||
size_t w_len = strlen(worker->name);
|
||||
#endif
|
||||
char *u_path_info = r->filename + 6 + w_len;
|
||||
int delta = 0;
|
||||
if (u_path_info[0] != '/') {
|
||||
delta = 1;
|
||||
}
|
||||
int decode_status = ap_unescape_url(url+w_len-delta);
|
||||
if (decode_status) {
|
||||
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
|
||||
"unable to decode uri: %s",
|
||||
url+w_len-delta);
|
||||
return HTTP_INTERNAL_SERVER_ERROR;
|
||||
}
|
||||
apr_table_add(r->subprocess_env, "PATH_INFO", url+w_len-delta);
|
||||
|
||||
|
||||
/* Create space for state information */
|
||||
status = ap_proxy_acquire_connection(UWSGI_SCHEME, &backend, worker,
|
||||
r->server);
|
||||
if (status != OK) {
|
||||
goto cleanup;
|
||||
}
|
||||
backend->is_ssl = 0;
|
||||
|
||||
/* Step One: Determine Who To Connect To */
|
||||
status = ap_proxy_determine_connection(p, r, conf, worker, backend,
|
||||
uri, &url, proxyname, proxyport,
|
||||
server_portstr, sizeof(server_portstr));
|
||||
if (status != OK) {
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
|
||||
/* Step Two: Make the Connection */
|
||||
if (ap_proxy_connect_backend(UWSGI_SCHEME, backend, worker, r->server)) {
|
||||
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
|
||||
"failed to make connection to backend: %s:%u",
|
||||
backend->hostname, backend->port);
|
||||
status = HTTP_SERVICE_UNAVAILABLE;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* Step Three: Create conn_rec */
|
||||
if (!backend->connection) {
|
||||
if ((status = ap_proxy_connection_create(UWSGI_SCHEME, backend,
|
||||
r->connection, r->server)) != OK)
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* Step Four: Process the Request */
|
||||
if ( ((status = ap_setup_client_block(r, REQUEST_CHUNKED_ERROR)) != OK)
|
||||
|| ((status = uwsgi_send_headers(r, backend)) != OK)
|
||||
|| ((status = uwsgi_send_body(r, backend)) != OK)
|
||||
|| ((status = uwsgi_response(r, backend, conf)) != OK)) {
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
cleanup:
|
||||
if (backend) {
|
||||
backend->close = 1; /* always close the socket */
|
||||
ap_proxy_release_connection(UWSGI_SCHEME, backend, r->server);
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
static void register_hooks(apr_pool_t *p)
|
||||
{
|
||||
proxy_hook_scheme_handler(uwsgi_handler, NULL, NULL, APR_HOOK_FIRST);
|
||||
proxy_hook_canon_handler(uwsgi_canon, NULL, NULL, APR_HOOK_FIRST);
|
||||
}
|
||||
|
||||
|
||||
module AP_MODULE_DECLARE_DATA proxy_uwsgi_module = {
|
||||
STANDARD20_MODULE_STUFF,
|
||||
NULL, /* create per-directory config structure */
|
||||
NULL, /* merge per-directory config structures */
|
||||
NULL, /* create per-server config structure */
|
||||
NULL, /* merge per-server config structures */
|
||||
NULL, /* command table */
|
||||
register_hooks /* register hooks */
|
||||
};
|
123
modules/proxy/mod_proxy_uwsgi.dsp
Normal file
123
modules/proxy/mod_proxy_uwsgi.dsp
Normal file
@@ -0,0 +1,123 @@
|
||||
# Microsoft Developer Studio Project File - Name="mod_proxy_uwsgi" - Package Owner=<4>
|
||||
# Microsoft Developer Studio Generated Build File, Format Version 6.00
|
||||
# ** DO NOT EDIT **
|
||||
|
||||
# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
|
||||
|
||||
CFG=mod_proxy_uwsgi - Win32 Release
|
||||
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
|
||||
!MESSAGE use the Export Makefile command and run
|
||||
!MESSAGE
|
||||
!MESSAGE NMAKE /f "mod_proxy_uwsgi.mak".
|
||||
!MESSAGE
|
||||
!MESSAGE You can specify a configuration when running NMAKE
|
||||
!MESSAGE by defining the macro CFG on the command line. For example:
|
||||
!MESSAGE
|
||||
!MESSAGE NMAKE /f "mod_proxy_uwsgi.mak" CFG="mod_proxy_uwsgi - Win32 Release"
|
||||
!MESSAGE
|
||||
!MESSAGE Possible choices for configuration are:
|
||||
!MESSAGE
|
||||
!MESSAGE "mod_proxy_uwsgi - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
|
||||
!MESSAGE "mod_proxy_uwsgi - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
|
||||
!MESSAGE
|
||||
|
||||
# Begin Project
|
||||
# PROP AllowPerConfigDependencies 0
|
||||
# PROP Scc_ProjName ""
|
||||
# PROP Scc_LocalPath ""
|
||||
CPP=cl.exe
|
||||
MTL=midl.exe
|
||||
RSC=rc.exe
|
||||
|
||||
!IF "$(CFG)" == "mod_proxy_uwsgi - Win32 Release"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 0
|
||||
# PROP BASE Output_Dir "Release"
|
||||
# PROP BASE Intermediate_Dir "Release"
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 0
|
||||
# PROP Output_Dir "Release"
|
||||
# PROP Intermediate_Dir "Release"
|
||||
# PROP Ignore_Export_Lib 0
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /MD /W3 /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /FD /c
|
||||
# ADD CPP /nologo /MD /W3 /O2 /Oy- /Zi /I "../../include" /I "../../srclib/apr/include" /I "../../srclib/apr-util/include" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /Fd"Release\mod_proxy_uwsgi_src" /FD /c
|
||||
# ADD BASE MTL /nologo /D "NDEBUG" /win32
|
||||
# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
|
||||
# ADD BASE RSC /l 0x809 /d "NDEBUG"
|
||||
# ADD RSC /l 0x409 /fo"Release/mod_proxy_uwsgi.res" /i "../../include" /i "../../srclib/apr/include" /d "NDEBUG" /d BIN_NAME="mod_proxy_uwsgi.so" /d LONG_NAME="proxy_uwsgi_module for Apache"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LINK32=link.exe
|
||||
# ADD BASE LINK32 kernel32.lib ws2_32.lib mswsock.lib /nologo /subsystem:windows /dll /out:".\Release\mod_proxy_uwsgi.so" /base:@..\..\os\win32\BaseAddr.ref,mod_proxy_uwsgi.so
|
||||
# ADD LINK32 kernel32.lib ws2_32.lib mswsock.lib /nologo /subsystem:windows /dll /incremental:no /debug /out:".\Release\mod_proxy_uwsgi.so" /base:@..\..\os\win32\BaseAddr.ref,mod_proxy_uwsgi.so /opt:ref
|
||||
# Begin Special Build Tool
|
||||
TargetPath=.\Release\mod_proxy_uwsgi.so
|
||||
SOURCE="$(InputPath)"
|
||||
PostBuild_Desc=Embed .manifest
|
||||
PostBuild_Cmds=if exist $(TargetPath).manifest mt.exe -manifest $(TargetPath).manifest -outputresource:$(TargetPath);2
|
||||
# End Special Build Tool
|
||||
|
||||
!ELSEIF "$(CFG)" == "mod_proxy_uwsgi - Win32 Debug"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 1
|
||||
# PROP BASE Output_Dir "Debug"
|
||||
# PROP BASE Intermediate_Dir "Debug"
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 1
|
||||
# PROP Output_Dir "Debug"
|
||||
# PROP Intermediate_Dir "Debug"
|
||||
# PROP Ignore_Export_Lib 0
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /MDd /W3 /EHsc /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FD /c
|
||||
# ADD CPP /nologo /MDd /W3 /EHsc /Zi /Od /I "../../include" /I "../../srclib/apr/include" /I "../../srclib/apr-util/include" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /Fd"Debug\mod_proxy_uwsgi_src" /FD /c
|
||||
# ADD BASE MTL /nologo /D "_DEBUG" /win32
|
||||
# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
|
||||
# ADD BASE RSC /l 0x809 /d "_DEBUG"
|
||||
# ADD RSC /l 0x409 /fo"Debug/mod_proxy_uwsgi.res" /i "../../include" /i "../../srclib/apr/include" /d "_DEBUG" /d BIN_NAME="mod_proxy_uwsgi.so" /d LONG_NAME="proxy_uwsgi_module for Apache"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LINK32=link.exe
|
||||
# ADD BASE LINK32 kernel32.lib ws2_32.lib mswsock.lib /nologo /subsystem:windows /dll /incremental:no /debug /out:".\Debug\mod_proxy_uwsgi.so" /base:@..\..\os\win32\BaseAddr.ref,mod_proxy_uwsgi.so
|
||||
# ADD LINK32 kernel32.lib ws2_32.lib mswsock.lib /nologo /subsystem:windows /dll /incremental:no /debug /out:".\Debug\mod_proxy_uwsgi.so" /base:@..\..\os\win32\BaseAddr.ref,mod_proxy_uwsgi.so
|
||||
# Begin Special Build Tool
|
||||
TargetPath=.\Debug\mod_proxy_uwsgi.so
|
||||
SOURCE="$(InputPath)"
|
||||
PostBuild_Desc=Embed .manifest
|
||||
PostBuild_Cmds=if exist $(TargetPath).manifest mt.exe -manifest $(TargetPath).manifest -outputresource:$(TargetPath);2
|
||||
# End Special Build Tool
|
||||
|
||||
!ENDIF
|
||||
|
||||
# Begin Target
|
||||
|
||||
# Name "mod_proxy_uwsgi - Win32 Release"
|
||||
# Name "mod_proxy_uwsgi - Win32 Debug"
|
||||
# Begin Group "Source Files"
|
||||
|
||||
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;hpj;bat;for;f90"
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\mod_proxy_uwsgi.c
|
||||
# End Source File
|
||||
# End Group
|
||||
# Begin Group "Header Files"
|
||||
|
||||
# PROP Default_Filter ".h"
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\mod_proxy.h
|
||||
# End Source File
|
||||
# End Group
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\build\win32\httpd.rc
|
||||
# End Source File
|
||||
# End Target
|
||||
# End Project
|
Reference in New Issue
Block a user