Consuming GAE Endpoints with a Python client - python

I am using Google AppEngine Endpoints to build a web API.
I will consume it with a client written in Python.
I know that scripts are provided to generate Android and iOS client API, but it doesn't seem that there is anything comparable for Python.
It does seem redundant to code everything again. For instance, the messages definition which are basically the same.
It there anyway of getting this done more easily?
Thanks

You can use the Google APIs Client Library for Python which is compatible with endpoints.
Normally you would build a client using service = build(api, version, http=http) for example service = build("plus", "v1", http=http) to build a client to access to Google+ API.
For using the library for your endpoint you would use:
service = build("your_api", "your_api_version", http=http,
discoveryServiceUrl=("https://yourapp.appspot.com/_ah/api/discovery/v1/"
"apis/{api}/{apiVersion}/rest"))
You can then access your API with
result = service.resource().method([parameters]).execute()

Here's what happens with the endpoints helloworld greetings example:
__author__ = 'robertking'
import httplib2
from apiclient.discovery import build
http = httplib2.Http()
service = build("helloworld", "v1", http=http,
discoveryServiceUrl=("http://localhost:8080/_ah/api/discovery/v1/apis/helloworld/v1/rest"))
print service.greetings().listGreeting().execute()['items']
"""
prints
[{u'message': u'hello world!'}, {u'message': u'goodbye world!'}]
"""
Right now I'm using http.

Related

Retrive endpoint url of deployed app from google cloud run with Python

I want to send requests to a deployed app on a cloud run with python, but inside the test file, I don't want to hardcode the endpoint; how can I get the URL of the deployed app with python script inside the test file so that I can send requests to that URL?
You can use gcloud to fetch the url of the service like this
gcloud run services describe SERVICE_NAME
--format="value(status.url)"
In a pure Python way, you can use Google's API Client Library for Run.
To my knowledge, there isn't a Cloud Client Library
The method is namespaces.services.get and it is documented by APIs Explorer namespaces.services.get.
One important fact with Cloud Run is that the API endpoint differs by Cloud Run region.
See service endpoint. You will need to override the client configuration (using ClientOptions) with the correct (region-specific) api_endpoint.
The following is from-memory! I've not run this code but it should be (nearly) correct:
import google.auth
import os
from googleapiclient import discovery
from google.api_core.client_options import ClientOptions
creds, project = google.auth.default()
REGION = os.getenv("REGION")
SERVICE = os.getenv("SERVICE")
# Must override the default run.googleapis.com endpoint
# with region-specific endpoint
api_endpoint = "https://{region}-run.googleapis.com".format(
region=REGION
)
options = ClientOptions(
api_endpoint=api_endpoint
)
service = discovery.build("run", "v1",
client_options=options,
credentials=creds
)
name = "namespaces/{namespace}/services/{service}".format(
namespace=project,
service=SERVICE
)
rqst = service.namespaces().services().get(name=name)
resp = rqst.execute()
The resp will be Service and you can grab its ServiceStatus url.

Make calls to Drive API inside of a Google App Engine Cloud Endpoints

I am trying to build my own endpoints inside of an App Engine Application.
There is an endpoint API that needs to ask user for
"https://www.googleapis.com/auth/drive.readonly" scope.
It performs a list of the Drive API and scan the drive file of that user.
The problem is that I don't know how to make call to Drive api inside of an endpoint API.
I think inside of the endpoint method, it has the credentials we got from the user. But I don't know how to receive that.
I am using python as the backend language.
#drivetosp_test_api.api_class(resource_name='report')
class Report(remote.Service):
#endpoints.method(EmptyMessage, EmptyMessage,
name='generate',
path='report/generate',
http_method='GET'
)
def report_generate(self, request):
logging.info(endpoints)
return EmptyMessage()
You can use os.environ to access the HTTP Authorization header, that includes the access token, that was granted all scopes you asked for on the client side, include drive.readonly in your sample.
if "HTTP_AUTHORIZATION" in os.environ:
(tokentype, token) = os.environ["HTTP_AUTHORIZATION"].split(" ")
You can then use this token to make calls to the API, either directly or by using the Google APIs Client Library for Python:
credentials = AccessTokenCredentials(token, 'my-user-agent/1.0')
http = httplib2.Http()
http = credentials.authorize(http)
service = build('drive', 'v2', http=http)
files = service.files().list().execute()
Note that this approach won't work if you are using an Android client, because that uses ID-Token authorization instead of access tokens.

How to generate RequestToken URL for Google API

