| 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
|
| +import logging
|
| +import os
|
| +import traceback
|
| +import webapp2
|
| +
|
| +from google.appengine.api import app_identity
|
| +from google.appengine.ext import ndb
|
| +
|
| +import common
|
| +
|
| +
|
| +def is_development_server():
|
| + return os.environ['SERVER_SOFTWARE'].startswith('Development')
|
| +
|
| +
|
| +class VMHandler(webapp2.RequestHandler):
|
| + 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)
|
| +
|
| + def post(self):
|
| + requester_id = self.request.headers.get('X-Appengine-Inbound-Appid', None)
|
| + task_name = self.request.headers.get('X-AppEngine-TaskName', None)
|
| + my_id = app_identity.get_application_id()
|
| + authorized = is_development_server() or task_name or requester_id == my_id
|
| + if not authorized:
|
| + self.abort(403)
|
| + # logging.debug('Received POST /vm: %s',
|
| + # common.payload_stats(self.request.body))
|
| + data = common.get_data()
|
| + 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'])
|
| + http_auth = credentials.authorize(http_auth)
|
| + def callback(_response, _content):
|
| + 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),
|
| + ], debug=True)
|
|
|