mirror of
https://github.com/apache/httpd.git
synced 2025-08-08 15:02:10 +03:00
This removes all BUFF's from the HTTP proxy. This code is relatively
ugly, but it does proxy pages. This even fixes the content-type bug that I introduced yesterday sometime. As soon as BUFF is removed from the FTP proxy, the buff.c and buff.h files need to go away. git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@86988 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
@@ -496,6 +496,8 @@ void ap_finalize_sub_req_protocol(request_rec *sub_r);
|
|||||||
*/
|
*/
|
||||||
AP_CORE_DECLARE(void) ap_parse_uri(request_rec *r, const char *uri);
|
AP_CORE_DECLARE(void) ap_parse_uri(request_rec *r, const char *uri);
|
||||||
|
|
||||||
|
AP_CORE_DECLARE(int) ap_getline(char *s, int n, request_rec *r, int fold);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the method number associated with the given string, assumed to
|
* Get the method number associated with the given string, assumed to
|
||||||
* contain an HTTP method. Returns M_INVALID if not recognized.
|
* contain an HTTP method. Returns M_INVALID if not recognized.
|
||||||
|
@@ -818,7 +818,6 @@ struct dechunk_ctx {
|
|||||||
};
|
};
|
||||||
|
|
||||||
static long get_chunk_size(char *);
|
static long get_chunk_size(char *);
|
||||||
static int getline(char *s, int n, request_rec *r, int fold);
|
|
||||||
|
|
||||||
apr_status_t ap_dechunk_filter(ap_filter_t *f, ap_bucket_brigade *bb,
|
apr_status_t ap_dechunk_filter(ap_filter_t *f, ap_bucket_brigade *bb,
|
||||||
ap_input_mode_t mode)
|
ap_input_mode_t mode)
|
||||||
@@ -841,7 +840,7 @@ apr_status_t ap_dechunk_filter(ap_filter_t *f, ap_bucket_brigade *bb,
|
|||||||
*/
|
*/
|
||||||
char line[30];
|
char line[30];
|
||||||
|
|
||||||
if ((rv = getline(line, sizeof(line), f->r, 0)) < 0) {
|
if ((rv = ap_getline(line, sizeof(line), f->r, 0)) < 0) {
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
switch(ctx->state) {
|
switch(ctx->state) {
|
||||||
@@ -1028,7 +1027,7 @@ apr_status_t ap_http_filter(ap_filter_t *f, ap_bucket_brigade *b, ap_input_mode_
|
|||||||
* If no LF is detected on the last line due to a dropped connection
|
* If no LF is detected on the last line due to a dropped connection
|
||||||
* or a full buffer, that's considered an error.
|
* or a full buffer, that's considered an error.
|
||||||
*/
|
*/
|
||||||
static int getline(char *s, int n, request_rec *r, int fold)
|
int ap_getline(char *s, int n, request_rec *r, int fold)
|
||||||
{
|
{
|
||||||
char *pos = s;
|
char *pos = s;
|
||||||
char *last_char;
|
char *last_char;
|
||||||
@@ -1224,7 +1223,7 @@ static int read_request_line(request_rec *r)
|
|||||||
ap_bsetflag(conn->client, B_SAFEREAD, 1);
|
ap_bsetflag(conn->client, B_SAFEREAD, 1);
|
||||||
ap_bflush(conn->client);
|
ap_bflush(conn->client);
|
||||||
#endif
|
#endif
|
||||||
while ((len = getline(l, sizeof(l), r, 0)) <= 0) {
|
while ((len = ap_getline(l, sizeof(l), r, 0)) <= 0) {
|
||||||
if (len < 0) { /* includes EOF */
|
if (len < 0) { /* includes EOF */
|
||||||
#if 0
|
#if 0
|
||||||
/* XXX: I am 99% sure that these are already taken care of, but I want to
|
/* XXX: I am 99% sure that these are already taken care of, but I want to
|
||||||
@@ -1276,7 +1275,7 @@ static int read_request_line(request_rec *r)
|
|||||||
|
|
||||||
ap_parse_uri(r, uri);
|
ap_parse_uri(r, uri);
|
||||||
|
|
||||||
/* getline returns (size of max buffer - 1) if it fills up the
|
/* ap_getline returns (size of max buffer - 1) if it fills up the
|
||||||
* buffer before finding the end-of-line. This is only going to
|
* buffer before finding the end-of-line. This is only going to
|
||||||
* happen if it exceeds the configured limit for a request-line.
|
* happen if it exceeds the configured limit for a request-line.
|
||||||
*/
|
*/
|
||||||
@@ -1316,7 +1315,7 @@ static void get_mime_headers(request_rec *r)
|
|||||||
* Read header lines until we get the empty separator line, a read error,
|
* Read header lines until we get the empty separator line, a read error,
|
||||||
* the connection closes (EOF), reach the server limit, or we timeout.
|
* the connection closes (EOF), reach the server limit, or we timeout.
|
||||||
*/
|
*/
|
||||||
while ((len = getline(field, sizeof(field), r, 1)) > 0) {
|
while ((len = ap_getline(field, sizeof(field), r, 1)) > 0) {
|
||||||
|
|
||||||
if (r->server->limit_req_fields &&
|
if (r->server->limit_req_fields &&
|
||||||
(++fields_read > r->server->limit_req_fields)) {
|
(++fields_read > r->server->limit_req_fields)) {
|
||||||
@@ -1326,7 +1325,7 @@ static void get_mime_headers(request_rec *r)
|
|||||||
"this server's limit.<P>\n");
|
"this server's limit.<P>\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
/* getline returns (size of max buffer - 1) if it fills up the
|
/* ap_getline returns (size of max buffer - 1) if it fills up the
|
||||||
* buffer before finding the end-of-line. This is only going to
|
* buffer before finding the end-of-line. This is only going to
|
||||||
* happen if it exceeds the configured limit for a field size.
|
* happen if it exceeds the configured limit for a field size.
|
||||||
*/
|
*/
|
||||||
@@ -2683,7 +2682,7 @@ AP_DECLARE(int) ap_setup_client_block(request_rec *r, int read_policy)
|
|||||||
|
|
||||||
#ifdef AP_DEBUG
|
#ifdef AP_DEBUG
|
||||||
{
|
{
|
||||||
/* Make sure getline() didn't leave any droppings. */
|
/* Make sure ap_getline() didn't leave any droppings. */
|
||||||
core_request_config *req_cfg =
|
core_request_config *req_cfg =
|
||||||
(core_request_config *)ap_get_module_config(r->request_config,
|
(core_request_config *)ap_get_module_config(r->request_config,
|
||||||
&core_module);
|
&core_module);
|
||||||
|
@@ -255,7 +255,7 @@ char *ap_proxy_canonenc(apr_pool_t *p, const char *x, int len, enum enctype t,
|
|||||||
char *ap_proxy_canon_netloc(apr_pool_t *p, char **const urlp, char **userp,
|
char *ap_proxy_canon_netloc(apr_pool_t *p, char **const urlp, char **userp,
|
||||||
char **passwordp, char **hostp, int *port);
|
char **passwordp, char **hostp, int *port);
|
||||||
const char *ap_proxy_date_canon(apr_pool_t *p, const char *x);
|
const char *ap_proxy_date_canon(apr_pool_t *p, const char *x);
|
||||||
apr_table_t *ap_proxy_read_headers(request_rec *r, char *buffer, int size, BUFF *f);
|
apr_table_t *ap_proxy_read_headers(request_rec *r, char *buffer, int size, conn_rec *c);
|
||||||
long int ap_proxy_send_fb(proxy_completion *, BUFF *f, request_rec *r, ap_cache_el *c);
|
long int ap_proxy_send_fb(proxy_completion *, BUFF *f, request_rec *r, ap_cache_el *c);
|
||||||
void ap_proxy_send_headers(request_rec *r, const char *respline, apr_table_t *hdrs);
|
void ap_proxy_send_headers(request_rec *r, const char *respline, apr_table_t *hdrs);
|
||||||
int ap_proxy_liststr(const char *list, const char *val);
|
int ap_proxy_liststr(const char *list, const char *val);
|
||||||
|
@@ -58,10 +58,13 @@
|
|||||||
|
|
||||||
/* HTTP routines for Apache proxy */
|
/* HTTP routines for Apache proxy */
|
||||||
|
|
||||||
|
#define CORE_PRIVATE
|
||||||
|
|
||||||
#include "mod_proxy.h"
|
#include "mod_proxy.h"
|
||||||
#include "http_log.h"
|
#include "http_log.h"
|
||||||
#include "http_main.h"
|
#include "http_main.h"
|
||||||
#include "http_core.h"
|
#include "http_core.h"
|
||||||
|
#include "http_connection.h"
|
||||||
#include "util_date.h"
|
#include "util_date.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -180,11 +183,10 @@ int ap_proxy_http_handler(request_rec *r, ap_cache_el *c, char *url,
|
|||||||
apr_table_entry_t *reqhdrs;
|
apr_table_entry_t *reqhdrs;
|
||||||
struct sockaddr_in server;
|
struct sockaddr_in server;
|
||||||
struct in_addr destaddr;
|
struct in_addr destaddr;
|
||||||
BUFF *f;
|
|
||||||
char buffer[HUGE_STRING_LEN];
|
char buffer[HUGE_STRING_LEN];
|
||||||
|
char *buffer2;
|
||||||
char portstr[32];
|
char portstr[32];
|
||||||
apr_pool_t *p = r->pool;
|
apr_pool_t *p = r->pool;
|
||||||
const long int zero = 0L;
|
|
||||||
int destport = 0;
|
int destport = 0;
|
||||||
char *destportstr = NULL;
|
char *destportstr = NULL;
|
||||||
const char *urlptr = NULL;
|
const char *urlptr = NULL;
|
||||||
@@ -192,7 +194,9 @@ int ap_proxy_http_handler(request_rec *r, ap_cache_el *c, char *url,
|
|||||||
apr_ssize_t cntr;
|
apr_ssize_t cntr;
|
||||||
apr_file_t *cachefp = NULL;
|
apr_file_t *cachefp = NULL;
|
||||||
char *buf;
|
char *buf;
|
||||||
int rbb;
|
conn_rec *origin;
|
||||||
|
ap_bucket *e;
|
||||||
|
ap_bucket_brigade *bb = ap_brigade_create(r->pool);
|
||||||
|
|
||||||
void *sconf = r->server->module_config;
|
void *sconf = r->server->module_config;
|
||||||
proxy_server_conf *conf =
|
proxy_server_conf *conf =
|
||||||
@@ -274,24 +278,24 @@ int ap_proxy_http_handler(request_rec *r, ap_cache_el *c, char *url,
|
|||||||
desthost, NULL));
|
desthost, NULL));
|
||||||
}
|
}
|
||||||
|
|
||||||
clear_connection(r->pool, r->headers_in); /* Strip connection-based headers */
|
origin = ap_new_apr_connection(r->pool, r->server, sock, 0);
|
||||||
|
ap_add_output_filter("CORE", NULL, NULL, origin);
|
||||||
|
|
||||||
f = ap_bcreate(p, B_RDWR);
|
clear_connection(r->pool, r->headers_in); /* Strip connection-based headers */
|
||||||
ap_bpush_socket(f, sock);
|
|
||||||
|
|
||||||
buf = apr_pstrcat(r->pool, r->method, " ", proxyhost ? url : urlptr,
|
buf = apr_pstrcat(r->pool, r->method, " ", proxyhost ? url : urlptr,
|
||||||
" HTTP/1.0" CRLF, NULL);
|
" HTTP/1.0" CRLF, NULL);
|
||||||
rbb = strlen(buf);
|
e = ap_bucket_create_pool(buf, strlen(buf), r->pool);
|
||||||
apr_send(sock, buf, &rbb);
|
AP_BRIGADE_INSERT_TAIL(bb, e);
|
||||||
if (destportstr != NULL && destport != DEFAULT_HTTP_PORT) {
|
if (destportstr != NULL && destport != DEFAULT_HTTP_PORT) {
|
||||||
buf = apr_pstrcat(r->pool, "Host: ", desthost, ":", destportstr, CRLF, NULL);
|
buf = apr_pstrcat(r->pool, "Host: ", desthost, ":", destportstr, CRLF, NULL);
|
||||||
rbb = strlen(buf);
|
e = ap_bucket_create_pool(buf, strlen(buf), r->pool);
|
||||||
apr_send(sock, buf, &rbb);
|
AP_BRIGADE_INSERT_TAIL(bb, e);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
buf = apr_pstrcat(r->pool, "Host: ", desthost, CRLF, NULL);
|
buf = apr_pstrcat(r->pool, "Host: ", desthost, CRLF, NULL);
|
||||||
rbb = strlen(buf);
|
e = ap_bucket_create_pool(buf, strlen(buf), r->pool);
|
||||||
apr_send(sock, buf, &rbb);
|
AP_BRIGADE_INSERT_TAIL(bb, e);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (conf->viaopt == via_block) {
|
if (conf->viaopt == via_block) {
|
||||||
@@ -333,67 +337,80 @@ int ap_proxy_http_handler(request_rec *r, ap_cache_el *c, char *url,
|
|||||||
|| !strcasecmp(reqhdrs[i].key, "Proxy-Authorization"))
|
|| !strcasecmp(reqhdrs[i].key, "Proxy-Authorization"))
|
||||||
continue;
|
continue;
|
||||||
buf = apr_pstrcat(r->pool, reqhdrs[i].key, ": ", reqhdrs[i].val, CRLF, NULL);
|
buf = apr_pstrcat(r->pool, reqhdrs[i].key, ": ", reqhdrs[i].val, CRLF, NULL);
|
||||||
rbb = strlen(buf);
|
e = ap_bucket_create_pool(buf, strlen(buf), r->pool);
|
||||||
apr_send(sock, buf, &rbb);
|
AP_BRIGADE_INSERT_TAIL(bb, e);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
rbb = strlen(CRLF);
|
e = ap_bucket_create_pool(CRLF, strlen(CRLF), r->pool);
|
||||||
apr_send(sock, CRLF, &rbb);
|
AP_BRIGADE_INSERT_TAIL(bb, e);
|
||||||
|
e = ap_bucket_create_flush();
|
||||||
|
AP_BRIGADE_INSERT_TAIL(bb, e);
|
||||||
|
|
||||||
|
ap_pass_brigade(origin->output_filters, bb);
|
||||||
/* send the request data, if any. */
|
/* send the request data, if any. */
|
||||||
|
|
||||||
if (ap_should_client_block(r)) {
|
if (ap_should_client_block(r)) {
|
||||||
while ((i = ap_get_client_block(r, buffer, sizeof buffer)) > 0) {
|
while ((i = ap_get_client_block(r, buffer, sizeof buffer)) > 0) {
|
||||||
cntr = i;
|
e = ap_bucket_create_pool(buffer, i, r->pool);
|
||||||
apr_send(sock, buffer, &cntr);
|
AP_BRIGADE_INSERT_TAIL(bb, e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#if 0 /* This doesn't make any sense until we convert the raw socket calls
|
/* Flush the data to the origin server */
|
||||||
* to filters.
|
e = ap_bucket_create_flush();
|
||||||
*/
|
AP_BRIGADE_INSERT_TAIL(bb, e);
|
||||||
ap_bflush(f);
|
ap_pass_brigade(origin->output_filters, bb);
|
||||||
#endif
|
|
||||||
|
|
||||||
len = ap_bgets(buffer, sizeof buffer - 1, f);
|
ap_add_input_filter("HTTP", NULL, NULL, origin);
|
||||||
|
ap_add_input_filter("CORE_IN", NULL, NULL, origin);
|
||||||
|
|
||||||
|
ap_brigade_destroy(bb);
|
||||||
|
bb = ap_brigade_create(r->pool);
|
||||||
|
|
||||||
|
/* Tell http_filter to grab the data one line at a time. */
|
||||||
|
origin->remain = 0;
|
||||||
|
|
||||||
|
ap_get_brigade(origin->input_filters, bb, AP_MODE_BLOCKING);
|
||||||
|
ap_bucket_read(AP_BRIGADE_FIRST(bb), (const char **)&buffer2, &len, AP_BLOCK_READ);
|
||||||
if (len == -1) {
|
if (len == -1) {
|
||||||
ap_bclose(f);
|
apr_close_socket(sock);
|
||||||
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
|
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
|
||||||
"ap_bgets() - proxy receive - Error reading from remote server %s (length %d)",
|
"ap_get_brigade() - proxy receive - Error reading from remote server %s (length %d)",
|
||||||
proxyhost ? proxyhost : desthost, len);
|
proxyhost ? proxyhost : desthost, len);
|
||||||
return ap_proxyerror(r, HTTP_BAD_GATEWAY,
|
return ap_proxyerror(r, HTTP_BAD_GATEWAY,
|
||||||
"Error reading from remote server");
|
"Error reading from remote server");
|
||||||
} else if (len == 0) {
|
} else if (len == 0) {
|
||||||
ap_bclose(f);
|
apr_close_socket(sock);
|
||||||
return ap_proxyerror(r, HTTP_BAD_GATEWAY,
|
return ap_proxyerror(r, HTTP_BAD_GATEWAY,
|
||||||
"Document contains no data");
|
"Document contains no data");
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Is it an HTTP/1 response? This is buggy if we ever see an HTTP/1.10 */
|
/* Is it an HTTP/1 response? This is buggy if we ever see an HTTP/1.10 */
|
||||||
if (ap_checkmask(buffer, "HTTP/#.# ###*")) {
|
if (ap_checkmask(buffer2, "HTTP/#.# ###*")) {
|
||||||
int major, minor;
|
int major, minor;
|
||||||
if (2 != sscanf(buffer, "HTTP/%u.%u", &major, &minor)) {
|
if (2 != sscanf(buffer2, "HTTP/%u.%u", &major, &minor)) {
|
||||||
major = 1;
|
major = 1;
|
||||||
minor = 0;
|
minor = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If not an HTTP/1 message or if the status line was > 8192 bytes */
|
/* If not an HTTP/1 message or if the status line was > 8192 bytes */
|
||||||
if (buffer[5] != '1' || buffer[len - 1] != '\n') {
|
if (buffer2[5] != '1' || buffer2[len - 1] != '\n') {
|
||||||
ap_bclose(f);
|
apr_close_socket(sock);
|
||||||
return HTTP_BAD_GATEWAY;
|
return HTTP_BAD_GATEWAY;
|
||||||
}
|
}
|
||||||
backasswards = 0;
|
backasswards = 0;
|
||||||
buffer[--len] = '\0';
|
buffer2[--len] = '\0';
|
||||||
|
|
||||||
buffer[12] = '\0';
|
buffer2[12] = '\0';
|
||||||
r->status = atoi(&buffer[9]);
|
r->status = atoi(&buffer2[9]);
|
||||||
buffer[12] = ' ';
|
buffer2[12] = ' ';
|
||||||
r->status_line = apr_pstrdup(p, &buffer[9]);
|
r->status_line = apr_pstrdup(p, &buffer2[9]);
|
||||||
|
|
||||||
/* read the headers. */
|
/* read the headers. */
|
||||||
/* N.B. for HTTP/1.0 clients, we have to fold line-wrapped headers */
|
/* N.B. for HTTP/1.0 clients, we have to fold line-wrapped headers */
|
||||||
/* Also, take care with headers with multiple occurences. */
|
/* Also, take care with headers with multiple occurences. */
|
||||||
|
|
||||||
resp_hdrs = ap_proxy_read_headers(r, buffer, HUGE_STRING_LEN, f);
|
resp_hdrs = ap_proxy_read_headers(r, buffer, HUGE_STRING_LEN, origin);
|
||||||
if (resp_hdrs == NULL) {
|
if (resp_hdrs == NULL) {
|
||||||
ap_log_error(APLOG_MARK, APLOG_WARNING|APLOG_NOERRNO, 0, r->server,
|
ap_log_error(APLOG_MARK, APLOG_WARNING|APLOG_NOERRNO, 0, r->server,
|
||||||
"proxy: Bad HTTP/%d.%d header returned by %s (%s)",
|
"proxy: Bad HTTP/%d.%d header returned by %s (%s)",
|
||||||
@@ -475,21 +492,17 @@ int ap_proxy_http_handler(request_rec *r, ap_cache_el *c, char *url,
|
|||||||
/* send headers */
|
/* send headers */
|
||||||
ap_cache_el_header_walk(c, ap_proxy_send_hdr_line, r, NULL);
|
ap_cache_el_header_walk(c, ap_proxy_send_hdr_line, r, NULL);
|
||||||
|
|
||||||
#if 0
|
|
||||||
if (!r->assbackwards)
|
if (!r->assbackwards)
|
||||||
ap_rputs(CRLF, r);
|
ap_rputs(CRLF, r);
|
||||||
#endif
|
|
||||||
|
|
||||||
/* We don't set byte count this way anymore. I think this can be removed
|
|
||||||
* cleanly now.
|
|
||||||
ap_bsetopt(r->connection->client, BO_BYTECT, &zero);
|
|
||||||
*/
|
|
||||||
r->sent_bodyct = 1;
|
r->sent_bodyct = 1;
|
||||||
/* Is it an HTTP/0.9 response? If so, send the extra data */
|
/* Is it an HTTP/0.9 response? If so, send the extra data */
|
||||||
if (backasswards) {
|
if (backasswards) {
|
||||||
cntr = len;
|
cntr = len;
|
||||||
apr_send(r->connection->client_socket, buffer, &cntr);
|
apr_send(r->connection->client_socket, buffer, &cntr);
|
||||||
cntr = len;
|
cntr = len;
|
||||||
|
e = ap_bucket_create_heap(buffer, cntr, 0, NULL);
|
||||||
|
AP_BRIGADE_INSERT_TAIL(bb, e);
|
||||||
if (cachefp && apr_write(cachefp, buffer, &cntr) != APR_SUCCESS) {
|
if (cachefp && apr_write(cachefp, buffer, &cntr) != APR_SUCCESS) {
|
||||||
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
|
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
|
||||||
"proxy: error writing extra data to cache");
|
"proxy: error writing extra data to cache");
|
||||||
@@ -497,14 +510,6 @@ int ap_proxy_http_handler(request_rec *r, ap_cache_el *c, char *url,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CHARSET_EBCDIC
|
|
||||||
/* What we read/write after the header should not be modified
|
|
||||||
* (i.e., the cache copy is ASCII, not EBCDIC, even for text/html)
|
|
||||||
*/
|
|
||||||
ap_bsetflag(f, B_ASCII2EBCDIC|B_EBCDIC2ASCII, 0);
|
|
||||||
ap_bsetflag(r->connection->client, B_ASCII2EBCDIC|B_EBCDIC2ASCII, 0);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* send body */
|
/* send body */
|
||||||
/* if header only, then cache will be NULL */
|
/* if header only, then cache will be NULL */
|
||||||
/* HTTP/1.0 tells us to read to EOF, rather than content-length bytes */
|
/* HTTP/1.0 tells us to read to EOF, rather than content-length bytes */
|
||||||
@@ -512,10 +517,18 @@ int ap_proxy_http_handler(request_rec *r, ap_cache_el *c, char *url,
|
|||||||
proxy_completion pc;
|
proxy_completion pc;
|
||||||
pc.content_length = content_length;
|
pc.content_length = content_length;
|
||||||
pc.cache_completion = conf->cache_completion;
|
pc.cache_completion = conf->cache_completion;
|
||||||
ap_proxy_send_fb(&pc, f, r, c);
|
|
||||||
|
origin->remain = content_length;
|
||||||
|
while (ap_get_brigade(origin->input_filters, bb, AP_MODE_BLOCKING) == APR_SUCCESS) {
|
||||||
|
if (AP_BUCKET_IS_EOS(AP_BRIGADE_LAST(bb))) {
|
||||||
|
ap_pass_brigade(r->output_filters, bb);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
ap_pass_brigade(r->output_filters, bb);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ap_bclose(f);
|
apr_close_socket(sock);
|
||||||
if(c) ap_proxy_cache_update(c);
|
if(c) ap_proxy_cache_update(c);
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
@@ -56,13 +56,17 @@
|
|||||||
* University of Illinois, Urbana-Champaign.
|
* University of Illinois, Urbana-Champaign.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#define CORE_PRIVATE
|
||||||
|
|
||||||
/* Utility routines for Apache proxy */
|
/* Utility routines for Apache proxy */
|
||||||
#include "mod_proxy.h"
|
#include "mod_proxy.h"
|
||||||
|
#include "http_core.h"
|
||||||
#include "http_main.h"
|
#include "http_main.h"
|
||||||
#include "http_log.h"
|
#include "http_log.h"
|
||||||
#include "util_uri.h"
|
#include "util_uri.h"
|
||||||
#include "util_date.h" /* get ap_checkmask() decl. */
|
#include "util_date.h" /* get ap_checkmask() decl. */
|
||||||
#include "apr_md5.h"
|
#include "apr_md5.h"
|
||||||
|
#include "apr_pools.h"
|
||||||
|
|
||||||
static int proxy_match_ipaddr(struct dirconn_entry *This, request_rec *r);
|
static int proxy_match_ipaddr(struct dirconn_entry *This, request_rec *r);
|
||||||
static int proxy_match_domainname(struct dirconn_entry *This, request_rec *r);
|
static int proxy_match_domainname(struct dirconn_entry *This, request_rec *r);
|
||||||
@@ -364,63 +368,32 @@ const char *
|
|||||||
return q;
|
return q;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static request_rec *make_fake_req(conn_rec *c)
|
||||||
/* NOTE: This routine is taken from http_protocol::getline()
|
|
||||||
* because the old code found in the proxy module was too
|
|
||||||
* difficult to understand and maintain.
|
|
||||||
*/
|
|
||||||
/* Get a line of protocol input, including any continuation lines
|
|
||||||
* caused by MIME folding (or broken clients) if fold != 0, and place it
|
|
||||||
* in the buffer s, of size n bytes, without the ending newline.
|
|
||||||
*
|
|
||||||
* Returns -1 on error, or the length of s.
|
|
||||||
*
|
|
||||||
* Note: Because bgets uses 1 char for newline and 1 char for NUL,
|
|
||||||
* the most we can get is (n - 2) actual characters if it
|
|
||||||
* was ended by a newline, or (n - 1) characters if the line
|
|
||||||
* length exceeded (n - 1). So, if the result == (n - 1),
|
|
||||||
* then the actual input line exceeded the buffer length,
|
|
||||||
* and it would be a good idea for the caller to puke 400 or 414.
|
|
||||||
*/
|
|
||||||
static int proxy_getline(char *s, int n, BUFF *in, int fold)
|
|
||||||
{
|
{
|
||||||
char *pos, next;
|
request_rec *r = apr_pcalloc(c->pool, sizeof(*r));
|
||||||
int retval;
|
core_request_config *req_cfg;
|
||||||
int total = 0;
|
|
||||||
|
|
||||||
pos = s;
|
r->pool = c->pool;
|
||||||
|
r->status = HTTP_OK;
|
||||||
|
|
||||||
do {
|
r->headers_in = apr_make_table(r->pool, 50);
|
||||||
retval = ap_bgets(pos, n, in); /* retval == -1 if error, 0 if EOF */
|
r->subprocess_env = apr_make_table(r->pool, 50);
|
||||||
|
r->headers_out = apr_make_table(r->pool, 12);
|
||||||
|
r->err_headers_out = apr_make_table(r->pool, 5);
|
||||||
|
r->notes = apr_make_table(r->pool, 5);
|
||||||
|
|
||||||
if (retval <= 0)
|
r->read_body = REQUEST_NO_BODY;
|
||||||
return ((retval < 0) && (total == 0)) ? -1 : total;
|
r->connection = c;
|
||||||
|
r->output_filters = c->output_filters;
|
||||||
|
r->input_filters = c->input_filters;
|
||||||
|
|
||||||
/* retval is the number of characters read, not including NUL */
|
r->request_config = ap_create_request_config(r->pool);
|
||||||
|
req_cfg = apr_pcalloc(r->pool, sizeof(core_request_config));
|
||||||
|
req_cfg->bb = ap_brigade_create(r->pool);
|
||||||
|
ap_set_module_config(r->request_config, &core_module, req_cfg);
|
||||||
|
|
||||||
n -= retval; /* Keep track of how much of s is full */
|
return r;
|
||||||
pos += (retval - 1); /* and where s ends */
|
|
||||||
total += retval; /* and how long s has become */
|
|
||||||
|
|
||||||
if (*pos == '\n') { /* Did we get a full line of input? */
|
|
||||||
*pos = '\0';
|
|
||||||
--total;
|
|
||||||
++n;
|
|
||||||
}
|
}
|
||||||
else
|
|
||||||
return total; /* if not, input line exceeded buffer size */
|
|
||||||
|
|
||||||
/* Continue appending if line folding is desired and
|
|
||||||
* the last line was not empty and we have room in the buffer and
|
|
||||||
* the next line begins with a continuation character.
|
|
||||||
*/
|
|
||||||
} while (fold && (retval != 1) && (n > 1)
|
|
||||||
&& (next = ap_blookc(in))
|
|
||||||
&& ((next == ' ') || (next == '\t')));
|
|
||||||
|
|
||||||
return total;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Reads headers from a buffer and returns an array of headers.
|
* Reads headers from a buffer and returns an array of headers.
|
||||||
@@ -429,12 +402,13 @@ static int proxy_getline(char *s, int n, BUFF *in, int fold)
|
|||||||
* @@@: XXX: FIXME: currently the headers are passed thru un-merged.
|
* @@@: XXX: FIXME: currently the headers are passed thru un-merged.
|
||||||
* Is that okay, or should they be collapsed where possible?
|
* Is that okay, or should they be collapsed where possible?
|
||||||
*/
|
*/
|
||||||
apr_table_t *ap_proxy_read_headers(request_rec *r, char *buffer, int size, BUFF *f)
|
apr_table_t *ap_proxy_read_headers(request_rec *r, char *buffer, int size, conn_rec *c)
|
||||||
{
|
{
|
||||||
apr_table_t *resp_hdrs;
|
apr_table_t *resp_hdrs;
|
||||||
int len;
|
int len;
|
||||||
char *value, *end;
|
char *value, *end;
|
||||||
char field[MAX_STRING_LEN];
|
char field[MAX_STRING_LEN];
|
||||||
|
request_rec *rr = make_fake_req(c);
|
||||||
|
|
||||||
resp_hdrs = ap_make_table(r->pool, 20);
|
resp_hdrs = ap_make_table(r->pool, 20);
|
||||||
|
|
||||||
@@ -442,7 +416,7 @@ apr_table_t *ap_proxy_read_headers(request_rec *r, char *buffer, int size, BUFF
|
|||||||
* Read header lines until we get the empty separator line, a read error,
|
* Read header lines until we get the empty separator line, a read error,
|
||||||
* the connection closes (EOF), or we timeout.
|
* the connection closes (EOF), or we timeout.
|
||||||
*/
|
*/
|
||||||
while ((len = proxy_getline(buffer, size, f, 1)) > 0) {
|
while ((len = ap_getline(buffer, size, rr, 1)) > 0) {
|
||||||
|
|
||||||
if (!(value = strchr(buffer, ':'))) { /* Find the colon separator */
|
if (!(value = strchr(buffer, ':'))) { /* Find the colon separator */
|
||||||
|
|
||||||
@@ -479,7 +453,7 @@ apr_table_t *ap_proxy_read_headers(request_rec *r, char *buffer, int size, BUFF
|
|||||||
|
|
||||||
/* the header was too long; at the least we should skip extra data */
|
/* the header was too long; at the least we should skip extra data */
|
||||||
if (len >= size - 1) {
|
if (len >= size - 1) {
|
||||||
while ((len = proxy_getline(field, MAX_STRING_LEN, f, 1))
|
while ((len = ap_getline(field, MAX_STRING_LEN, r, 1))
|
||||||
>= MAX_STRING_LEN - 1) {
|
>= MAX_STRING_LEN - 1) {
|
||||||
/* soak up the extra data */
|
/* soak up the extra data */
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user