All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.google.appengine.tools.development.DevAppServerModulesCommon Maven / Gradle / Ivy

Go to download

SDK for dev_appserver (local development) with some of the dependencies shaded (repackaged)

There is a newer version: 2.0.31
Show newest version
/*
 * Copyright 2021 Google LLC
 *
 * Licensed 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
 *
 *     https://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.
 */

package com.google.appengine.tools.development;

import com.google.appengine.api.backends.BackendService;
import com.google.appengine.api.backends.dev.LocalServerController;
import com.google.appengine.api.modules.ModulesException;
import com.google.appengine.api.modules.ModulesService;
import com.google.appengine.api.modules.ModulesServiceFactory;
import com.google.apphosting.api.ApiProxy;
import com.google.appengine.repackaged.com.google.common.annotations.VisibleForTesting;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 * This filter intercepts all request sent to all module instances.
 *
 * 

There are 6 different request types that this filter will see: * *

* DIRECT_BACKEND_REQUEST: a client request sent to a serving (non load balancing) backend * instance. * *

* REDIRECT_REQUESTED: a request requesting a redirect in one of three ways 1) The request * contains a BackendService.REQUEST_HEADER_BACKEND_REDIRECT header or parameter 2) The request is * sent to a load balancing module instance. 3) The request is sent to a load balancing backend * instance. * *

If the request specifies an instance with the BackendService.REQUEST_HEADER_INSTANCE_REDIRECT * request header or parameter the filter verifies that the instance is available, obtains a serving * permit and forwards the requests. If the instance is not available the filter responds with a 500 * error. * *

If the request does not specify an instance the filter picks one, obtains a serving permit, * and forwards the request. If no instance is available this filter responds with a 500 error. * *

* DIRECT_MODULE_REQUEST: a request sent directly to the listening port of a specific serving * module instance. The filter verifies that the instance is available, obtains a serving permit and * sends the request to the handler. If no instance is available this filter responds with a 500 * error. * *

* REDIRECTED_BACKEND_REQUEST: a request redirected to a backend instance. The filter sends the * request to the handler. The serving permit has already been obtained by this filter when * performing the redirect. * *

* REDIRECTED_MODULE_REQUEST: a request redirected to a specific module instance. The filter * sends the request to the handler. The serving permit has already been obtained when by filter * performing the redirect. * *

* STARTUP_REQUEST: Internally generated startup request. The filter passes the request to the * handler without obtaining a serving permit. */ public class DevAppServerModulesCommon { protected static final String BACKEND_REDIRECT_ATTRIBUTE = "com.google.appengine.backend.BackendName"; protected static final String BACKEND_INSTANCE_REDIRECT_ATTRIBUTE = "com.google.appengine.backend.BackendInstance"; @VisibleForTesting protected static final String MODULE_INSTANCE_REDIRECT_ATTRIBUTE = "com.google.appengine.module.ModuleInstance"; protected final BackendServersBase backendServersManager; protected final ModulesService modulesService; protected final Logger logger = Logger.getLogger(DevAppServerModulesFilter.class.getName()); @VisibleForTesting protected DevAppServerModulesCommon( BackendServersBase backendServers, ModulesService modulesService) { this.backendServersManager = backendServers; this.modulesService = modulesService; } public DevAppServerModulesCommon() { this(BackendServersBase.getInstance(), ModulesServiceFactory.getModulesService()); } protected boolean isLoadBalancingRequest() { ModulesFilterHelper modulesFilterHelper = getModulesFilterHelper(); String module = modulesService.getCurrentModule(); int instance = getCurrentModuleInstance(); return modulesFilterHelper.isLoadBalancingInstance(module, instance); } protected boolean expectsGeneratedStartRequests(String backendName, int requestPort) { String moduleOrBackendName = backendName; if (moduleOrBackendName == null) { moduleOrBackendName = modulesService.getCurrentModule(); } int instance = backendName == null ? getCurrentModuleInstance() : backendServersManager.getServerInstanceFromPort(requestPort); ModulesFilterHelper modulesFilterHelper = getModulesFilterHelper(); return modulesFilterHelper.expectsGeneratedStartRequests(moduleOrBackendName, instance); } /** * Returns the instance id for the module instance handling the current request or -1 if a back * end server or load balancing server is handling the request. */ protected int getCurrentModuleInstance() { String instance = "-1"; try { instance = modulesService.getCurrentInstanceId(); } catch (ModulesException me) { logger.log(Level.FINEST, "Ignoring Exception getting module instance and continuing", me); } return Integer.parseInt(instance); } protected ModulesFilterHelper getModulesFilterHelper() { Map attributes = ApiProxy.getCurrentEnvironment().getAttributes(); return (ModulesFilterHelper) attributes.get(DevAppServerImpl.MODULES_FILTER_HELPER_PROPERTY); } /** * Inject information about the current backend server setup so it is available to the * BackendService API. This information is stored in the threadLocalAttributes in the current * environment. * * @param backendName The server that is handling the request * @param instance The server instance that is handling the request */ protected void injectApiInfo(String backendName, int instance) { Map portMapping = backendServersManager.getPortMapping(); if (portMapping == null) { throw new IllegalStateException("backendServersManager.getPortMapping() is null"); } injectBackendServiceCurrentApiInfo(backendName, instance, portMapping); Map threadLocalAttributes = ApiProxy.getCurrentEnvironment().getAttributes(); // We inject backendServersManager which is not injected by // injectBackendServiceCurrentApiInfo as it is not needed by BackendsService // but is needed by the admin console for handling HTTP requests. if (!portMapping.isEmpty()) { threadLocalAttributes.put( LocalServerController.BACKEND_CONTROLLER_ATTRIBUTE_KEY, backendServersManager); } threadLocalAttributes.put( ModulesController.MODULES_CONTROLLER_ATTRIBUTE_KEY, Modules.getInstance()); } /** Sets up {@link ApiProxy} attributes needed {@link BackendService}. */ public static void injectBackendServiceCurrentApiInfo( String backendName, int backendInstance, Map portMapping) { Map threadLocalAttributes = ApiProxy.getCurrentEnvironment().getAttributes(); if (backendInstance != -1) { threadLocalAttributes.put(BackendService.INSTANCE_ID_ENV_ATTRIBUTE, backendInstance + ""); } if (backendName != null) { threadLocalAttributes.put(BackendService.BACKEND_ID_ENV_ATTRIBUTE, backendName); } threadLocalAttributes.put(BackendService.DEVAPPSERVER_PORTMAPPING_KEY, portMapping); } @VisibleForTesting public static enum RequestType { DIRECT_MODULE_REQUEST, REDIRECT_REQUESTED, DIRECT_BACKEND_REQUEST, REDIRECTED_BACKEND_REQUEST, REDIRECTED_MODULE_REQUEST, STARTUP_REQUEST; } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy