0

I'm attempting to incorporate cloud enpoints into my app, I'm currently using the Python Quickstart for proof of concept. I'm having an issue when I attempt to call a method to send a card to my glass. Below is my code, please ignore the indentation is missing.

@endpoints.api(name='tasks', version='v1',
description='API for TaskAlert Management',
allowed_client_ids=[CLIENT_ID, endpoints.API_EXPLORER_CLIENT_ID])
class TaskAlertApi(remote.Service):
@endpoints.method(Task, Task,
name='task.insert',
path='tasker',
http_method='POST')
def insert_task(self, request):

TaskModel(author=request.author, content=request.content, date=request.date).put()
themirror = MainHandler()

themirror._insert_map_with_distance_from_home()

return request

So when "themirror._insert_map_with_distance_from_home()" is called I am getting the following error. Does anyone have any suggestions? I am trying to call this from myappspot.com/_ah/api/explorer.

in _insert_map_with_distance_from_home
    self.mirror_service.timeline().insert(body=body).execute()
AttributeError: 'MainHandler' object has no attribute 'mirror_service'
marty331
  • 423
  • 5
  • 12

1 Answers1

2

I'm afraid you will have to rethink your code quite a bit for this but I'll try to get the basics explained here.

The main problem is that the MainHandler does quite a bit when actually receiving a HTTP request. The most important thing is what happens in the @util.auth_required decorator of the MainHandler's get method, which actually creates the mirror_service, authenticated for the current user. When you access the MainHandler directly from your code, none of this actually happens, so there is no mirror_service available (which results in the error you get).

Since the way endpoints are called is quite different from the way normal RequestHandlers are called, you also can't rely on stored session credentials or similar to match an Endpoints User to the Mirror User.

Basically what you would have to do is to create a new mirror_service inside of your endpoint method.

For this you will have to call your API authenticated (adding the Mirror API scopes to the authentication scopes). You can then extract the used access_token from the request header and use this access_token to create OAuth2Credentials to create the mirror_service.

Some code snippets without promises of completeness since it's hard to tell without knowing your actual code:

import os
from oauth2client.client import AccessTokenCredentials

# extract the token from request
if "HTTP_AUTHORIZATION" in os.environ:
    (tokentype, token)  = os.environ["HTTP_AUTHORIZATION"].split(" ")

# create simple OAuth2Credentials using the token
credentials = AccessTokenCredentials(token, 'my-user-agent/1.0')

# create mirror_service (using the method from util.py from the quickstart(
mirror_service = create_service('mirror', 'v1', credentials)

Of course you would then also have to change the _insert_map_with_distance_from_home to use this mirror_service object, but moving this method away from your MainHandler would make more sense in this context anyway.

Scarygami
  • 15,009
  • 2
  • 35
  • 24
  • Thank you for the guidence. I'm working through it and also incorporating comments from http://stackoverflow.com/questions/18213622/using-additional-google-apis-in-my-glassware-sharing-to-g-accounts Here is the error I'm currently getting. Encountered unexpected error from ProtoRPC method implementation: HttpError () Any ideas? – marty331 Oct 24 '13 at 05:57
  • 1
    When you authenticated for the request to your API (I'm assuming you still test with the API Explorer?) did you add `https://www.googleapis.com/auth/glass.timeline` as additional scope? Because otherwise you don't have permission to write to the timeline with the access token you got. – Scarygami Oct 24 '13 at 07:26
  • Scarygami, that was exactly what I was missing! I now have endpoints connected and am able to send timeline cards to Glass! I can't thank you enough for your help!!! – marty331 Oct 24 '13 at 14:50