mod_serf.c revision 51671516558a4ae29a50067a3cc67a3f684b7446
/* 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
*
*
* 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.
*/
#include "httpd.h"
#include "http_core.h"
#include "http_config.h"
#include "http_protocol.h"
#include "http_log.h"
#include "serf.h"
#include "serf_bucket_types.h"
#include "serf_bucket_util.h"
#include "apr_uri.h"
typedef struct {
int on;
typedef struct {
int rstatus;
int want_ssl;
int done_headers;
int keep_reading;
request_rec *r;
} s_baton_t;
void *closed_baton,
{
if (why) {
/* justin says that error handling isn't done yet. hah. */
/* XXXXXX: review */
return;
}
}
void *setup_baton,
{
serf_bucket_t *c;
}
return c;
}
{
/* XXXXX: List of headers not to copy to serf. serf's serf_bucket_headers_setn,
* doesn't actually overwrite a header if we set it once, so we need to ignore anything
* we might want to toggle or combine.
*/
switch (key[0]) {
case 'a':
case 'A':
return 0;
}
break;
case 'c':
case 'C':
return 0;
}
break;
case 'h':
case 'H':
return 0;
}
break;
case 'k':
case 'K':
return 0;
}
break;
case 't':
case 'T':
return 0;
}
return 0;
}
break;
case 'u':
case 'U':
return 0;
}
break;
default:
break;
}
return 0;
}
{
int done = 0;
/* XXXXX: Special Treatment required for MANY other headers. fixme.*/
switch (key[0]) {
case 'c':
case 'C':
done = 1;
break;
}
done = 1;
break;
}
done = 1;
break;
}
done = 1;
break;
}
break;
case 't':
case 'T':
done = 1;
break;
}
break;
default:
break;
}
if (!done) {
}
return 0;
}
void *acceptor_baton,
{
serf_bucket_t *c;
/* get the per-request bucket allocator */
/* Create a barrier so the response doesn't eat us! */
return serf_bucket_response_create(c, bkt_alloc);
}
void *vbaton,
{
const char *data;
/* XXXXXXX: Create better error message. */
if (rv) {
if (APR_STATUS_IS_EAGAIN(rv)) {
return APR_SUCCESS;
}
return rv;
}
/**
* XXXXX: If I understood serf buckets better, it might be possible to not
* copy all of the data here, and better stream it to the client.
**/
do {
if (SERF_BUCKET_READ_ERROR(rv)) {
return rv;
}
if (!ctx->done_headers) {
}
/* XXXX: write to brigades and stuff. meh */
if (APR_STATUS_IS_EOF(rv)) {
ctx->keep_reading = 0;
return APR_EOF;
}
/* XXXX: Should we send a flush now? */
if (APR_STATUS_IS_EAGAIN(rv)) {
return APR_SUCCESS;
}
} while (1);
}
void *vbaton,
void **acceptor_baton,
void **handler_baton,
{
/* XXXXX: handle incoming request bodies */
/* XXXXXX: SerfPreserveHost on */
}
else {
}
}
*acceptor_baton = ctx;
*handler_baton = ctx;
return APR_SUCCESS;
}
{
/* XXXXX: make persistent/per-process or something.*/
/* XXXXX: cache dns? */
pool);
if (rv != APR_SUCCESS) {
return HTTP_INTERNAL_SERVER_ERROR;
}
baton.r = r;
baton.done_headers = 0;
}
else {
}
conn_setup, &baton,
pool);
&baton);
do {
/* XXXX: Handle timeouts */
if (APR_STATUS_IS_TIMEUP(rv)) {
continue;
}
if (rv != APR_SUCCESS) {
return HTTP_INTERNAL_SERVER_ERROR;
}
} while (baton.keep_reading);
}
typedef struct {
typedef struct {
/* Forward-declare */
{
}
{
apr_bucket *b, *end, *f;
}
}
return status;
}
int acceptable, int *found,
{
if (APR_STATUS_IS_EAGAIN(status)) {
if (found) {
}
}
return status;
}
const char **data,
{
return APR_ENOTIMPL;
}
{
}
const serf_bucket_type_t serf_bucket_type_brigade = {
};
{
return ctx;
}
{
if (mode == AP_MODE_INIT) {
return APR_SUCCESS;
}
if (!ctx)
{
}
if (mode == AP_MODE_GETLINE) {
const char *data;
int found;
apr_bucket *b;
return APR_SUCCESS;
}
if (mode == AP_MODE_READBYTES) {
const char *data;
apr_bucket *b;
return APR_SUCCESS;
}
mode == AP_MODE_SPECULATIVE) {
abort();
}
}
{
conn_rec *c = f->c;
if (!ctx) {
}
return APR_SUCCESS;
}
static ap_filter_rec_t *serf_input_filter_handle;
static ap_filter_rec_t *serf_output_filter_handle;
{
net->c = c;
return DONE;
}
static int serf_handler(request_rec *r)
{
&serf_module);
return DECLINED;
}
return drive_serf(r, conf);
}
const char *vdest)
{
if (rv != APR_SUCCESS) {
return "mod_serf: Unable to parse SerfPass url.";
}
/* XXXX: These are bugs in apr_uri_parse. Fixme. */
}
}
return NULL;
}
{
return new;
}
static const command_rec serf_cmds[] =
{
"A prefix and destination"),
{NULL}
};
static void register_hooks(apr_pool_t *p)
{
}
{
NULL,
NULL,
NULL,
};