/* 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_scgi.c * Proxy backend module for the SCGI protocol * (http://python.ca/scgi/protocol.txt) * * Andr� Malo (nd/perlig.de), August 2007
*/
/* * We create our own bucket type, which is actually derived (c&p) from the * socket bucket. * Maybe some time this should be made more abstract (like passing an * interception function to read or something) and go into the ap_ or * even apr_ namespace.
*/
/* Change the current bucket to refer to what we read */
a = apr_bucket_heap_make(a, buf, *len, apr_bucket_free);
h = a->data;
h->alloc_len = APR_BUCKET_BUFF_SIZE; /* note the real buffer size */
*str = buf;
APR_BUCKET_INSERT_AFTER(a, bucket_socket_ex_create(data, a->list));
} else {
apr_bucket_free(buf);
a = apr_bucket_immortal_make(a, "", 0);
*str = a->data;
} return APR_SUCCESS;
}
/* * The header blob basically takes the environment and concatenates * keys and values using 0 bytes. There are special treatments here: * - GATEWAY_INTERFACE and SCGI_MAGIC are dropped * - CONTENT_LENGTH is always set and must be sent as the very first * variable * * Additionally it's wrapped into a so-called netstring (see SCGI spec)
*/
env_table = apr_table_elts(r->subprocess_env);
env = (apr_table_entry_t *)env_table->elts; for (j = 0; j < env_table->nelts; ++j) { if ( (!strcmp(env[j].key, GATEWAY_INTERFACE))
|| (!strcmp(env[j].key, CONTENT_LENGTH))
|| (!strcmp(env[j].key, SCGI_MAGIC))) { continue;
}
headerlen += strlen(env[j].key) + strlen(env[j].val) + 2;
}
bodylen = apr_psprintf(r->pool, "%" APR_OFF_T_FMT, r->remaining);
bodylen_size = strlen(bodylen) + 1;
headerlen += bodylen_size;
/* * Send request body (if any)
*/ staticint send_request_body(request_rec *r, proxy_conn_rec *conn)
{ if (ap_should_client_block(r)) { char *buf = apr_palloc(r->pool, AP_IOBUFSIZE); int status; long readlen;
readlen = ap_get_client_block(r, buf, AP_IOBUFSIZE); while (readlen > 0) {
status = sendall(conn, buf, (apr_size_t)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, APLOGNO(00859) "receiving request body failed"); return HTTP_INTERNAL_SERVER_ERROR;
}
}
return OK;
}
/* * Fetch response from backend and pass back to the front
*/ staticint pass_response(request_rec *r, proxy_conn_rec *conn)
{
apr_bucket_brigade *bb;
apr_bucket *b; constchar *location;
scgi_config *conf;
socket_ex_data *sock_data; int status;
/* SCGI has its own body framing mechanism which we don't * match against any provided Content-Length, so let the * core determine C-L vs T-E based on what's actually sent.
*/ if (!apr_table_get(r->subprocess_env, AP_TRUST_CGILIKE_CL_ENVVAR))
apr_table_unset(r->headers_out, "Content-Length");
apr_table_unset(r->headers_out, "Transfer-Encoding");
conf = ap_get_module_config(r->per_dir_config, &proxy_scgi_module); if (conf->sendfile && conf->sendfile != scgi_sendfile_off) { short err = 1;
/* Create space for state information */
status = ap_proxy_acquire_connection(PROXY_FUNCTION, &backend, worker,
r->server); if (status != OK) { goto cleanup;
}
backend->is_ssl = 0;
/* Step One: Determine Who To Connect To */
uri = apr_palloc(p, sizeof(*uri));
status = ap_proxy_determine_connection(p, r, conf, worker, backend,
uri, &url, proxyname, proxyport,
&dummy, 1); if (status != OK) { goto cleanup;
}
/* Step Two: Make the Connection */ if (ap_proxy_connect_backend(PROXY_FUNCTION, backend, worker, r->server)) {
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(00866) "failed to make connection to backend: %s:%u",
backend->hostname, backend->port);
status = HTTP_SERVICE_UNAVAILABLE; goto cleanup;
}
staticconst command_rec scgi_cmds[] =
{
AP_INIT_TAKE1("ProxySCGISendfile", scgi_set_send_file, NULL,
RSRC_CONF|ACCESS_CONF, "The name of the X-Sendfile pseudo response header or " "On or Off"),
AP_INIT_TAKE1("ProxySCGIInternalRedirect", scgi_set_internal_redirect, NULL,
RSRC_CONF|ACCESS_CONF, "The name of the pseudo response header or On or Off"),
{NULL}
};
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung ist noch experimentell.