/* 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.
*/
request_rec *r; /* the request processed in this ctx */
apr_status_t r_status; /* status of request work */ int r_done; /* request was processed, not necessarily successfully */ int r_may_retry; /* request may be retried */ int has_reusable_session; /* http2 session is live and clean */
} h2_proxy_ctx;
/* do syntatic check. * We break the URL into host, port, path, search
*/
err = ap_proxy_canon_netloc(r->pool, &url, NULL, NULL, &host, &port); if (err) {
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(03350) "error parsing URL %s: %s", url, err); return HTTP_BAD_REQUEST;
}
/* * now parse path/search args, according to rfc1738: * process the path. * * In a reverse proxy, our URL has been processed, so canonicalise * unless proxy-nocanon is set to say it's raw * In a forward proxy, we have and MUST NOT MANGLE the original.
*/ switch (r->proxyreq) { default: /* wtf are we doing here? */ case PROXYREQ_REVERSE: if (apr_table_get(r->notes, "proxy-nocanon")) {
path = url; /* this is the raw path */
} elseif (apr_table_get(r->notes, "proxy-noencode")) {
path = url; /* this is the encoded path already */
search = r->args;
} else { #ifdef PROXY_CANONENC_NOENCODEDSLASHENCODING
core_dir_config *d = ap_get_core_module_config(r->per_dir_config); int flags = d->allow_encoded_slashes && !d->decode_encoded_slashes ? PROXY_CANONENC_NOENCODEDSLASHENCODING : 0;
path = ap_proxy_canonenc_ex(r->pool, url, (int)strlen(url),
enc_path, flags, r->proxyreq); #else
path = ap_proxy_canonenc(r->pool, url, (int)strlen(url),
enc_path, 0, r->proxyreq); #endif if (!path) { return HTTP_BAD_REQUEST;
}
search = r->args;
} break; case PROXYREQ_PROXY:
path = url; break;
} /* * If we have a raw control character or a ' ' in nocanon path or * r->args, correct encoding was missed.
*/ if (path == url && *ap_scan_vchar_obstext(path)) {
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(10420) "To be forwarded path contains control " "characters or spaces"); return HTTP_FORBIDDEN;
} if (search && *ap_scan_vchar_obstext(search)) {
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(10412) "To be forwarded query string contains control " "characters or spaces"); return HTTP_FORBIDDEN;
}
status = h2_proxy_session_process(session); if (status != APR_SUCCESS) { /* Encountered an error during session processing */
ap_log_cerror(APLOG_MARK, APLOG_DEBUG, status, ctx->cfront,
APLOGNO(03375) "eng(%s): end of session %s",
ctx->id, session->id); /* Any open stream of that session needs to * a) be reopened on the new session iff safe to do so * b) reported as done (failed) otherwise
*/
h2_proxy_session_cleanup(session, session_req_done); goto out;
}
}
/* scheme says, this is for us. */
apr_table_setn(ctx->r->notes, H2_PROXY_REQ_URL_NOTE, url);
ap_log_rerror(APLOG_MARK, APLOG_TRACE1, 0, ctx->r, "H2: serving URL %s", url);
run_connect: if (ctx->cfront->aborted) goto cleanup;
/* Get a proxy_conn_rec from the worker, might be a new one, might * be one still open from another request, or it might fail if the
* worker is stopped or in error. */ if ((status = ap_proxy_acquire_connection(ctx->proxy_func, &ctx->p_conn,
ctx->worker, ctx->server)) != OK) { goto cleanup;
}
locurl = url;
ctx->p_conn->is_ssl = ctx->is_ssl;
/* Step One: Determine the URL to connect to (might be a proxy), * initialize the backend accordingly and determine the server
* port string we can expect in responses. */ if ((status = ap_proxy_determine_connection(ctx->pool, ctx->r, conf, worker,
ctx->p_conn, &uri, &locurl,
proxyname, proxyport,
ctx->server_portstr, sizeof(ctx->server_portstr))) != OK) { goto cleanup;
}
/* Step Two: Make the Connection (or check that an already existing * socket is still usable). On success, we have a socket connected to
* backend->hostname. */ if (ap_proxy_connect_backend(ctx->proxy_func, ctx->p_conn, ctx->worker,
ctx->server)) {
ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, ctx->cfront, APLOGNO(03352) "H2: failed to make connection to backend: %s",
ctx->p_conn->hostname); goto cleanup;
}
/* Step Three: Create conn_rec for the socket we have open now. */
status = ap_proxy_connection_create_ex(ctx->proxy_func, ctx->p_conn, ctx->r); if (status != OK) {
ap_log_cerror(APLOG_MARK, APLOG_DEBUG, status, ctx->cfront, APLOGNO(03353) "setup new connection: is_ssl=%d %s %s %s",
ctx->p_conn->is_ssl, ctx->p_conn->ssl_hostname,
locurl, ctx->p_conn->hostname);
ctx->r_status = status; goto cleanup;
}
if (!ctx->p_conn->data && ctx->is_ssl) { /* New SSL connection: set a note on the connection about what
* protocol we need. */
apr_table_setn(ctx->p_conn->connection->notes, "proxy-request-alpn-protos", "h2");
}
if (ctx->cfront->aborted) goto cleanup;
status = ctx_run(ctx);
if (ctx->r_status != APR_SUCCESS && ctx->r_may_retry && !ctx->cfront->aborted) { /* Not successfully processed, but may retry, tear down old conn and start over */ if (ctx->p_conn) {
ctx->p_conn->close = 1; #if AP_MODULE_MAGIC_AT_LEAST(20140207, 2)
proxy_run_detach_backend(r, ctx->p_conn); #endif
ap_proxy_release_connection(ctx->proxy_func, ctx->p_conn, ctx->server);
ctx->p_conn = NULL;
}
++reconnects; if (reconnects < 2) { goto run_connect;
}
ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, ctx->cfront, APLOGNO(10023) "giving up after %d reconnects, request-done=%d",
reconnects, ctx->r_done);
}
cleanup: if (ctx->p_conn) { if (status != APR_SUCCESS || !ctx->has_reusable_session) { /* close socket when errors happened or session is not "clean",
* meaning in a working condition with no open streams */
ctx->p_conn->close = 1;
} #if AP_MODULE_MAGIC_AT_LEAST(20140207, 2)
proxy_run_detach_backend(ctx->r, ctx->p_conn); #endif
ap_proxy_release_connection(ctx->proxy_func, ctx->p_conn, ctx->server);
ctx->p_conn = 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.0.3Bemerkung:
(vorverarbeitet)
¤
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.