Index: appengine/chrome_infra_mon_proxy/vm_module.py |
diff --git a/appengine/chrome_infra_mon_proxy/vm_module.py b/appengine/chrome_infra_mon_proxy/vm_module.py |
new file mode 100644 |
index 0000000000000000000000000000000000000000..4e5e85f2bca980dac7ded8c8f1f3d6a0cad9e127 |
--- /dev/null |
+++ b/appengine/chrome_infra_mon_proxy/vm_module.py |
@@ -0,0 +1,70 @@ |
+# Copyright 2015 The Chromium Authors. All rights reserved. |
+# Use of this source code is governed by a BSD-style license that can be |
+# found in the LICENSE file. |
+ |
+import googleapiclient.http |
+import json |
+import httplib2 |
ghost stip (do not use)
2015/04/14 00:36:43
nit: alphabetize
Sergey Berezin (google)
2015/04/16 04:39:07
Done.
|
+import logging |
+import os |
+import traceback |
+import webapp2 |
+ |
+from google.appengine.api import app_identity |
+from google.appengine.ext import ndb |
+ |
+import common |
ghost stip (do not use)
2015/04/14 00:36:44
you should rename this to be more specific. common
Sergey Berezin (google)
2015/04/16 04:39:07
I agree it's a lousy name. I just can't think of a
|
+ |
+ |
+def is_development_server(): |
+ return os.environ['SERVER_SOFTWARE'].startswith('Development') |
+ |
+ |
+class VMHandler(webapp2.RequestHandler): |
ghost stip (do not use)
2015/04/14 00:36:44
it pleases me how small this file is :)
Sergey Berezin (google)
2015/04/16 04:39:08
You should've seen the perl version :-)
|
+ def get(self): |
+ msg = 'This endpoint is for internal POST requests only.\n' |
+ self.response.headers['Content-Type'] = 'text/plain' |
+ self.response.out.write(msg) |
ghost stip (do not use)
2015/04/14 00:36:43
self.response.set_status(403) ?
Sergey Berezin (google)
2015/04/16 04:39:08
Actually, I just removed get(). It was there for d
|
+ |
+ def post(self): |
+ requester_id = self.request.headers.get('X-Appengine-Inbound-Appid', None) |
ghost stip (do not use)
2015/04/14 00:36:44
isn't None default? I think you can just do self.r
Sergey Berezin (google)
2015/04/16 04:39:08
Done.
|
+ task_name = self.request.headers.get('X-AppEngine-TaskName', None) |
ghost stip (do not use)
2015/04/14 00:36:44
same
Sergey Berezin (google)
2015/04/16 04:39:08
Done.
|
+ my_id = app_identity.get_application_id() |
+ authorized = is_development_server() or task_name or requester_id == my_id |
ghost stip (do not use)
2015/04/14 00:36:43
nit: might want to make the 'is me' check more obv
Sergey Berezin (google)
2015/04/16 04:39:08
Done.
|
+ if not authorized: |
+ self.abort(403) |
+ # logging.debug('Received POST /vm: %s', |
ghost stip (do not use)
2015/04/14 00:36:43
nit: remove commented code
Sergey Berezin (google)
2015/04/16 04:39:08
Done.
|
+ # common.payload_stats(self.request.body)) |
+ data = common.get_data() |
ghost stip (do not use)
2015/04/14 00:36:43
can you rename get_data to be more specific? what
Sergey Berezin (google)
2015/04/16 04:39:07
Renamed, and moved the function to vm_module.py.
|
+ if not data: |
+ self.abort_admin_error('Endpoint data is not set') |
+ if not all(f in data for f in ['credentials', 'url']): |
+ self.abort_admin_error('Missing required fields: credentials, url') |
+ |
+ url = data['url'] |
+ http_auth = httplib2.Http() |
+ if not is_development_server(): |
+ credentials = common.get_credentials(data['credentials'], data['scopes']) |
ghost stip (do not use)
2015/04/14 00:36:43
if data came from common, why do I have to pass i
Sergey Berezin (google)
2015/04/16 04:39:07
This function is now also in vm_module.py. It's no
|
+ http_auth = credentials.authorize(http_auth) |
+ def callback(_response, _content): |
ghost stip (do not use)
2015/04/14 00:36:44
I'm surprised this is needed. can you just set the
Sergey Berezin (google)
2015/04/16 04:39:08
Good idea, added logging for an error in response.
|
+ pass |
+ # Important: set content-type to binary, otherwise httplib2 mangles it. |
+ data.setdefault('headers', {}).update({ |
+ 'content-length': str(len(self.request.body)), |
+ 'content-type': 'application/x-protobuf', |
+ }) |
+ request = googleapiclient.http.HttpRequest( |
+ http_auth, callback, url, method='POST', body=self.request.body, |
+ headers=data['headers']) |
+ request.execute() |
+ |
+ def abort_admin_error(self, message): |
+ logging.error('%s; please visit https://%s/admin/', |
+ message, app_identity.get_default_version_hostname()) |
+ self.abort(500) |
+ |
+ |
+logging.basicConfig(level=logging.DEBUG) |
+app = webapp2.WSGIApplication([ |
+ (r'/vm', VMHandler), |
ghost stip (do not use)
2015/04/14 00:36:44
probably don't need the r here
Sergey Berezin (google)
2015/04/16 04:39:08
Done.
|
+ ], debug=True) |