/* 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.
*/
if (!apr_table_get(r->headers_in, "Upgrade")) { /* No Upgrade, let mod_proxy_http handle it (for instance). * Note: anything but OK/DECLINED will do (i.e. bypass wstunnel w/o * aborting the request), HTTP_UPGRADE_REQUIRED is documentary...
*/ return HTTP_UPGRADE_REQUIRED;
}
return OK;
}
/* * Canonicalise http-like URLs. * scheme is the scheme for the URL * url is the URL starting with the first '/' * def_port is the default port for this scheme.
*/ staticint proxy_wstunnel_canon(request_rec *r, char *url)
{
proxyws_dir_conf *dconf = ap_get_module_config(r->per_dir_config,
&proxy_wstunnel_module); char *host, *path, sport[7]; char *search = NULL; constchar *err; char *scheme;
apr_port_t port, def_port;
/* * do syntactic 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(02439) "error parsing URL %s: %s",
url, err); return HTTP_BAD_REQUEST;
}
/* * now parse path/search args, according to rfc1738: * process the path. With proxy-nocanon set (by * mod_proxy) we use the raw, unparsed uri
*/ 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 {
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, strlen(url), enc_path, flags,
r->proxyreq); if (!path) { return HTTP_BAD_REQUEST;
}
search = r->args;
} /* * 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(10419) "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(10409) "To be forwarded query string contains control " "characters or spaces"); return HTTP_FORBIDDEN;
}
/* This handler should take care of the entire connection; make it so that
* nothing else is attempted on the connection after returning. */
c->keepalive = AP_CONN_CLOSE;
do { /* Loop until done (one side closes the connection, or an error) */
rv = apr_pollset_poll(pollset, -1, &pollcnt, &signalled); if (rv != APR_SUCCESS) { if (APR_STATUS_IS_EINTR(rv)) { continue;
}
ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, APLOGNO(02444) "error apr_poll()"); return HTTP_INTERNAL_SERVER_ERROR;
}
ap_log_rerror(APLOG_MARK, APLOG_TRACE1, 0, r, APLOGNO(02445) "woke from poll(), i=%d", pollcnt);
for (pi = 0; pi < pollcnt; pi++) { const apr_pollfd_t *cur = &signalled[pi];
/* create space for state information */
status = ap_proxy_acquire_connection(scheme, &backend, worker, r->server); if (status != OK) { goto cleanup;
}
backend->is_ssl = is_ssl;
backend->close = 0;
/* Step One: Determine Who To Connect To */
status = ap_proxy_determine_connection(p, r, conf, worker, backend,
uri, &locurl, proxyname, proxyport,
server_portstr, sizeof(server_portstr)); if (status != OK) { goto cleanup;
}
/* Step Two: Make the Connection */ if (ap_proxy_connect_backend(scheme, backend, worker, r->server)) {
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(02452) "failed to make connection to backend: %s",
backend->hostname);
status = HTTP_SERVICE_UNAVAILABLE; goto cleanup;
}
/* Step Three: Create conn_rec */
status = ap_proxy_connection_create_ex(scheme, backend, r); if (status != OK) { goto cleanup;
}
/* Step Four: Process the Request */
status = proxy_wstunnel_request(p, r, backend, worker, conf, uri, locurl,
server_portstr);
cleanup: /* Do not close the socket */ if (backend) {
backend->close = 1;
ap_proxy_release_connection(scheme, backend, r->server);
} return status;
}
staticconst command_rec ws_proxy_cmds[] =
{
AP_INIT_FLAG("ProxyWebsocketFallbackToProxyHttp",
proxyws_fallback_to_proxy_http, NULL, RSRC_CONF|ACCESS_CONF, "whether to let mod_proxy_http handle the upgrade and tunneling, " "On by default"),
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.