def post(self): """Handle POST requests by executing the API call.""" verifier = unquote(self.request.path.rsplit('/', 1)[1]) if not validate_tamper_proof_string('remote', verifier, REMOTE_KEY): logging.info("Unauthorised Remote Access Attempt: %r", verifier) self.response.set_status(401) return # we skip the SSL check for local dev instances if (RUNNING_ON_GOOGLE_SERVERS and os.environ.get('HTTPS') not in SSL_ENABLED_FLAGS ): logging.info("Insecure Remote Access Attempt") self.response.set_status(401) return ApiCallHandler.post(self)
def run_app( api=None, dict=dict, sys=sys, API_HANDLERS=API_HANDLERS, DEVNULL=DEVNULL, ERROR=ERROR, ERROR_HEADER=ERROR_HEADER, NOTFOUND=NOTFOUND, ): """The core application runner.""" env = dict(os.environ) kwargs = {} sys._boot_stdout = sys.stdout sys.stdout = DEVNULL write = sys._boot_stdout.write try: http_method = env['REQUEST_METHOD'] content_type = env.get('CONTENT-TYPE', '') args = [arg for arg in env['PATH_INFO'].split('/') if arg] if args: api = args[0] # return a NotFoundError if it doesn't look like a valid api call if (http_method != 'POST') or (api not in API_HANDLERS): write(ERROR_HEADER) write(NOTFOUND) return # force the request to be over SSL when on a production deployment if RUNNING_ON_GOOGLE_SERVERS and env.get('HTTPS') not in SSL_FLAGS: write(ERROR_HEADER) write(NOTAUTHORISED) return # we assume that the request is utf-8 encoded, but that the request # kwarg "keys" are in ascii and the kwarg values to be in utf-8 if ';' in content_type: content_type = content_type.split(';', 1)[0] # parse the POST body if it exists and is of a known content type if content_type in VALID_REQUEST_CONTENT_TYPES: post_environ = env.copy() post_environ['QUERY_STRING'] = '' post_data = FieldStorage( environ=post_environ, fp=env['wsgi.input'] ).list if post_data: for field in post_data: key = field.name if field.filename: continue if key not in API_REQUEST_KEYS: continue value = unicode(field.value, UTF8, 'strict') kwargs[key] = value # check that there's a token and it validates if 0: # @/@ signature = kwargs.pop('sig', None) if not signature: write(ERROR_HEADER) write(NOTAUTHORISED) return if not validate_tamper_proof_string( 'token', token, key=API_KEY, timestamped=True ): logging.info("Unauthorised API Access Attempt: %r", token) write(UNAUTH) return handler, store_needed = api_definition # check if the datastore and memcache services are available if store_needed: disabled = None if not CapabilitySet('datastore_v3', capabilities=['write']).is_enabled(): disabled = 'datastore' elif not CapabilitySet('memcache', methods=['set']).is_enabled(): disabled = 'memcache' if disabled: write(ERROR_HEADER) write(DISABLED % disabled) return try: # try and respond with the result of calling the api handler args = tuple(args) result = handler(*args, **kwargs) if result: write(OK_HEADER) write(json_encode(result)) else: write(ERROR) except Exception, error: # log the error and return it as json logging.error(''.join(format_exception(*sys.exc_info()))) write(ERROR_HEADER) write(json_encode({ "error": error.__class__.__name__, "error_msg": str(error) })) except: # this shouldn't ever happen, but just in case... logging.critical(''.join(format_exception(*sys.exc_info()))) write(ERROR_HEADER) write(json_encode({ "error": error.__class__.__name__, "error_msg": str(error) })) finally: sys.stdout = sys._boot_stdout