in runtime/runtime_impl_jetty12/src/main/java/com/google/apphosting/runtime/jetty/http/JettyRequestAPIData.java [115:322]
public JettyRequestAPIData(
Request request, AppInfoFactory appInfoFactory, boolean passThroughPrivateHeaders) {
this.appInfoFactory = appInfoFactory;
// Can be overridden by X_APPENGINE_USER_IP header.
String userIp = Request.getRemoteAddr(request);
// Can be overridden by X_APPENGINE_API_TICKET header.
this.securityTicket = DEFAULT_SECRET_KEY;
HttpFields.Mutable fields = HttpFields.build();
for (HttpField field : request.getHeaders()) {
// If it has a HttpHeader it is one of the standard headers so won't match any appengine
// specific header.
if (field.getHeader() != null) {
fields.add(field);
continue;
}
String name = field.getLowerCaseName();
String value = field.getValue();
if (Strings.isNullOrEmpty(value)) {
continue;
}
switch (name) {
case X_APPENGINE_TRUSTED_IP_REQUEST:
// If there is a value, then the application is trusted
// If the value is IS_TRUSTED, then the user is trusted
isTrusted = value.equals(IS_TRUSTED);
isTrustedApp = true;
break;
case X_APPENGINE_HTTPS:
isHttps = value.equals("on");
break;
case X_APPENGINE_USER_IP:
userIp = value;
break;
case X_FORWARDED_PROTO:
isHttps = value.equals("https");
break;
case X_APPENGINE_USER_ID:
obfuscatedGaiaId = value;
break;
case X_APPENGINE_USER_ORGANIZATION:
userOrganization = value;
break;
case X_APPENGINE_LOAS_PEER_USERNAME:
peerUsername = value;
break;
case X_APPENGINE_GAIA_ID:
gaiaId = field.getLongValue();
break;
case X_APPENGINE_GAIA_AUTHUSER:
authUser = value;
break;
case X_APPENGINE_GAIA_SESSION:
gaiaSession = value;
break;
case X_APPENGINE_APPSERVER_DATACENTER:
appserverDataCenter = value;
break;
case X_APPENGINE_APPSERVER_TASK_BNS:
appserverTaskBns = value;
break;
case X_APPENGINE_ID_HASH:
eventIdHash = value;
break;
case X_APPENGINE_REQUEST_LOG_ID:
requestLogId = value;
break;
case X_APPENGINE_DEFAULT_VERSION_HOSTNAME:
defaultVersionHostname = value;
break;
case X_APPENGINE_USER_IS_ADMIN:
isAdmin = Objects.equals(value, IS_ADMIN_HEADER_VALUE);
break;
case X_APPENGINE_USER_EMAIL:
email = value;
break;
case X_APPENGINE_AUTH_DOMAIN:
authDomain = value;
break;
case X_APPENGINE_API_TICKET:
securityTicket = value;
break;
case X_CLOUD_TRACE_CONTEXT:
try {
traceContext = TraceContextHelper.parseTraceContextHeader(value);
} catch (NumberFormatException e) {
logger.atWarning().withCause(e).log("Could not parse trace context header: %s", value);
}
break;
case X_GOOGLE_INTERNAL_SKIPADMINCHECK:
request.setAttribute(SKIP_ADMIN_CHECK_ATTR, true);
isHttps = true;
break;
case X_APPENGINE_QUEUENAME:
request.setAttribute(SKIP_ADMIN_CHECK_ATTR, true);
isOffline = true;
break;
case X_APPENGINE_TIMEOUT_MS:
duration = Duration.ofMillis(Long.parseLong(value));
break;
case X_GOOGLE_INTERNAL_PROFILER:
/* TODO: what to do here?
try {
TextFormat.merge(value, upReqBuilder.getProfilerSettingsBuilder());
} catch (IOException ex) {
throw new IllegalStateException("X-Google-Internal-Profiler read content error:", ex);
}
*/
break;
case X_APPENGINE_BACKGROUNDREQUEST:
backgroundRequestId = value;
break;
default:
break;
}
if (passThroughPrivateHeaders || !PRIVATE_APPENGINE_HEADERS.contains(name)) {
// Only non AppEngine specific headers are passed to the application.
fields.add(field);
}
}
HttpURI httpURI;
boolean isSecure;
if (isHttps) {
httpURI = HttpURI.build(request.getHttpURI()).scheme(HttpScheme.HTTPS);
isSecure = true;
} else {
httpURI = request.getHttpURI();
isSecure = request.isSecure();
}
String decodedPath = request.getHttpURI().getDecodedPath();
if (BACKGROUND_REQUEST_URL.equals(decodedPath)) {
if (WARMUP_IP.equals(userIp)) {
requestType = RuntimePb.UPRequest.RequestType.BACKGROUND;
}
} else if (WARMUP_REQUEST_URL.equals(decodedPath)) {
if (WARMUP_IP.equals(userIp)) {
// This request came from within App Engine via secure internal channels; tell Jetty
// it's HTTPS to avoid 403 because of web.xml security-constraint checks.
isHttps = true;
}
}
StringBuilder sb = new StringBuilder(HttpURI.build(httpURI).query(null).asString());
String query = httpURI.getQuery();
// No need to escape, URL retains any %-escaping it might have, which is what we want.
if (query != null) {
sb.append('?').append(query);
}
url = sb.toString();
if (traceContext == null)
traceContext =
com.google.apphosting.base.protos.TracePb.TraceContextProto.getDefaultInstance();
String finalUserIp = userIp;
this.originalRequest = request;
this.request =
new Request.Wrapper(request) {
@Override
public HttpURI getHttpURI() {
return httpURI;
}
@Override
public boolean isSecure() {
return isSecure;
}
@Override
public HttpFields getHeaders() {
return fields;
}
@Override
public ConnectionMetaData getConnectionMetaData() {
return new ConnectionMetaData.Wrapper(super.getConnectionMetaData()) {
@Override
public SocketAddress getRemoteSocketAddress() {
return InetSocketAddress.createUnresolved(finalUserIp, 0);
}
@Override
public HostPort getServerAuthority() {
return new HostPort(UNSPECIFIED_IP, 0);
}
@Override
public SocketAddress getLocalSocketAddress() {
return InetSocketAddress.createUnresolved(UNSPECIFIED_IP, 0);
}
};
}
};
}