Apache HTTPD
mod_proxy_uwsgi.c
Go to the documentation of this file.
1/* Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache License, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17/*
18
19*** mod_proxy_uwsgi ***
20
21Copyright 2009-2017 Unbit S.a.s. <[email protected]>
22
23Licensed under the Apache License, Version 2.0 (the "License");
24you may not use this file except in compliance with the License.
25You may obtain a copy of the License at
26
27 http://www.apache.org/licenses/LICENSE-2.0
28
29Unless required by applicable law or agreed to in writing, software
30distributed under the License is distributed on an "AS IS" BASIS,
31WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
32See the License for the specific language governing permissions and
33limitations under the License.
34
35*/
36
37#define APR_WANT_MEMFUNC
38#define APR_WANT_STRFUNC
39#include "apr_strings.h"
40#include "apr_hooks.h"
41#include "apr_optional_hooks.h"
42#include "apr_buckets.h"
43
44#include "httpd.h"
45#include "http_config.h"
46#include "http_log.h"
47#include "http_protocol.h"
48#include "http_request.h"
49#include "util_script.h"
50
51#include "mod_proxy.h"
52
53
54#define UWSGI_SCHEME "uwsgi"
55#define UWSGI_DEFAULT_PORT 3031
56
57module AP_MODULE_DECLARE_DATA proxy_uwsgi_module;
58
59
60static int uwsgi_canon(request_rec *r, char *url)
61{
62 char *host, sport[sizeof(":65535")];
63 const char *err, *path;
65
66 if (ap_cstr_casecmpn(url, UWSGI_SCHEME "://", sizeof(UWSGI_SCHEME) + 2)) {
67 return DECLINED;
68 }
69 url += sizeof(UWSGI_SCHEME); /* Keep slashes */
70
72 if (err) {
74 "error parsing URL %s: %s", url, err);
75 return HTTP_BAD_REQUEST;
76 }
77
79 apr_snprintf(sport, sizeof(sport), ":%u", port);
80 else
81 sport[0] = '\0';
82
83 if (ap_strchr(host, ':')) { /* if literal IPv6 address */
84 host = apr_pstrcat(r->pool, "[", host, "]", NULL);
85 }
86
87 if (apr_table_get(r->notes, "proxy-nocanon")
88 || apr_table_get(r->notes, "proxy-noencode")) {
89 path = url; /* this is the raw/encoded path */
90 }
91 else {
93 int flags = d->allow_encoded_slashes && !d->decode_encoded_slashes ? PROXY_CANONENC_NOENCODEDSLASHENCODING : 0;
94
96 r->proxyreq);
97 if (!path) {
98 return HTTP_BAD_REQUEST;
99 }
100 }
101 /*
102 * If we have a raw control character or a ' ' in nocanon path,
103 * correct encoding was missed.
104 */
105 if (path == url && *ap_scan_vchar_obstext(path)) {
107 "To be forwarded path contains control "
108 "characters or spaces");
109 return HTTP_FORBIDDEN;
110 }
111
112 r->filename =
113 apr_pstrcat(r->pool, "proxy:" UWSGI_SCHEME "://", host, sport, "/",
114 path, NULL);
115
116 return OK;
117}
118
119
120static int uwsgi_send(proxy_conn_rec * conn, const char *buf,
122{
123 apr_status_t rv;
124 apr_size_t written;
125
126 while (length > 0) {
127 written = length;
128 if ((rv = apr_socket_send(conn->sock, buf, &written)) != APR_SUCCESS) {
130 "sending data to %s:%u failed",
131 conn->hostname, conn->port);
133 }
134
135 /* count for stats */
136 conn->worker->s->transferred += written;
137 buf += written;
138 length -= written;
139 }
140
141 return OK;
142}
143
144
145/*
146 * Send uwsgi header block
147 */
149{
150 char *buf, *ptr;
151
153 const apr_table_entry_t *env;
154
155 int j;
156
158 apr_size_t pktsize, keylen, vallen;
159 const char *script_name;
160 const char *path_info;
161 const char *auth;
162
165
166 /*
167 this is not a security problem (in Linux) as uWSGI destroy the env memory area readable in /proc
168 and generally if you host untrusted apps in your server and allows them to read others uid /proc/<pid>
169 files you have higher problems...
170 */
171 auth = apr_table_get(r->headers_in, "Authorization");
172 if (auth) {
173 apr_table_setn(r->subprocess_env, "HTTP_AUTHORIZATION", auth);
174 }
175
176 script_name = apr_table_get(r->subprocess_env, "SCRIPT_NAME");
177 path_info = apr_table_get(r->subprocess_env, "PATH_INFO");
178
179 if (script_name && path_info) {
180 if (strcmp(path_info, "/")) {
181 apr_table_set(r->subprocess_env, "SCRIPT_NAME",
183 strlen(script_name) -
184 strlen(path_info)));
185 }
186 else {
187 if (!strcmp(script_name, "/")) {
188 apr_table_setn(r->subprocess_env, "SCRIPT_NAME", "");
189 }
190 }
191 }
192
194 env = (apr_table_entry_t *) env_table->elts;
195
196 for (j = 0; j < env_table->nelts; ++j) {
197 headerlen += 2 + strlen(env[j].key) + 2 + (env[j].val ? strlen(env[j].val) : 0);
198 }
199
200 pktsize = headerlen - 4;
201 if (pktsize > APR_UINT16_MAX) {
203 "can't send headers to %s:%u: packet size too "
204 "large (%" APR_SIZE_T_FMT ")",
205 conn->hostname, conn->port, pktsize);
207 }
208
209 ptr = buf = apr_palloc(r->pool, headerlen);
210
211 ptr += 4;
212
213 for (j = 0; j < env_table->nelts; ++j) {
214 keylen = strlen(env[j].key);
215 *ptr++ = (apr_byte_t) (keylen & 0xff);
216 *ptr++ = (apr_byte_t) ((keylen >> 8) & 0xff);
217 memcpy(ptr, env[j].key, keylen);
218 ptr += keylen;
219
220 vallen = env[j].val ? strlen(env[j].val) : 0;
221 *ptr++ = (apr_byte_t) (vallen & 0xff);
222 *ptr++ = (apr_byte_t) ((vallen >> 8) & 0xff);
223 if (env[j].val) {
224 memcpy(ptr, env[j].val, vallen);
225 }
226 ptr += vallen;
227 }
228
229 buf[0] = 0;
230 buf[1] = (apr_byte_t) (pktsize & 0xff);
231 buf[2] = (apr_byte_t) ((pktsize >> 8) & 0xff);
232 buf[3] = 0;
233
234 return uwsgi_send(conn, buf, headerlen, r);
235}
236
237
239{
241 char *buf = apr_palloc(r->pool, AP_IOBUFSIZE);
242 int status;
243 long readlen;
244
246 while (readlen > 0) {
248 if (status != OK) {
250 }
252 }
253 if (readlen == -1) {
255 "receiving request body failed");
257 }
258 }
259
260 return OK;
261}
262
264{
267
268 apr_pool_create(&pool, c->pool);
269 apr_pool_tag(pool, "proxy_uwsgi_rp");
270
271 rp = apr_pcalloc(pool, sizeof(*r));
272
273 rp->pool = pool;
274 rp->status = HTTP_OK;
275
276 rp->headers_in = apr_table_make(pool, 50);
277 rp->subprocess_env = apr_table_make(pool, 50);
278 rp->headers_out = apr_table_make(pool, 12);
279 rp->err_headers_out = apr_table_make(pool, 5);
280 rp->notes = apr_table_make(pool, 5);
281
282 rp->server = r->server;
283 rp->log = r->log;
284 rp->proxyreq = r->proxyreq;
285 rp->request_time = r->request_time;
286 rp->connection = c;
287 rp->output_filters = c->output_filters;
288 rp->input_filters = c->input_filters;
289 rp->proto_output_filters = c->output_filters;
290 rp->proto_input_filters = c->input_filters;
291 rp->useragent_ip = c->client_ip;
292 rp->useragent_addr = c->client_addr;
293
294 rp->request_config = ap_create_request_config(pool);
296
297 return rp;
298}
299
301 proxy_server_conf * conf)
302{
303
305 const char *buf;
306 char *value, *end;
307 char keepchar;
308 int len;
309 int backend_broke = 0;
310 int status_start;
311 int status_end;
312 int finish = 0;
315 apr_status_t rv;
316 apr_bucket *e;
320 proxy_dir_conf *dconf;
321
323 rp->proxyreq = PROXYREQ_RESPONSE;
324
325 bb = apr_brigade_create(r->pool, c->bucket_alloc);
326 pass_bb = apr_brigade_create(r->pool, c->bucket_alloc);
327
328 len = ap_getline(buffer, sizeof(buffer), rp, 1);
329 if (len <= 0) {
330 /* invalid or empty */
332 }
333 backend->worker->s->read += len;
334 if ((apr_size_t)len >= sizeof(buffer)) {
335 /* too long */
337 }
338
339 /* Position of http status code */
340 if (apr_date_checkmask(buffer, "HTTP/#.# ###*")) {
341 status_start = 9;
342 }
343 else if (apr_date_checkmask(buffer, "HTTP/# ###*")) {
344 status_start = 7;
345 }
346 else {
347 /* not HTTP */
348 return HTTP_BAD_GATEWAY;
349 }
351
353 buffer[status_end] = '\0';
355
356 if (keepchar != '\0') {
358 }
359 else {
360 /* 2616 requires the space in Status-Line; the origin
361 * server may have sent one but ap_rgetline_core will
362 * have stripped it. */
363 buffer[status_end] = ' ';
364 buffer[status_end + 1] = '\0';
365 }
367
368 /* parse headers */
369 while ((len = ap_getline(buffer, sizeof(buffer), rp, 1)) > 0) {
370 if ((apr_size_t)len >= sizeof(buffer)) {
371 /* too long */
372 len = -1;
373 break;
374 }
375 value = strchr(buffer, ':');
376 if (!value) {
377 /* invalid header */
378 len = -1;
379 break;
380 }
381 *value++ = '\0';
383 /* invalid name */
384 len = -1;
385 break;
386 }
387 while (apr_isspace(*value))
388 ++value;
389 for (end = &value[strlen(value) - 1];
390 end > value && apr_isspace(*end); --end)
391 *end = '\0';
393 /* invalid value */
394 len = -1;
395 break;
396 }
398 }
399 if (len < 0) {
400 /* Reset headers, but not to NULL because things below the chain expect
401 * this to be non NULL e.g. the ap_content_length_filter.
402 */
404 return HTTP_BAD_GATEWAY;
405 }
406
407 /* T-E wins over C-L */
408 if (apr_table_get(r->headers_out, "Transfer-Encoding")) {
409 apr_table_unset(r->headers_out, "Content-Length");
410 backend->close = 1;
411 }
412
413 if ((buf = apr_table_get(r->headers_out, "Content-Type"))) {
415 }
416
417 /* honor ProxyErrorOverride and ErrorDocument */
418#if AP_MODULE_MAGIC_AT_LEAST(20101106,0)
419 dconf =
420 ap_get_module_config(r->per_dir_config, &proxy_module);
421 if (ap_proxy_should_override(dconf, r->status)) {
422#else
423 if (ap_proxy_should_override(conf, r->status)) {
424#endif
425 int status = r->status;
426 r->status = HTTP_OK;
427 r->status_line = NULL;
428
431
432 return status;
433 }
434
435 while (!finish) {
436 rv = ap_get_brigade(rp->input_filters, bb,
439 || (rv == APR_SUCCESS && APR_BRIGADE_EMPTY(bb))) {
440 e = apr_bucket_flush_create(c->bucket_alloc);
442 if (ap_pass_brigade(r->output_filters, bb) || c->aborted) {
443 break;
444 }
447 continue;
448 }
449 else if (rv == APR_EOF) {
450 break;
451 }
452 else if (rv != APR_SUCCESS) {
455 backend_broke = 1;
456 break;
457 }
458
461 backend->worker->s->read += readbytes;
462
463 if (APR_BRIGADE_EMPTY(bb)) {
465 break;
466 }
467
469
470 /* found the last brigade? */
472 finish = 1;
473
474 /* do not pass chunk if it is zero_sized */
476
477 if ((readbytes > 0
479 || c->aborted) {
480 finish = 1;
481 }
482
485 }
486
487 e = apr_bucket_eos_create(c->bucket_alloc);
490
492
493 if (c->aborted || backend_broke) {
494 return DONE;
495 }
496
497 return OK;
498}
499
501 proxy_server_conf * conf, char *url,
502 const char *proxyname, apr_port_t proxyport)
503{
504 int status;
505 proxy_conn_rec *backend = NULL;
506 apr_pool_t *p = r->pool;
507 char server_portstr[32];
508 char *u_path_info;
509 apr_uri_t *uri;
510
511 if (ap_cstr_casecmpn(url, UWSGI_SCHEME "://", sizeof(UWSGI_SCHEME) + 2)) {
512 ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, "declining URL %s", url);
513 return DECLINED;
514 }
515
516 uri = apr_palloc(r->pool, sizeof(*uri));
517
518 /* ADD PATH_INFO (unescaped) */
519 u_path_info = ap_strchr(url + sizeof(UWSGI_SCHEME) + 2, '/');
520 if (!u_path_info) {
521 u_path_info = apr_pstrdup(r->pool, "/");
522 }
523 else if (ap_unescape_url(u_path_info) != OK) {
525 "unable to decode uwsgi uri: %s", url);
527 }
528 else {
529 /* Remove duplicate slashes at the beginning of PATH_INFO */
530 while (u_path_info[1] == '/') {
531 u_path_info++;
532 }
533 }
535
536 /* Create space for state information */
538 r->server);
539 if (status != OK) {
540 goto cleanup;
541 }
542 backend->is_ssl = 0;
543
544 /* Step One: Determine Who To Connect To */
545 status = ap_proxy_determine_connection(p, r, conf, worker, backend,
547 server_portstr,
548 sizeof(server_portstr));
549 if (status != OK) {
550 goto cleanup;
551 }
552
553
554 /* Step Two: Make the Connection */
555 if (ap_proxy_connect_backend(UWSGI_SCHEME, backend, worker, r->server)) {
557 "failed to make connection to backend: %s:%u",
558 backend->hostname, backend->port);
560 goto cleanup;
561 }
562
563 /* Step Three: Create conn_rec */
565 r->connection,
566 r->server)) != OK)
567 goto cleanup;
568
569 /* Step Four: Process the Request */
571 || ((status = uwsgi_send_headers(r, backend)) != OK)
572 || ((status = uwsgi_send_body(r, backend)) != OK)
573 || ((status = uwsgi_response(r, backend, conf)) != OK)) {
574 goto cleanup;
575 }
576
577 cleanup:
578 if (backend) {
579 backend->close = 1; /* always close the socket */
581 }
582 return status;
583}
584
585
591
592
593module AP_MODULE_DECLARE_DATA proxy_uwsgi_module = {
594 STANDARD20_MODULE_STUFF,
595 NULL, /* create per-directory config structure */
596 NULL, /* merge per-directory config structures */
597 NULL, /* create per-server config structure */
598 NULL, /* merge per-server config structures */
599 NULL, /* command table */
600 register_hooks /* register hooks */
601};
const char apr_size_t len
Definition ap_regex.h:187
APR-UTIL Buckets/Bucket Brigades.
Apache hook functions.
Apache optional hook functions.
apr_size_t const unsigned char unsigned int unsigned int d
Definition apr_siphash.h:72
APR Strings library.
#define ap_get_module_config(v, m)
ap_conf_vector_t * ap_create_request_config(apr_pool_t *p)
Definition config.c:356
request_rec int int apr_table_t const char * path
request_rec * r
#define HUGE_STRING_LEN
Definition httpd.h:303
#define AP_IOBUFSIZE
Definition httpd.h:306
#define DECLINED
Definition httpd.h:457
#define OK
Definition httpd.h:456
#define DONE
Definition httpd.h:458
apr_status_t ap_pass_brigade(ap_filter_t *filter, apr_bucket_brigade *bucket)
apr_status_t ap_get_brigade(ap_filter_t *filter, apr_bucket_brigade *bucket, ap_input_mode_t mode, apr_read_type_e block, apr_off_t readbytes)
#define ap_get_core_module_config(v)
Definition http_core.h:383
#define APLOGNO(n)
Definition http_log.h:117
#define ap_log_rerror
Definition http_log.h:454
#define APLOG_ERR
Definition http_log.h:67
#define APLOG_MARK
Definition http_log.h:283
#define APLOG_DEBUG
Definition http_log.h:71
const unsigned char * buf
Definition util_md5.h:50
int ap_should_client_block(request_rec *r)
void ap_set_content_type(request_rec *r, const char *ct)
int ap_getline(char *s, int n, request_rec *r, int flags)
Definition protocol.c:545
long ap_get_client_block(request_rec *r, char *buffer, apr_size_t bufsiz)
int ap_setup_client_block(request_rec *r, int read_policy)
void ap_add_common_vars(request_rec *r)
void ap_add_cgi_vars(request_rec *r)
const char apr_port_t port
Definition http_vhost.h:125
const char * host
Definition http_vhost.h:124
#define APR_EOF
Definition apr_errno.h:461
#define APR_STATUS_IS_EAGAIN(s)
Definition apr_errno.h:1272
#define APR_BRIGADE_LAST(b)
#define APR_BRIGADE_INSERT_TAIL(b, e)
apr_read_type_e
Definition apr_buckets.h:57
apr_bucket * e
#define APR_BRIGADE_EMPTY(b)
#define APR_BUCKET_IS_EOS(e)
int apr_off_t * length
@ APR_BLOCK_READ
Definition apr_buckets.h:58
@ APR_NONBLOCK_READ
Definition apr_buckets.h:59
apr_dbd_transaction_t int mode
Definition apr_dbd.h:261
const char apr_ssize_t int flags
Definition apr_encode.h:168
const char * url
Definition apr_escape.h:120
#define APR_HOOK_FIRST
Definition apr_hooks.h:301
const char * uri
Definition apr_uri.h:159
#define HTTP_OK
Definition httpd.h:490
#define HTTP_BAD_REQUEST
Definition httpd.h:508
#define HTTP_SERVICE_UNAVAILABLE
Definition httpd.h:538
#define HTTP_BAD_GATEWAY
Definition httpd.h:537
#define HTTP_INTERNAL_SERVER_ERROR
Definition httpd.h:535
#define HTTP_FORBIDDEN
Definition httpd.h:511
int ap_proxy_connect_backend(const char *proxy_function, proxy_conn_rec *conn, proxy_worker *worker, server_rec *s)
int ap_proxy_should_override(proxy_dir_conf *conf, int code)
char * ap_proxy_canon_netloc(apr_pool_t *p, char **const urlp, char **userp, char **passwordp, char **hostp, apr_port_t *port)
Definition proxy_util.c:342
int ap_proxy_release_connection(const char *proxy_function, proxy_conn_rec *conn, server_rec *s)
int ap_proxy_acquire_connection(const char *proxy_function, proxy_conn_rec **conn, proxy_worker *worker, server_rec *s)
char * ap_proxy_canonenc_ex(apr_pool_t *p, const char *x, int len, enum enctype t, int flags, int proxyreq)
Definition proxy_util.c:220
void ap_proxy_backend_broke(request_rec *r, apr_bucket_brigade *brigade)
#define PROXY_CANONENC_NOENCODEDSLASHENCODING
Definition mod_proxy.h:81
apr_status_t ap_proxy_buckets_lifetime_transform(request_rec *r, apr_bucket_brigade *from, apr_bucket_brigade *to)
void proxy_hook_canon_handler(proxy_HOOK_canon_handler_t *pf, const char *const *aszPre, const char *const *aszSucc, int nOrder)
Definition mod_proxy.c:3412
int ap_proxy_determine_connection(apr_pool_t *p, request_rec *r, proxy_server_conf *conf, proxy_worker *worker, proxy_conn_rec *conn, apr_uri_t *uri, char **url, const char *proxyname, apr_port_t proxyport, char *server_portstr, int server_portstr_size)
void proxy_hook_scheme_handler(proxy_HOOK_scheme_handler_t *pf, const char *const *aszPre, const char *const *aszSucc, int nOrder)
Definition mod_proxy.c:3406
int ap_proxy_connection_create(const char *proxy_function, proxy_conn_rec *conn, conn_rec *c, server_rec *s)
int proxy_run_create_req(request_rec *r, request_rec *pr)
Definition proxy_util.c:92
@ enc_path
Definition mod_proxy.h:76
#define ap_strchr(s, c)
Definition httpd.h:2351
const char * ap_scan_http_token(const char *ptr)
Definition util.c:1664
const char * ap_scan_vchar_obstext(const char *ptr)
Definition util.c:1674
int ap_cstr_casecmpn(const char *s1, const char *s2, apr_size_t n)
Definition util.c:3559
const char * ap_scan_http_field_content(const char *ptr)
Definition util.c:1654
int ap_unescape_url(char *url)
Definition util.c:1939
#define PROXYREQ_RESPONSE
Definition httpd.h:1136
apr_size_t size
apr_uint32_t val
Definition apr_atomic.h:66
const char int apr_pool_t * pool
Definition apr_cstr.h:84
#define apr_isspace(c)
Definition apr_lib.h:225
const char * value
Definition apr_env.h:51
#define APR_SUCCESS
Definition apr_errno.h:225
int apr_status_t
Definition apr_errno.h:44
const char * key
void const char apr_status_t(* cleanup)(void *))
char * buffer
apr_vformatter_buff_t * c
Definition apr_lib.h:175
char const *const char const *const ** env
apr_uint16_t apr_port_t
#define apr_pool_create(newpool, parent)
Definition apr_pools.h:322
#define apr_pcalloc(p, size)
Definition apr_pools.h:465
const char char ** end
apr_int32_t apr_int32_t apr_int32_t err
int int status
#define REQUEST_CHUNKED_ERROR
Definition httpd.h:748
Apache Configuration.
Apache Logging library.
HTTP protocol handling.
Apache Request library.
HTTP Daemon routines.
apr_pool_t * p
Definition md_event.c:32
Proxy Extension Module for Apache.
static int uwsgi_handler(request_rec *r, proxy_worker *worker, proxy_server_conf *conf, char *url, const char *proxyname, apr_port_t proxyport)
static int uwsgi_send(proxy_conn_rec *conn, const char *buf, apr_size_t length, request_rec *r)
static int uwsgi_response(request_rec *r, proxy_conn_rec *backend, proxy_server_conf *conf)
static int uwsgi_send_headers(request_rec *r, proxy_conn_rec *conn)
static int uwsgi_canon(request_rec *r, char *url)
static void register_hooks(apr_pool_t *p)
#define UWSGI_SCHEME
#define UWSGI_DEFAULT_PORT
static int uwsgi_send_body(request_rec *r, proxy_conn_rec *conn)
static request_rec * make_fake_req(conn_rec *c, request_rec *r)
return NULL
Definition mod_so.c:359
#define APR_UINT16_MAX
Definition apr_tables.h:81
Structure to store things which are per connection.
Definition httpd.h:1152
Per-directory configuration.
Definition http_core.h:527
const char * hostname
Definition mod_proxy.h:275
apr_socket_t * sock
Definition mod_proxy.h:278
proxy_worker * worker
Definition mod_proxy.h:273
apr_port_t port
Definition mod_proxy.h:282
unsigned int is_ssl
Definition mod_proxy.h:283
unsigned int close
Definition mod_proxy.h:284
conn_rec * connection
Definition mod_proxy.h:270
apr_size_t io_buffer_size
Definition mod_proxy.h:177
apr_off_t transferred
Definition mod_proxy.h:462
proxy_worker_shared * s
Definition mod_proxy.h:505
A structure that represents the current request.
Definition httpd.h:845
int status
Definition httpd.h:891
struct ap_filter_t * output_filters
Definition httpd.h:1070
apr_table_t * notes
Definition httpd.h:985
apr_pool_t * pool
Definition httpd.h:847
char * filename
Definition httpd.h:1018
apr_time_t request_time
Definition httpd.h:886
int proxyreq
Definition httpd.h:873
conn_rec * connection
Definition httpd.h:849
const struct ap_logconf * log
Definition httpd.h:1054
apr_table_t * headers_in
Definition httpd.h:976
apr_table_t * subprocess_env
Definition httpd.h:983
server_rec * server
Definition httpd.h:851
struct ap_conf_vector_t * per_dir_config
Definition httpd.h:1047
const char * status_line
Definition httpd.h:889
apr_table_t * headers_out
Definition httpd.h:978
struct ap_logconf log
Definition httpd.h:1335
apr_status_t apr_socket_send(apr_socket_t *sock, const char *buf, apr_size_t *len)
Definition sendrecv.c:30
@ AP_MODE_READBYTES
Definition util_filter.h:43
Apache script tools.
static size_t keylen(KEY s)
Definition xmlparse.c:7166