def test_path_given_does_not_exist(self): path = tempfile.mkdtemp() os.rmdir(path) self.assertEqual( path, api_server.get_storage_path(path, 'dev~example.com:myapp')) self.assertTrue(os.path.isdir(path))
def test_no_path_given_directory_does_not_exist(self): path = tempfile.mkdtemp() os.rmdir(path) api_server._generate_storage_paths('example.com_myapp').AndReturn([path]) self.mox.ReplayAll() self.assertEqual( path, api_server.get_storage_path(None, 'dev~example.com:myapp')) self.mox.VerifyAll() self.assertTrue(os.path.isdir(path))
def test_no_path_given_directory_does_not_exist(self): path = tempfile.mkdtemp() os.rmdir(path) api_server._generate_storage_paths('example.com_myapp').AndReturn( [path]) self.mox.ReplayAll() self.assertEqual( path, api_server.get_storage_path(None, 'dev~example.com:myapp')) self.mox.VerifyAll() self.assertTrue(os.path.isdir(path))
def test_no_path_given_directory_exists(self): path1 = tempfile.mkdtemp() os.chmod(path1, 0777) path2 = tempfile.mkdtemp() # Made with mode 0700. api_server._generate_storage_paths('example.com_myapp').AndReturn( [path1, path2]) self.mox.ReplayAll() if sys.platform == 'win32': expected_path = path1 else: expected_path = path2 self.assertEqual( expected_path, api_server.get_storage_path(None, 'dev~example.com:myapp')) self.mox.VerifyAll()
def setup_local(): from google.appengine.tools.devappserver2.devappserver2 import PARSER options = PARSER.parse_args([APP_YAML_LOCAL_FILE, ]) from google.appengine.tools.devappserver2.devappserver2 import application_configuration configuration = application_configuration.ApplicationConfiguration(options.config_paths, options.app_id) # set the app ID to make stubs happy, esp. datastore os.environ['APPLICATION_ID'] = configuration.app_id os.environ['AUTH_DOMAIN'] = 'localhost' os.environ['SERVER_NAME'] = 'localhost' os.environ['SERVER_PORT'] = '8080' try: from google.appengine.tools.devappserver2.api_server import get_storage_path except ImportError: from google.appengine.tools.devappserver2.devappserver2 import _get_storage_path as get_storage_path storage_path = get_storage_path(options.storage_path, configuration.app_id) setup_stubs(storage_path, options, configuration)
def test_path_given_exists(self): path = tempfile.mkdtemp() self.assertEqual( path, api_server.get_storage_path(path, 'dev~example.com:myapp'))
def start(self, options): """Start devappserver2 servers based on the provided command line arguments. Args: options: An argparse.Namespace containing the command line arguments. """ logging.getLogger().setLevel(constants.LOG_LEVEL_TO_PYTHON_CONSTANT[ options.dev_appserver_log_level]) configuration = application_configuration.ApplicationConfiguration( options.config_paths, options.app_id) if options.skip_sdk_update_check: logging.info('Skipping SDK update check.') else: update_checker.check_for_updates(configuration) if options.port == 0: logging.warn( 'DEFAULT_VERSION_HOSTNAME will not be set correctly with ' '--port=0') _setup_environ(configuration.app_id, configuration.modules[0].version_id) python_config = runtime_config_pb2.PythonConfig() if options.python_startup_script: python_config.startup_script = os.path.abspath( options.python_startup_script) if options.python_startup_args: python_config.startup_args = options.python_startup_args php_executable_path = (options.php_executable_path and os.path.abspath( options.php_executable_path)) cloud_sql_config = runtime_config_pb2.CloudSQL() cloud_sql_config.mysql_host = options.mysql_host cloud_sql_config.mysql_port = options.mysql_port cloud_sql_config.mysql_user = options.mysql_user cloud_sql_config.mysql_password = options.mysql_password if options.mysql_socket: cloud_sql_config.mysql_socket = options.mysql_socket if options.max_module_instances is None: module_to_max_instances = {} elif isinstance(options.max_module_instances, int): module_to_max_instances = { module_configuration.module_name: options.max_module_instances for module_configuration in configuration.modules } else: module_to_max_instances = options.max_module_instances if options.threadsafe_override is None: module_to_threadsafe_override = {} elif isinstance(options.threadsafe_override, bool): module_to_threadsafe_override = { module_configuration.module_name: options.threadsafe_override for module_configuration in configuration.modules } else: module_to_threadsafe_override = options.threadsafe_override self._dispatcher = dispatcher.Dispatcher( configuration, options.host, options.port, options.auth_domain, constants.LOG_LEVEL_TO_RUNTIME_CONSTANT[options.log_level], php_executable_path, options.php_remote_debugging, python_config, cloud_sql_config, module_to_max_instances, options.use_mtime_file_watcher, options.automatic_restart, options.allow_skipped_files, module_to_threadsafe_override, options.external_api_port) request_data = wsgi_request_info.WSGIRequestInfo(self._dispatcher) storage_path = api_server.get_storage_path(options.storage_path, configuration.app_id) apis = api_server.create_api_server( request_data, storage_path, options, configuration.app_id, configuration.modules[0].application_root) apis.start() self._running_modules.append(apis) self._dispatcher.start(apis.port, request_data) self._running_modules.append(self._dispatcher) xsrf_path = os.path.join(storage_path, 'xsrf') admin = admin_server.AdminServer(options.admin_host, options.admin_port, self._dispatcher, configuration, xsrf_path) admin.start() self._running_modules.append(admin)
def start(self, options): """Start devappserver2 servers based on the provided command line arguments. Args: options: An argparse.Namespace containing the command line arguments. """ self._options = options logging.getLogger().setLevel(constants.LOG_LEVEL_TO_PYTHON_CONSTANT[ options.dev_appserver_log_level]) parsed_env_variables = dict(options.env_variables or []) configuration = application_configuration.ApplicationConfiguration( config_paths=options.config_paths, app_id=options.app_id, runtime=options.runtime, env_variables=parsed_env_variables) if options.google_analytics_client_id: metrics_logger = metrics.GetMetricsLogger() metrics_logger.Start( options.google_analytics_client_id, options.google_analytics_user_agent, {module.runtime for module in configuration.modules}, {module.env or 'standard' for module in configuration.modules}) if options.skip_sdk_update_check: logging.info('Skipping SDK update check.') else: update_checker.check_for_updates(configuration) # There is no good way to set the default encoding from application code # (it needs to be done during interpreter initialization in site.py or # sitecustomize.py) so just warn developers if they have a different # encoding than production. if sys.getdefaultencoding() != constants.PROD_DEFAULT_ENCODING: logging.warning( 'The default encoding of your local Python interpreter is set to %r ' 'while App Engine\'s production environment uses %r; as a result ' 'your code may behave differently when deployed.', sys.getdefaultencoding(), constants.PROD_DEFAULT_ENCODING) if options.port == 0: logging.warn( 'DEFAULT_VERSION_HOSTNAME will not be set correctly with ' '--port=0') _setup_environ(configuration.app_id) # grpc_proxy is only needed for python2 because remote_api_stub.py is # imported in local python runtime sandbox. For more details, see # grpc_proxy_util.py. grpc_proxy_port = portpicker.PickUnusedPort() self._dispatcher = dispatcher.Dispatcher( configuration, options.host, options.port, options.auth_domain, constants.LOG_LEVEL_TO_RUNTIME_CONSTANT[options.log_level], self._create_php_config(options), self._create_python_config(options, grpc_proxy_port), self._create_java_config(options), self._create_go_config(options), self._create_custom_config(options), self._create_cloud_sql_config(options), self._create_vm_config(options), self._create_module_to_setting(options.max_module_instances, configuration, '--max_module_instances'), options.use_mtime_file_watcher, options.watcher_ignore_re, options.automatic_restart, options.allow_skipped_files, self._create_module_to_setting(options.threadsafe_override, configuration, '--threadsafe_override'), options.external_port) wsgi_request_info_ = wsgi_request_info.WSGIRequestInfo( self._dispatcher) storage_path = api_server.get_storage_path(options.storage_path, configuration.app_id) datastore_emulator_host = ( parsed_env_variables['DATASTORE_EMULATOR_HOST'] if 'DATASTORE_EMULATOR_HOST' in parsed_env_variables else None) apiserver = api_server.create_api_server( wsgi_request_info_, storage_path, options, configuration.app_id, configuration.modules[0].application_root, datastore_emulator_host) apiserver.start() self._running_modules.append(apiserver) if options.grpc_apis: grpc_apiserver = api_server.GRPCAPIServer(options.grpc_api_port) grpc_apiserver.start() self._running_modules.append(grpc_apiserver) # We declare grpc_proxy_util as global, otherwise it cannot be accessed # from outside of this function. global grpc_proxy_util # pylint: disable=g-import-not-at-top # We lazy import here because grpc binaries are not always present. from google.appengine.tools.devappserver2 import grpc_proxy_util grpc_proxy = grpc_proxy_util.GrpcProxyServer(grpc_proxy_port) grpc_proxy.start() self._running_modules.append(grpc_proxy) self._dispatcher.start(options.api_host, apiserver.port, wsgi_request_info_, options.grpc_apis) xsrf_path = os.path.join(storage_path, 'xsrf') admin = admin_server.AdminServer(options.admin_host, options.admin_port, self._dispatcher, configuration, xsrf_path) admin.start() self._running_modules.append(admin) try: default = self._dispatcher.get_module_by_name('default') apiserver.set_balanced_address(default.balanced_address) except request_info.ModuleDoesNotExistError: logging.warning('No default module found. Ignoring.')
def start(self, options): """Start devappserver2 servers based on the provided command line arguments. Args: options: An argparse.Namespace containing the command line arguments. """ self._options = options logging.getLogger().setLevel( constants.LOG_LEVEL_TO_PYTHON_CONSTANT[options.dev_appserver_log_level]) parsed_env_variables = dict(options.env_variables or []) configuration = application_configuration.ApplicationConfiguration( config_paths=options.config_paths, app_id=options.app_id, runtime=options.runtime, env_variables=parsed_env_variables) if options.google_analytics_client_id: metrics_logger = metrics.GetMetricsLogger() metrics_logger.Start( options.google_analytics_client_id, options.google_analytics_user_agent, {module.runtime for module in configuration.modules}, {module.env or 'standard' for module in configuration.modules}) if options.skip_sdk_update_check: logging.info('Skipping SDK update check.') else: update_checker.check_for_updates(configuration) # There is no good way to set the default encoding from application code # (it needs to be done during interpreter initialization in site.py or # sitecustomize.py) so just warn developers if they have a different # encoding than production. if sys.getdefaultencoding() != constants.PROD_DEFAULT_ENCODING: logging.warning( 'The default encoding of your local Python interpreter is set to %r ' 'while App Engine\'s production environment uses %r; as a result ' 'your code may behave differently when deployed.', sys.getdefaultencoding(), constants.PROD_DEFAULT_ENCODING) if options.port == 0: logging.warn('DEFAULT_VERSION_HOSTNAME will not be set correctly with ' '--port=0') _setup_environ(configuration.app_id) # grpc_proxy is only needed for python2 because remote_api_stub.py is # imported in local python runtime sandbox. For more details, see # grpc_proxy_util.py. grpc_proxy_port = portpicker.PickUnusedPort() self._dispatcher = dispatcher.Dispatcher( configuration, options.host, options.port, options.auth_domain, constants.LOG_LEVEL_TO_RUNTIME_CONSTANT[options.log_level], self._create_php_config(options), self._create_python_config(options, grpc_proxy_port), self._create_java_config(options), self._create_go_config(options), self._create_custom_config(options), self._create_cloud_sql_config(options), self._create_vm_config(options), self._create_module_to_setting(options.max_module_instances, configuration, '--max_module_instances'), options.use_mtime_file_watcher, options.watcher_ignore_re, options.automatic_restart, options.allow_skipped_files, self._create_module_to_setting( options.threadsafe_override, configuration, '--threadsafe_override'), options.external_port) wsgi_request_info_ = wsgi_request_info.WSGIRequestInfo(self._dispatcher) storage_path = api_server.get_storage_path( options.storage_path, configuration.app_id) datastore_emulator_host = ( parsed_env_variables['DATASTORE_EMULATOR_HOST'] if 'DATASTORE_EMULATOR_HOST' in parsed_env_variables else None) apiserver = api_server.create_api_server( wsgi_request_info_, storage_path, options, configuration.app_id, configuration.modules[0].application_root, datastore_emulator_host) apiserver.start() self._running_modules.append(apiserver) if options.grpc_apis: grpc_apiserver = api_server.GRPCAPIServer(options.grpc_api_port) grpc_apiserver.start() self._running_modules.append(grpc_apiserver) # We declare grpc_proxy_util as global, otherwise it cannot be accessed # from outside of this function. global grpc_proxy_util # pylint: disable=g-import-not-at-top # We lazy import here because grpc binaries are not always present. from google.appengine.tools.devappserver2 import grpc_proxy_util grpc_proxy = grpc_proxy_util.GrpcProxyServer(grpc_proxy_port) grpc_proxy.start() self._running_modules.append(grpc_proxy) self._dispatcher.start( options.api_host, apiserver.port, wsgi_request_info_, options.grpc_apis) xsrf_path = os.path.join(storage_path, 'xsrf') admin = admin_server.AdminServer(options.admin_host, options.admin_port, self._dispatcher, configuration, xsrf_path) admin.start() self._running_modules.append(admin) try: default = self._dispatcher.get_module_by_name('default') apiserver.set_balanced_address(default.balanced_address) except request_info.ModuleDoesNotExistError: logging.warning('No default module found. Ignoring.')
def _local(devappserver2=None, configuration=None, options=None, wsgi_request_info=None, **kwargs): # If we use `_LocalRequestInfo`, deferred tasks don't seem to work, # but with the default `WSGIRequestInfo`, building the request url for # blobstore uploads fails. So we inherit from `WSGIRequestInfo` and copy # the `get_request_url` from `_LocalRequestInfo` class CustomWSGIRequestInfo(wsgi_request_info.WSGIRequestInfo): def get_request_url(self, request_id): """Returns the URL the request e.g. 'http://localhost:8080/foo?bar=baz'. Args: request_id: The string id of the request making the API call. Returns: The URL of the request as a string. """ try: host = os.environ['HTTP_HOST'] except KeyError: host = os.environ['SERVER_NAME'] port = os.environ['SERVER_PORT'] if port != '80': host += ':' + port url = 'http://' + host url += quote(os.environ.get('PATH_INFO', '/')) if os.environ.get('QUERY_STRING'): url += '?' + os.environ['QUERY_STRING'] return url global _API_SERVER _disable_sqlite_stub_logging() original_environ = os.environ.copy() # Silence warnings about this being unset, localhost:8080 is the dev_appserver default. # Note that we're setting things for the *Blobstore* handler in os.environ here, which seems # kind of crazy, and probably is, but it seems to be necessary to make stuff work. url = "localhost" port = get_next_available_port(url, DEFAULT_BLOBSTORE_SERVICE_PORT) os.environ.setdefault("HTTP_HOST", "{}:{}".format(url, port)) os.environ['SERVER_NAME'] = url os.environ['SERVER_PORT'] = str(port) os.environ['DEFAULT_VERSION_HOSTNAME'] = '%s:%s' % (os.environ['SERVER_NAME'], os.environ['SERVER_PORT']) devappserver2._setup_environ(configuration.app_id) from google.appengine.tools.devappserver2 import api_server from google.appengine.tools.sdk_update_checker import GetVersionObject, _VersionList if hasattr(api_server, "get_storage_path"): storage_path = api_server.get_storage_path(options.storage_path, configuration.app_id) else: # SDK < 1.9.51 storage_path = devappserver2._get_storage_path(options.storage_path, configuration.app_id) dispatcher = _create_dispatcher(configuration, options) request_data = CustomWSGIRequestInfo(dispatcher) # Remember the wsgi request info object so it can be reused to avoid duplication. dispatcher._request_data = request_data # We set the API and Admin ports so that they are beyond any modules (if you # have 10 modules then these values will shift, but it's better that they are predictable # in the common case) options.api_port = get_next_available_port(url, max(DEFAULT_API_PORT, port + 1)) options.admin_port = get_next_available_port(url, max(DEFAULT_ADMIN_PORT, options.api_port + 1)) if hasattr(api_server, "create_api_server"): current_version = _VersionList(GetVersionObject()['release']) app_rather_than_config = current_version >= _VersionList('1.9.54') # Google changed the argument structure in version 1.9.54 so we have to # conditionally supply the args here if app_rather_than_config: _API_SERVER = api_server.create_api_server( request_data, storage_path, options, configuration.app_id, environment.get_application_root() ) else: _API_SERVER = api_server.create_api_server( request_data, storage_path, options, configuration ) # We have to patch api_server.create_api_server to return _API_SERVER # every time it's called, without this we end up with all kinds of # problems. Basically we need one api server for the lifetime of the # sandbox (including in `runserver`) def create_api_server_patch(*args, **kwargs): return _API_SERVER api_server.create_api_server = create_api_server_patch else: _API_SERVER = devappserver2.DevelopmentServer._create_api_server( request_data, storage_path, options, configuration ) from .blobstore_service import start_blobstore_service, stop_blobstore_service start_blobstore_service() try: yield finally: api_server.cleanup_stubs() os.environ = original_environ stop_blobstore_service()
def start(self, options): """Start devappserver2 servers based on the provided command line arguments. Args: options: An argparse.Namespace containing the command line arguments. """ logging.getLogger().setLevel( constants.LOG_LEVEL_TO_PYTHON_CONSTANT[options.dev_appserver_log_level]) configuration = application_configuration.ApplicationConfiguration( options.config_paths, options.app_id) if options.skip_sdk_update_check: logging.info('Skipping SDK update check.') else: update_checker.check_for_updates(configuration) if options.port == 0: logging.warn('DEFAULT_VERSION_HOSTNAME will not be set correctly with ' '--port=0') _setup_environ(configuration.app_id, configuration.modules[0].version_id) python_config = runtime_config_pb2.PythonConfig() if options.python_startup_script: python_config.startup_script = os.path.abspath( options.python_startup_script) if options.python_startup_args: python_config.startup_args = options.python_startup_args php_executable_path = (options.php_executable_path and os.path.abspath(options.php_executable_path)) cloud_sql_config = runtime_config_pb2.CloudSQL() cloud_sql_config.mysql_host = options.mysql_host cloud_sql_config.mysql_port = options.mysql_port cloud_sql_config.mysql_user = options.mysql_user cloud_sql_config.mysql_password = options.mysql_password if options.mysql_socket: cloud_sql_config.mysql_socket = options.mysql_socket if options.max_module_instances is None: module_to_max_instances = {} elif isinstance(options.max_module_instances, int): module_to_max_instances = { module_configuration.module_name: options.max_module_instances for module_configuration in configuration.modules} else: module_to_max_instances = options.max_module_instances if options.threadsafe_override is None: module_to_threadsafe_override = {} elif isinstance(options.threadsafe_override, bool): module_to_threadsafe_override = { module_configuration.module_name: options.threadsafe_override for module_configuration in configuration.modules} else: module_to_threadsafe_override = options.threadsafe_override self._dispatcher = dispatcher.Dispatcher( configuration, options.host, options.port, options.auth_domain, constants.LOG_LEVEL_TO_RUNTIME_CONSTANT[options.log_level], php_executable_path, options.php_remote_debugging, python_config, cloud_sql_config, module_to_max_instances, options.use_mtime_file_watcher, options.automatic_restart, options.allow_skipped_files, module_to_threadsafe_override) request_data = wsgi_request_info.WSGIRequestInfo(self._dispatcher) storage_path = api_server.get_storage_path( options.storage_path, configuration.app_id) apis = api_server.create_api_server( request_data, storage_path, options, configuration.app_id, configuration.modules[0].application_root) apis.start() self._running_modules.append(apis) self._dispatcher.start(apis.port, request_data) self._running_modules.append(self._dispatcher)
def start(self, options): """Start devappserver2 servers based on the provided command line arguments. Args: options: An argparse.Namespace containing the command line arguments. Raises: PhpPathError: php executable path is not specified for php72. MissingDatastoreEmulatorError: dev_appserver.py is not invoked from the right directory. """ self._options = options self._correct_datastore_emulator_cmd() self._fail_for_using_datastore_emulator_from_legacy_sdk() self._decide_use_datastore_emulator() logging.getLogger().setLevel( constants.LOG_LEVEL_TO_PYTHON_CONSTANT[options.dev_appserver_log_level]) parsed_env_variables = dict(options.env_variables or []) if options.dev_appserver_log_setup_script: try: execfile(options.dev_appserver_log_setup_script, {}, {}) except Exception as e: logging.exception("Error executing log setup script at %r.", options.dev_appserver_log_setup_script) configuration = application_configuration.ApplicationConfiguration( config_paths=options.config_paths, app_id=options.app_id, runtime=options.runtime, env_variables=parsed_env_variables) all_module_runtimes = {module.runtime for module in configuration.modules} self._check_platform_support(all_module_runtimes) storage_path = api_server.get_storage_path( options.storage_path, configuration.app_id) datastore_path = api_server.get_datastore_path( storage_path, options.datastore_path) datastore_data_type = (datastore_converter.get_stub_type(datastore_path) if os.path.isfile(datastore_path) else None) if options.skip_sdk_update_check: logging.info('Skipping SDK update check.') else: update_checker.check_for_updates(configuration) # There is no good way to set the default encoding from application code # (it needs to be done during interpreter initialization in site.py or # sitecustomize.py) so just warn developers if they have a different # encoding than production. if sys.getdefaultencoding() != constants.PROD_DEFAULT_ENCODING: logging.warning( 'The default encoding of your local Python interpreter is set to %r ' 'while App Engine\'s production environment uses %r; as a result ' 'your code may behave differently when deployed.', sys.getdefaultencoding(), constants.PROD_DEFAULT_ENCODING) if options.port == 0: logging.warn('DEFAULT_VERSION_HOSTNAME will not be set correctly with ' '--port=0') util.setup_environ(configuration.app_id) php_version = self._get_php_runtime(configuration) if not options.php_executable_path and php_version == 'php72': raise PhpPathError('For php72, --php_executable_path must be specified.') if options.ssl_certificate_path and options.ssl_certificate_key_path: ssl_certificate_paths = self._create_ssl_certificate_paths_if_valid( options.ssl_certificate_path, options.ssl_certificate_key_path) else: if options.ssl_certificate_path or options.ssl_certificate_key_path: logging.warn('Must provide both --ssl_certificate_path and ' '--ssl_certificate_key_path to enable SSL. Since ' 'only one flag was provided, not using SSL.') ssl_certificate_paths = None if options.google_analytics_client_id: metrics_logger = metrics.GetMetricsLogger() metrics_logger.Start( options.google_analytics_client_id, options.google_analytics_user_agent, all_module_runtimes, {module.env or 'standard' for module in configuration.modules}, options.support_datastore_emulator, datastore_data_type, bool(ssl_certificate_paths), options, multi_module=len(configuration.modules) > 1, dispatch_config=configuration.dispatch is not None, grpc_import_report=self.grpc_import_report, java_major_version=self.java_major_version ) self._dispatcher = dispatcher.Dispatcher( configuration, options.host, options.port, options.auth_domain, constants.LOG_LEVEL_TO_RUNTIME_CONSTANT[options.log_level], self._create_php_config(options, php_version), self._create_python_config(options), self._create_java_config(options), self._create_go_config(options), self._create_custom_config(options), self._create_cloud_sql_config(options), self._create_vm_config(options), self._create_module_to_setting(options.max_module_instances, configuration, '--max_module_instances'), options.use_mtime_file_watcher, options.watcher_ignore_re, options.automatic_restart, options.allow_skipped_files, self._create_module_to_setting( options.threadsafe_override, configuration, '--threadsafe_override'), options.external_port, options.specified_service_ports, options.enable_host_checking, ssl_certificate_paths) wsgi_request_info_ = wsgi_request_info.WSGIRequestInfo(self._dispatcher) apiserver = api_server.create_api_server( wsgi_request_info_, storage_path, options, configuration.app_id, configuration.modules[0].application_root) apiserver.start() self._running_modules.append(apiserver) self._dispatcher.start( options.api_host, apiserver.port, wsgi_request_info_) xsrf_path = os.path.join(storage_path, 'xsrf') admin = admin_server.AdminServer(options.admin_host, options.admin_port, self._dispatcher, configuration, xsrf_path, options.enable_host_checking, options.enable_console) admin.start() self._running_modules.append(admin) if options.enable_datastore_translator: # We do a late import just in case of any problems with importing # protobuf (although in theory python/wrapper_util.py's path-munging has # handled them all). from google.appengine.tools.devappserver2.datastore_translator import ( datastore_translator_server) translator = datastore_translator_server.DatastoreTranslatorServer( options.datastore_translator_host, options.datastore_translator_port, options.enable_host_checking) translator.start() self._running_modules.append(translator) try: default = self._dispatcher.get_module_by_name('default') apiserver.set_balanced_address(default.balanced_address) except request_info.ModuleDoesNotExistError: logging.warning('No default module found. Ignoring.')
def start(self, options): """Start devappserver2 servers based on the provided command line arguments. Args: options: An argparse.Namespace containing the command line arguments. """ self._options = options logging.getLogger().setLevel(constants.LOG_LEVEL_TO_PYTHON_CONSTANT[ options.dev_appserver_log_level]) parsed_env_variables = dict(options.env_variables or []) configuration = application_configuration.ApplicationConfiguration( config_paths=options.config_paths, app_id=options.app_id, runtime=options.runtime, env_variables=parsed_env_variables) if options.google_analytics_client_id: metrics_logger = metrics.GetMetricsLogger() metrics_logger.Start( options.google_analytics_client_id, options.google_analytics_user_agent, {module.runtime for module in configuration.modules}, {module.env or 'standard' for module in configuration.modules}) if options.skip_sdk_update_check: logging.info('Skipping SDK update check.') else: update_checker.check_for_updates(configuration) # There is no good way to set the default encoding from application code # (it needs to be done during interpreter initialization in site.py or # sitecustomize.py) so just warn developers if they have a different # encoding than production. if sys.getdefaultencoding() != constants.PROD_DEFAULT_ENCODING: logging.warning( 'The default encoding of your local Python interpreter is set to %r ' 'while App Engine\'s production environment uses %r; as a result ' 'your code may behave differently when deployed.', sys.getdefaultencoding(), constants.PROD_DEFAULT_ENCODING) if options.port == 0: logging.warn( 'DEFAULT_VERSION_HOSTNAME will not be set correctly with ' '--port=0') _setup_environ(configuration.app_id) self._dispatcher = dispatcher.Dispatcher( configuration, options.host, options.port, options.auth_domain, constants.LOG_LEVEL_TO_RUNTIME_CONSTANT[options.log_level], self._create_php_config(options), self._create_python_config(options), self._create_java_config(options), self._create_go_config(options), self._create_custom_config(options), self._create_cloud_sql_config(options), self._create_vm_config(options), self._create_module_to_setting(options.max_module_instances, configuration, '--max_module_instances'), options.use_mtime_file_watcher, options.watcher_ignore_re, options.automatic_restart, options.allow_skipped_files, self._create_module_to_setting(options.threadsafe_override, configuration, '--threadsafe_override'), options.external_port) wsgi_request_info_ = wsgi_request_info.WSGIRequestInfo( self._dispatcher) storage_path = api_server.get_storage_path(options.storage_path, configuration.app_id) apiserver = api_server.create_api_server( wsgi_request_info_, storage_path, options, configuration.app_id, configuration.modules[0].application_root) apiserver.start() self._running_modules.append(apiserver) self._dispatcher.start(options.api_host, apiserver.port, wsgi_request_info_) xsrf_path = os.path.join(storage_path, 'xsrf') admin = admin_server.AdminServer(options.admin_host, options.admin_port, self._dispatcher, configuration, xsrf_path) admin.start() self._running_modules.append(admin) try: default = self._dispatcher.get_module_by_name('default') apiserver.set_balanced_address(default.balanced_address) except request_info.ModuleDoesNotExistError: logging.warning('No default module found. Ignoring.')
def _local(devappserver2=None, configuration=None, options=None, wsgi_request_info=None, **kwargs): # If we use `_LocalRequestInfo`, deferred tasks don't seem to work, # but with the default `WSGIRequestInfo`, building the request url for # blobstore uploads fails. So we inherit from `WSGIRequestInfo` and copy # the `get_request_url` from `_LocalRequestInfo` class CustomWSGIRequestInfo(wsgi_request_info.WSGIRequestInfo): def get_request_url(self, request_id): """Returns the URL the request e.g. 'http://localhost:8080/foo?bar=baz'. Args: request_id: The string id of the request making the API call. Returns: The URL of the request as a string. """ try: host = os.environ['HTTP_HOST'] except KeyError: host = os.environ['SERVER_NAME'] port = os.environ['SERVER_PORT'] if port != '80': host += ':' + port url = 'http://' + host url += urllib.quote(os.environ.get('PATH_INFO', '/')) if os.environ.get('QUERY_STRING'): url += '?' + os.environ['QUERY_STRING'] return url global _API_SERVER _disable_sqlite_stub_logging() original_environ = os.environ.copy() # Silence warnings about this being unset, localhost:8080 is the dev_appserver default. # Note that we're setting things for the *Blobstore* handler in os.environ here, which seems # kind of crazy, and probably is, but it seems to be necessary to make stuff work. url = "localhost" port = get_next_available_port(url, DEFAULT_BLOBSTORE_SERVICE_PORT) os.environ.setdefault("HTTP_HOST", "{}:{}".format(url, port)) os.environ['SERVER_NAME'] = url os.environ['SERVER_PORT'] = str(port) os.environ['DEFAULT_VERSION_HOSTNAME'] = '%s:%s' % (os.environ['SERVER_NAME'], os.environ['SERVER_PORT']) devappserver2._setup_environ(configuration.app_id) from google.appengine.tools.devappserver2 import api_server if hasattr(api_server, "get_storage_path"): storage_path = api_server.get_storage_path(options.storage_path, configuration.app_id) else: # SDK < 1.9.51 storage_path = devappserver2._get_storage_path(options.storage_path, configuration.app_id) dispatcher = _create_dispatcher(configuration, options) request_data = CustomWSGIRequestInfo(dispatcher) # Remember the wsgi request info object so it can be reused to avoid duplication. dispatcher._request_data = request_data # We set the API and Admin ports so that they are beyond any modules (if you # have 10 modules then these values will shift, but it's better that they are predictable # in the common case) options.api_port = get_next_available_port(url, DEFAULT_API_PORT) options.admin_port = get_next_available_port(url, DEFAULT_ADMIN_PORT) if hasattr(api_server, "create_api_server"): _API_SERVER = api_server.create_api_server( request_data, storage_path, options, configuration ) # We have to patch api_server.create_api_server to return _API_SERVER # every time it's called, without this we end up with all kinds of # problems. Basically we need one api server for the lifetime of the # sandbox (including in `runserver`) def create_api_server_patch(*args, **kwargs): return _API_SERVER api_server.create_api_server = create_api_server_patch else: _API_SERVER = devappserver2.DevelopmentServer._create_api_server( request_data, storage_path, options, configuration ) from .blobstore_service import start_blobstore_service, stop_blobstore_service start_blobstore_service() try: yield finally: api_server.cleanup_stubs() os.environ = original_environ stop_blobstore_service()
def start(self, options): """Start devappserver2 servers based on the provided command line arguments. Args: options: An argparse.Namespace containing the command line arguments. Raises: PhpPathError: php executable path is not specified for php72. MissingDatastoreEmulatorError: dev_appserver.py is not invoked from the right directory. """ self._options = options self._options.datastore_emulator_cmd = self._correct_datastore_emulator_cmd( self._options.datastore_emulator_cmd) self._check_datastore_emulator_support() logging.getLogger().setLevel(constants.LOG_LEVEL_TO_PYTHON_CONSTANT[ options.dev_appserver_log_level]) parsed_env_variables = dict(options.env_variables or []) configuration = application_configuration.ApplicationConfiguration( config_paths=options.config_paths, app_id=options.app_id, runtime=options.runtime, env_variables=parsed_env_variables) all_module_runtimes = { module.runtime for module in configuration.modules } self._check_platform_support(all_module_runtimes) storage_path = api_server.get_storage_path(options.storage_path, configuration.app_id) datastore_path = api_server.get_datastore_path(storage_path, options.datastore_path) datastore_data_type = ( datastore_converter.get_stub_type(datastore_path) if os.path.isfile(datastore_path) else None) if options.skip_sdk_update_check: logging.info('Skipping SDK update check.') else: update_checker.check_for_updates(configuration) # There is no good way to set the default encoding from application code # (it needs to be done during interpreter initialization in site.py or # sitecustomize.py) so just warn developers if they have a different # encoding than production. if sys.getdefaultencoding() != constants.PROD_DEFAULT_ENCODING: logging.warning( 'The default encoding of your local Python interpreter is set to %r ' 'while App Engine\'s production environment uses %r; as a result ' 'your code may behave differently when deployed.', sys.getdefaultencoding(), constants.PROD_DEFAULT_ENCODING) if options.port == 0: logging.warn( 'DEFAULT_VERSION_HOSTNAME will not be set correctly with ' '--port=0') util.setup_environ(configuration.app_id) php_version = self._get_php_runtime(configuration) if not options.php_executable_path and php_version == 'php72': raise PhpPathError( 'For php72, --php_executable_path must be specified.') if options.ssl_certificate_path and options.ssl_certificate_key_path: ssl_certificate_paths = self._create_ssl_certificate_paths_if_valid( options.ssl_certificate_path, options.ssl_certificate_key_path) else: if options.ssl_certificate_path or options.ssl_certificate_key_path: logging.warn('Must provide both --ssl_certificate_path and ' '--ssl_certificate_key_path to enable SSL. Since ' 'only one flag was provided, not using SSL.') ssl_certificate_paths = None if options.google_analytics_client_id: metrics_logger = metrics.GetMetricsLogger() metrics_logger.Start( options.google_analytics_client_id, options.google_analytics_user_agent, all_module_runtimes, {module.env or 'standard' for module in configuration.modules}, options.support_datastore_emulator, datastore_data_type, bool(ssl_certificate_paths), options, multi_module=len(configuration.modules) > 1, dispatch_config=configuration.dispatch is not None, ) self._dispatcher = dispatcher.Dispatcher( configuration, options.host, options.port, options.auth_domain, constants.LOG_LEVEL_TO_RUNTIME_CONSTANT[options.log_level], self._create_php_config(options, php_version), self._create_python_config(options), self._create_java_config(options), self._create_go_config(options), self._create_custom_config(options), self._create_cloud_sql_config(options), self._create_vm_config(options), self._create_module_to_setting(options.max_module_instances, configuration, '--max_module_instances'), options.use_mtime_file_watcher, options.watcher_ignore_re, options.automatic_restart, options.allow_skipped_files, self._create_module_to_setting(options.threadsafe_override, configuration, '--threadsafe_override'), options.external_port, options.specified_service_ports, options.enable_host_checking, ssl_certificate_paths) wsgi_request_info_ = wsgi_request_info.WSGIRequestInfo( self._dispatcher) apiserver = api_server.create_api_server( wsgi_request_info_, storage_path, options, configuration.app_id, configuration.modules[0].application_root) apiserver.start() self._running_modules.append(apiserver) self._dispatcher.start(options.api_host, apiserver.port, wsgi_request_info_) xsrf_path = os.path.join(storage_path, 'xsrf') admin = admin_server.AdminServer(options.admin_host, options.admin_port, self._dispatcher, configuration, xsrf_path, options.enable_host_checking, options.enable_console) admin.start() self._running_modules.append(admin) try: default = self._dispatcher.get_module_by_name('default') apiserver.set_balanced_address(default.balanced_address) except request_info.ModuleDoesNotExistError: logging.warning('No default module found. Ignoring.')