in runtime/runtime_impl_jetty9/src/main/java/com/google/apphosting/runtime/jetty9/JettyRequestAPIData.java [117:369]
public JettyRequestAPIData(
Request request,
HttpServletRequest httpServletRequest,
AppInfoFactory appInfoFactory,
boolean passThroughPrivateHeaders) {
this.appInfoFactory = appInfoFactory;
// Can be overridden by X_APPENGINE_USER_IP header.
String userIp = request.getRemoteAddr();
// Can be overridden by X_APPENGINE_API_TICKET header.
this.securityTicket = DEFAULT_SECRET_KEY;
HttpFields fields = new HttpFields();
for (HttpField field : request.getHttpFields()) {
// 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.getName().toLowerCase(Locale.ROOT);
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 = Long.parseLong(value);
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 = new HttpURI(request.getHttpURI());
httpUri.setScheme(HttpScheme.HTTPS.asString());
isSecure = true;
} else {
httpUri = request.getHttpURI();
isSecure = request.isSecure();
}
String decodedPath = request.getHttpURI().getDecodedPath();
if (Objects.equals(decodedPath, BACKGROUND_REQUEST_URL)) {
if (Objects.equals(userIp, WARMUP_IP)) {
requestType = RuntimePb.UPRequest.RequestType.BACKGROUND;
}
} else if (Objects.equals(decodedPath, WARMUP_REQUEST_URL)) {
if (Objects.equals(userIp, WARMUP_IP)) {
// 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;
}
}
HttpURI uri = new HttpURI(httpUri);
uri.setQuery(null);
StringBuilder sb = new StringBuilder(uri.toString());
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 = TraceContextProto.getDefaultInstance();
}
String finalUserIp = NORMALIZE_INET_ADDR ? HostPort.normalizeHost(userIp) : userIp;
this.httpServletRequest =
new HttpServletRequestWrapper(httpServletRequest) {
@Override
public long getDateHeader(String name) {
return fields.getDateField(name);
}
@Override
public String getHeader(String name) {
return fields.get(name);
}
@Override
public Enumeration<String> getHeaders(String name) {
return fields.getValues(name);
}
@Override
public Enumeration<String> getHeaderNames() {
return fields.getFieldNames();
}
@Override
public int getIntHeader(String name) {
return Math.toIntExact(fields.getLongField(name));
}
@Override
public String getRequestURI() {
return httpUri.getPath();
}
@Override
public String getScheme() {
return httpUri.getScheme();
}
@Override
public boolean isSecure() {
return isSecure;
}
@Override
public String getRemoteAddr() {
return finalUserIp;
}
@Override
public String getRemoteHost() {
return finalUserIp;
}
@Override
public int getRemotePort() {
return 0;
}
@Override
public String getLocalName() {
return UNSPECIFIED_IP;
}
@Override
public String getLocalAddr() {
return UNSPECIFIED_IP;
}
@Override
public int getLocalPort() {
return 0;
}
};
this.baseRequest = request;
this.baseRequest.setSecure(isSecure);
this.baseRequest.setHttpURI(httpUri);
}