Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(74)

Side by Side Diff: third_party/google-endpoints/endpoints/discovery_service.py

Issue 2666783008: Add google-endpoints to third_party/. (Closed)
Patch Set: Created 3 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 # Copyright 2016 Google Inc. All Rights Reserved.
2 #
3 # Licensed under the Apache License, Version 2.0 (the "License");
4 # you may not use this file except in compliance with the License.
5 # You may obtain a copy of the License at
6 #
7 # http://www.apache.org/licenses/LICENSE-2.0
8 #
9 # Unless required by applicable law or agreed to in writing, software
10 # distributed under the License is distributed on an "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 # See the License for the specific language governing permissions and
13 # limitations under the License.
14
15 """Hook into the live Discovery service and get API configuration info."""
16
17 # pylint: disable=g-bad-name
18 import json
19 import logging
20
21 import api_config
22 import discovery_api_proxy
23 import discovery_generator
24 import util
25
26
27 class DiscoveryService(object):
28 """Implements the local discovery service.
29
30 This has a static minimal version of the discoverable part of the
31 discovery .api file.
32
33 It only handles returning the discovery doc and directory, and ignores
34 directory parameters to filter the results.
35
36 The discovery docs/directory are created by calling a Cloud Endpoints
37 discovery service to generate the discovery docs/directory from an .api
38 file/set of .api files.
39 """
40
41 _GET_REST_API = 'apisdev.getRest'
42 _GET_RPC_API = 'apisdev.getRpc'
43 _LIST_API = 'apisdev.list'
44 API_CONFIG = {
45 'name': 'discovery',
46 'version': 'v1',
47 'methods': {
48 'discovery.apis.getRest': {
49 'path': 'apis/{api}/{version}/rest',
50 'httpMethod': 'GET',
51 'rosyMethod': _GET_REST_API,
52 },
53 'discovery.apis.getRpc': {
54 'path': 'apis/{api}/{version}/rpc',
55 'httpMethod': 'GET',
56 'rosyMethod': _GET_RPC_API,
57 },
58 'discovery.apis.list': {
59 'path': 'apis',
60 'httpMethod': 'GET',
61 'rosyMethod': _LIST_API,
62 },
63 }
64 }
65
66 def __init__(self, config_manager, backend):
67 """Initializes an instance of the DiscoveryService.
68
69 Args:
70 config_manager: An instance of ApiConfigManager.
71 backend: An _ApiServer instance for API config generation.
72 """
73 self._config_manager = config_manager
74 self._backend = backend
75 self._discovery_proxy = discovery_api_proxy.DiscoveryApiProxy()
76
77 def _send_success_response(self, response, start_response):
78 """Sends an HTTP 200 json success response.
79
80 This calls start_response and returns the response body.
81
82 Args:
83 response: A string containing the response body to return.
84 start_response: A function with semantics defined in PEP-333.
85
86 Returns:
87 A string, the response body.
88 """
89 headers = [('Content-Type', 'application/json; charset=UTF-8')]
90 return util.send_wsgi_response('200', headers, response, start_response)
91
92 def _get_rest_doc(self, request, start_response):
93 """Sends back HTTP response with API directory.
94
95 This calls start_response and returns the response body. It will return
96 the discovery doc for the requested api/version.
97
98 Args:
99 request: An ApiRequest, the transformed request sent to the Discovery API.
100 start_response: A function with semantics defined in PEP-333.
101
102 Returns:
103 A string, the response body.
104 """
105 api = request.body_json['api']
106 version = request.body_json['version']
107
108 generator = discovery_generator.DiscoveryGenerator()
109 doc = generator.pretty_print_config_to_json(self._backend.api_services)
110 if not doc:
111 error_msg = ('Failed to convert .api to discovery doc for '
112 'version %s of api %s') % (version, api)
113 logging.error('%s', error_msg)
114 return util.send_wsgi_error_response(error_msg, start_response)
115 return self._send_success_response(doc, start_response)
116
117 def _generate_api_config_with_root(self, request):
118 """Generate an API config with a specific root hostname.
119
120 This uses the backend object and the ApiConfigGenerator to create an API
121 config specific to the hostname of the incoming request. This allows for
122 flexible API configs for non-standard environments, such as localhost.
123
124 Args:
125 request: An ApiRequest, the transformed request sent to the Discovery API.
126
127 Returns:
128 A string representation of the generated API config.
129 """
130 actual_root = self._get_actual_root(request)
131 generator = api_config.ApiConfigGenerator()
132 api = request.body_json['api']
133 version = request.body_json['version']
134 lookup_key = (api, version)
135
136 service_factories = self._backend.api_name_version_map.get(lookup_key)
137 if not service_factories:
138 return None
139
140 service_classes = [service_factory.service_class
141 for service_factory in service_factories]
142 config_dict = generator.get_config_dict(
143 service_classes, hostname=actual_root)
144
145 # Save to cache
146 for config in config_dict.get('items', []):
147 lookup_key_with_root = (
148 config.get('name', ''), config.get('version', ''), actual_root)
149 self._config_manager.save_config(lookup_key_with_root, config)
150
151 return config_dict
152
153 def _get_actual_root(self, request):
154 url = request.server
155
156 # Append the port if not the default
157 if ((request.url_scheme == 'https' and request.port != '443') or
158 (request.url_scheme != 'https' and request.port != '80')):
159 url += ':%s' % request.port
160
161 return url
162
163 def _list(self, start_response):
164 """Sends HTTP response containing the API directory.
165
166 This calls start_response and returns the response body.
167
168 Args:
169 start_response: A function with semantics defined in PEP-333.
170
171 Returns:
172 A string containing the response body.
173 """
174 configs = []
175 for config in self._config_manager.configs.itervalues():
176 if config != self.API_CONFIG:
177 configs.append(json.dumps(config))
178 directory = self._discovery_proxy.generate_directory(configs)
179 if not directory:
180 logging.error('Failed to get API directory')
181 # By returning a 404, code explorer still works if you select the
182 # API in the URL
183 return util.send_wsgi_not_found_response(start_response)
184 return self._send_success_response(directory, start_response)
185
186 def handle_discovery_request(self, path, request, start_response):
187 """Returns the result of a discovery service request.
188
189 This calls start_response and returns the response body.
190
191 Args:
192 path: A string containing the API path (the portion of the path
193 after /_ah/api/).
194 request: An ApiRequest, the transformed request sent to the Discovery API.
195 start_response: A function with semantics defined in PEP-333.
196
197 Returns:
198 The response body. Or returns False if the request wasn't handled by
199 DiscoveryService.
200 """
201 if path == self._GET_REST_API:
202 return self._get_rest_doc(request, start_response)
203 elif path == self._GET_RPC_API:
204 error_msg = ('RPC format documents are no longer supported with the '
205 'Endpoints Framework for Python. Please use the REST '
206 'format.')
207 logging.error('%s', error_msg)
208 return util.send_wsgi_error_response(error_msg, start_response)
209 elif path == self._LIST_API:
210 return self._list(start_response)
211 return False
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698