I'm writing Python 2.7 desktop application which needs to access Google Spreadsheets using OAuth 2.0. I'va found a library for Google Spreadsheets for python here which uses this python OAuth2.0 library. The flow for desktop applications described here tells me that I have to generate RequestToken URL first which user can use to get Authorization Code to the application.
I already have Client ID and Client Secret generated in Developer's Console. But I can't figure out what class/method I can use to generate RequestToken URL in python.
Should I somehow construct it myself or is there an API to do it?
I've figured it out from documentation here
#!/usr/bin/env python
import oauth2client
from oauth2client.client import OAuth2WebServerFlow
flow = OAuth2WebServerFlow(client_id='your_client_id',
client_secret='your_client_secret',
scope='https://spreadsheets.google.com/feeds',
redirect_uri='urn:ietf:wg:oauth:2.0:oob')
auth_uri = flow.step1_get_authorize_url()
print auth_uri
You'd need your own client_id and client_secret here though.

Sample of Server to Server authentication using OAuth 2.0 with Google API's

This is a follow-up question for this question:
I have successfully created a private key and have read the various pages of Google documentation on the concepts of server to server authentication.
I need to create a JWT to authorize my App Engine application (Python) to access the Google calendar and post events in the calendar. From the source in oauth2client it looks like I need to use oauth2client.client.SignedJwtAssertionCredentials to create the JWT.
What I'm missing at the moment is a stylised bit of sample Python code of the various steps involved to create the JWT and use it to authenticate my App Engine application for Google Calendar. Also, from SignedJwtAssertionCredentials source it looks like I need some App Engine compatible library to perform the signing.
Can anybody shed some light on this?
After some digging I found a couple of samples based on the OAuth2 authentication. From this I cooked up the following simple sample that creates a JWT to access the calendar API:
import httplib2
import pprint
from apiclient.discovery import build
from oauth2client.client import SignedJwtAssertionCredentials
# Get the private key from the Google supplied private key file.
f = file("your_private_key_file.p12", "rb")
key = f.read()
f.close()
# Create the JWT
credentials = SignedJwtAssertionCredentials(
"xxxxxxxxxx#developer.gserviceaccount.com", key,
scope="https://www.googleapis.com/auth/calendar"
)
# Create an authorized http instance
http = httplib2.Http()
http = credentials.authorize(http)
# Create a service call to the calendar API
service = build("calendar", "v3", http=http)
# List all calendars.
lists = service.calendarList().list(pageToken=None).execute(http=http)
pprint.pprint(lists)
For this to work on Google App Engine you will need to enable PyCrypto for your app. This means adding the following to your app.yaml file:
libraries:
- name: pycrypto
version: "latest"

Google API Service Account

I'm trying to connect to the google doubeclick api through a service account (client email and p12 certificate), using the python client library as in the following example:
http://code.google.com/p/google-api-python-client/source/browse/samples/service_account/tasks.py
It's returning me an empty access_token:
In [9]: type(credentials.access_token)
Out[9]: <type 'NoneType'>
What is the significance of this? Is there something I am likely doing wrong? I have also tried accessing the tasks api as in the example (thinking that possibly the doubleclick api is not a supported scope) but same result.
UPDATE (example code):
from oauth2client.client import SignedJwtAssertionCredentials
import httplib2
from adspygoogle.dfp import DfpClient
f = file('/path/to/.ssh/google-api.p12', 'rb')
key = f.read()
f.close()
credentials = SignedJwtAssertionCredentials('<email>', key, scope='https://www.google.com/apis/ads/publisher')
credentials.refresh(http)
http = httplib2.Http()
http = credentials.authorize(http)
client = DfpClient.DfpClient(headers={'networkCode': '<code>', 'applicationName': 'test', 'userAgent': 'test', 'oauth2credentials': credentials})
inventory_service = client.GetInventoryService()
inventory_service.getAdUnitsByStatement({'query':''})
ERROR:
DfpAuthenticationError: [AuthenticationError.NO_NETWORKS_TO_ACCESS # ]
The NO_NETWORKS_TO_ACCESS error specifically means that you did authenticate to the API endpoint but that your account isn't associated with a network. Search for that error on this page https://developers.google.com/doubleclick-publishers/docs/reference/v201203/InventoryService?hl=en.
You either need to have the Google account you are authenticating as invited to the network via the DoubleClick User Interface or you need to use impersonation.
A more specific writeup on DFP API and service accounts was recently posted https://developers.google.com/doubleclick-publishers/docs/service_accounts to the documentation. I suggest you look at the alternative section of that documentation to determine if you might prefer an OAuth 2.0 installed flow.

Categories

Resources