Home‎ > ‎

Google App Engine

 
 
Google App Engine is one of the easiest ways to get an application using the Healthx API up and running. You build and maintain your application, but host and serve it through Google's infrastructure.
 

 

Before You Start with Google App Engine

First, install the Google App Engine SDK for Python. Installing Google App Engine requires using SMS for verification purposes. For this example, we'll be using Python, so you may have to install a recent version of Python, Python 2.5, which you can get at python.org. Configure App Engine's environment according to their excellent documentation.



Once you've got App Engine chugging along, it's time to make your first Healthx Hello World application. In the first part of this tutorial, we walk you through setting up your application within the Google App Engine framework. If you are already familiar with the App Engine framework and want to skip right to the Healthx APIs, click here. By the time you're finished, you'll have a fully functional application, written in Python, that retrieves data from the Healthx API. Here is what it will look like.

Creating Your Healthx Hello World Application

Create a new directory named HxElig. The files for your Healthx Eligibility Hello World application will reside in this directory. You'll create two files in this directory, named app.py and app.yaml. Create these two skeleton files first to test your setup, you'll build up into a full Healthx application from there.
 
First create the app.py file. Give this file the following contents.
 

app.py

from google.appengine.ext import webapp
from google.appengine.ext.webapp.util import run_wsgi_app


class MainPage(webapp.RequestHandler):
  def get(self):
    self.response.out.write('Healthx Eligibility Here I Come!')

 

application = webapp.WSGIApplication(
                                     [('/', MainPage)],
                                     debug=False)

def main():
  run_wsgi_app(application)
if __name__ == "__main__":
  main()

 
The first two lines import the necessary parts of the Google Webapp framework. You'll add to these lines later when accessing the Healthx data. The MainPage class is the code that gets executed when the "/" URL recieves an HTTP GET request. This mapping is defined in the webapp.WSGIApplication instance. Finally , the main() function starts the application.
 
Next, create the app.yaml file. Give this file the following contents.
 

app.yaml

application: healthxelig #change this to whatever you like
version: 1
runtime: python
api_version: 1

handlers:
- url: /.*
  script: app.py

 
The attributes of the app.yaml file are exactly as defined in the Google App Engine app.yaml reference.

Testing your Healthx Hello World Application
 

Test your first application by launching it from the Google App Engine launcher that comes with Google App Engine. Passing in the port the appserver will listen on is optional. By default the appserver listens on port 8080.
 
Select your application and click Browse. This will open up a web browser where you can view your application.
 
You should see a message that reads "Healthx Eligibility Here I Come!".  If you see this message you have set up Google App Engine correctly and are ready to make some simple queries to the Healthx API.
 

Building in the Healthx API to your Healthx Hello World Application

 
The Healthx API is RESTful, which means you build requests to the API using standard HTTP commands such as GET and POST to persistent URLs. Each API function is called by making an OAuth request to a unique URL. There are several libraries available for OAuth, including one for Python. Read more about the Healthx OAuth implementation here.  For this sample, you'll use the eligibilityv1/getFamily function. The URL for this request looks like this.
 

GetFamily

http://qa.healthx.com/api/eligibilityv1/json/getFamily

 
This URL breaks down into a few relevant parts. First, the base path http://qa.healthx.com/API/. This is the standard path to the sandbox Healthx API. The production API lives at a similar subdomain, such as http://secure.healthx.com/API/. Next is the API service and version, in this case eligibilityv1. At some future date, Healthx may release a new version of this API, in which case the first version will continue to respond until it is deprecated. The next part of the URL maps to the specific function within the API service, admin/GetFamily.

Add the following lines to the top of your app.py file.

from google.appengine.api import urlfetch
from xml.dom.minidom import parseString
from django.utils import simplejson
from oauth import OAuthConsumer
from oauth import OAuthToken
from oauth import OAuthRequest
from oauth import OAuthSignatureMethod_HMAC_SHA1 
import codecs
import cgi
import urllib



In order to import OAuth Python library, you'll need to download it from here. Place your oauth.py file in the root of the directory you created earlier, at the same level as your app.yaml file.

A Note About OAuth

Healthx currently supports what's known as 2-legged OAuth. This means that a trusted application can access Healthx data using signed requests without the assistance of a user. These 2-legged OAuth requests are limited in scope by design. Support for 3-legged OAuth is not far behind. If you've got ideas, let's talk. Here's more about the Healthx OAuth implementation.

 
Add a few constants to the page. You'll get these constants when you sign up for a Healthx Developer account. You are welcome to use these for now, or input your own. If your application uses certificates, you'll have a slightly different set of credentials.


#Constants created when you signup for your Healthx Developer Account
CONSUMER_SECRET = 'Eo3HBzROlgBlJTlzKq5TPiO0pVUYBAUJV3pmhKYhtvWk7nx/'
CONSUMER_KEY = 'YDyLZJe9MaEFLcwgjqR0XqqOl'
INSTANCE_ID = '6EABC67F-F8B9-4435-A3F7-FA16AF14EA56' #given to you by an organization from their applications management page
#Your domain, or Localhost:80XX if on the dev server, or hxeliggetsample.appspot.com for the Healthx Demo
MYDOMAIN = 'http://localhost:8084'
#target for API calls. For testing, point to qa.
BASEPATH = 'http://qa.healthx.com'

Modify the application definition to deal with the new classes we are about to create. It should look like this:

application = webapp.WSGIApplication(
                                     [('/', MainPage),
                                      ('/getelig',GetElig),
                                      ('/oauthpage', OAuthPage),
                                      ('/oauthaccess', MainPage),
                                      ('/mainpage', MainPage)],
                                     debug=False)
def main():
  run_wsgi_app(application)
if __name__ == "__main__":
  main()


Edit the MainPage class to look like the below. This main page doesn't do anything interesting until the user has upgraded a Request Token to an Authorization Token (OAuth steps 1 and 2). We'll take care of the first two steps right after this.
 

class MainPage(webapp.RequestHandler):
def get(self):
self.response.headers['Content-Type'] = 'text/html'
self.response.out.write('<html><head><title>Demo Main</title></head><body>')
oauthtoken=None
self.response.out.write('<h2>Menu</h2>')
if (self.request.get('oauth_token') and self.request.get('oauth_verifier')):
#Only get here if OAuth Steps 1 and 2 are complete.
oauthverifier=self.request.get('oauth_verifier')
#retrieve the token, store the verifier, we'll need that later
query = AppAuthToken.all()
query.filter('tokenkey =', self.request.get('oauth_token'))
updateToken = query.fetch(1)
self.response.out.write("<div>Welcome. Your request token is %(reqtoken)s</div>" % {'reqtoken':updateToken[0].tokenkey})
updateToken[0].verifier=self.request.get('oauth_verifier')
key=updateToken[0].put()
self.response.out.write("""
<div><br /></div>
<form action="/getelig?oauth_verifier=%(oauthverifier)s" method="post">
                <div><input type="submit" value="Get Elig for User"></div>
              </form>
""" % {'oauthverifier':oauthverifier})
self.response.out.write('<a href="/oauthpage">Get Access Through Healthx</a>')
self.response.out.write('</body></html>')

Once those first two OAuth steps are complete, this page adds a form into which you can input your search parameters after the user has logged in to the Healthx site and the Healthx site has redirected the user's browser to this page.
 
Now, add an OAuthPage method. This OAuth page will do the work of fetching a Request Token, then passing the user over to the login screen where that user will provide his or her credentials.
 
class OAuthPage(webapp.RequestHandler):
def get(self):
#OAuth Step 1 : Request a request token.
req_url= (BASEPATH + "/API/Accounts/OAuthGetRequestToken")
#generate callback URL -` use Localhost in testing.
callbackUrl=MYDOMAIN + '/oauthaccess'
consumer = OAuthConsumer(CONSUMER_KEY, CONSUMER_SECRET)
request=OAuthRequest.from_consumer_and_token(oauth_consumer=consumer,token=None, callback=callbackUrl, verifier=None,http_method="GET", http_url=req_url.lower())# realm param is optional by spec, but required for some cases
sigMethod = OAuthSignatureMethod_HMAC_SHA1()
request.sign_request(sigMethod, consumer, None)#token = None
authHeader = request.to_header()
#    qa
req_token = urlfetch.fetch(url=req_url, method=urlfetch.GET, payload="", headers={"Authorization":authHeader["Authorization"], "charset":"utf-8"})
logging.info('authheader=' + str(authHeader))
logging.info("request url=" + req_url)
if req_token.status_code != 200:
self.response.out.write("Failed with response " + str(req_token.status_code))
self.response.out.write("<div>" + str(req_token.content) + "</div>")
else:
tokenstring=(str(req_token.content))
#UTF-8 strings can sometimes contain BOM character to start,  but the parse_qs method inside of OAuthToken.from_string doesn't like BOM.
if (tokenstring.startswith(codecs.BOM_UTF8)):
tokenstring=tokenstring.lstrip(codecs.BOM_UTF8)
try:
token=OAuthToken.from_string(tokenstring)
#save the token secret, we'll need it later.
auth = AppAuthToken(tokenkey=token.key, tokensecret=str(token.secret), verifier=None, accessTokenString=None)
auth.put()
#oauth step 2 : Exchanges a request token for an authorization token, redirecting the user to the login screen in the process
acc_url=(BASEPATH+"/api/Accounts/OAuthAuthorizeToken")
accessRequest=OAuthRequest.from_token_and_callback(token, callbackUrl.lower(), "GET", acc_url.lower(), {"instanceid":INSTANCE_ID})
authUrl = accessRequest.to_url()
logging.info(authUrl)
self.redirect(authUrl)
self.response.out.write('<a href="'+authUrl+'">'+authUrl+'</a>')
except KeyError:
#This might happen if the tokenstring is unable to be parsed into a proper token
raise

 Here, OAuth steps 1 and 2 take place. First, your application requests a request token from Healthx. Then your application exchanges that request token for an authorization token, redirecting the user to the Healthx authorization page.  We save the token and secret so that we can use them later, so we need to create a model class. For more on the model class, refer to Google App Engine's documentation.


class AppAuthToken(db.Model):
    tokenkey = db.StringProperty()
    tokensecret = db.StringProperty()
    adddatetime = db.DateTimeProperty(auto_now_add=True)
    verifier = db.StringProperty()
    accessTokenString = db.StringProperty()


You can see in the OAuthPage class, as well as the MainPage class, we store these AppAuthTokens using the model.put() method. We need to store the tokens for each user so that we can retrieve them when the user returns from the login page. We store the verifier so that we can retrieve the authorization token when we direct the user to the GetElig page. This page takes care of OAuth step 3, exchanging an authorized token for an access token, which then gets stored and used to make requests to protected resources.


class GetElig(webapp.RequestHandler):
    def post(self):
        self.response.headers['Content-Type'] = 'text/html'
self.response.out.write('<html><head><title>Get Eligibility</title></head><body>')
if (self.request.get('oauth_verifier') and self.request.get('oauth_verifier') != 'None'):
upgrade_url=BASEPATH + '/api/Accounts/OAuthGetAccessToken'
consumer = OAuthConsumer(CONSUMER_KEY, CONSUMER_SECRET)
sigMethod = OAuthSignatureMethod_HMAC_SHA1()
query=AppAuthToken.all()
#For this demo, we use verifer to look up your token for convenience because it is already URL encoded. 
# This is not suitable for production code, though it is secured through the Service Provider (healthx).
query.filter('verifier =', self.request.get('oauth_verifier'))
mytoken = query.fetch(1)
if ((mytoken[0])==None):
#if can't find the token, prompt the user to get a different one.
self.response.out.write("Oops. We seem to have lost your login, <a href='../oauthtoken'>please login again.</a>'")
#if we haven't gotten an auth token for the user yet, get one.
elif mytoken[0].accessTokenString is None:
token=OAuthToken(urllib.unquote(mytoken[0].tokenkey), mytoken[0].tokensecret)
token.set_verifier(mytoken[0].verifier)
request=OAuthRequest.from_consumer_and_token(consumer,token, None,token.verifier,"GET", upgrade_url.lower())
#from_consumer_and_token automatically puts in oauth_callback, but this param is not allowed by spec
del request.parameters['oauth_callback']
request.sign_request(sigMethod, consumer, token)
authheader=request.to_header()
result = urlfetch.fetch(url=upgrade_url, method=urlfetch.GET, payload="", headers={"Authorization":authheader['Authorization'], "charset":"utf-8"})
if result.status_code != 200:
self.response.out.write("failed with result " + str(result.status_code))
self.response.out.write("<div>" + str(result.content) + "</div>")
else:
tokenstring=(str(result.content))
#UTF-8 strings can sometimes contain BOM character to start,  but the parse_qs method inside of OAuthToken.from_string doesn't like BOM.
if (tokenstring.startswith(codecs.BOM_UTF8)):
tokenstring=tokenstring.lstrip(codecs.BOM_UTF8)
token=OAuthToken.from_string(tokenstring)
#if we've already got an auth token for this user, then we'll just use it.
else:
token=OAuthToken.from_string(mytoken[0].accessTokenString)
try:
get_elig_url='%(basepath)s/api/eligibilityv1/json/getfamily' % {'basepath':BASEPATH} 
#saving this token in the datastore so if the user clicks the back button, we can reuse the token.
mytoken[0].accessTokenString=token.to_string()
mytoken[0].put()
eligRequest=OAuthRequest.from_consumer_and_token(consumer,token,None,None,"GET",get_elig_url.lower())
eligRequest.sign_request(sigMethod, consumer, token)
eligpostdata=eligRequest.to_postdata()
eligpostdata=simplejson.dumps(eligpostdata)
#realm param is included in signaturebasestring in the Healthx implementation, but not the python library(as per spec).
eligAuthheader=eligRequest.to_header()
eligAuthheader['Authorization']=eligAuthheader['Authorization'].replace('realm="", ','')
eligResult = urlfetch.fetch(url=get_elig_url, method=urlfetch.GET, payload='', headers={"Authorization":eligAuthheader['Authorization'], 'instanceid': INSTANCE_ID, "charset":"utf-8", "content-type":"application/json"})
if eligResult.status_code!=200:
self.response.out.write("Elig Request Failed with result " + str(eligResult.status_code))
self.response.out.write("<div>" + str(eligResult.content) + "</div>")
self.response.out.write("<div>" + str(sigMethod.build_signature_base_string(eligRequest,consumer,token))+ "</div>")
else:
eligInfo = None
if eligResult.status_code == 200:
eligInfo = simplejson.loads(eligResult.content)
#write out data
for eligRec in eligInfo:
type = None
if not eligRec['IsDependent']: 
type = 'Member'
else:
type = 'Dependent'
self.response.out.write("<div><h2>%(fname)s %(lname)s</h2></div>" % {'fname':eligRec['FirstName'],'lname':eligRec['LastName']})
self.response.out.write("<div><b>%s</b></div>" % type)
self.response.out.write("<div>Member ID : %s</div>" % eligRec['MemberID'])
self.response.out.write("<div>Address : %s</div>" % eligRec['Address'])
self.response.out.write("<div>Benefit Plan : %s</div>" % eligRec['BnftPlan'])
#self.response.out.write("<div>" + eligAuthheader2 + "</div>")
except KeyError, k:
self.response.out.write("Could not find key : " + str(k.args)) 
self.response.out.write(eligInfo)
self.response.out.write("<div><a href='../oauthpage'>Click here to start over.</a></div>")
else:
self.redirect('../')
self.response.out.write('</body></html>')


The GetElig class exchanges the Authorization Token for an Access Token, then uses the Access Token to request access to protected resources, in this case, the user's eligibility record. This request must be accompanied by an instance ID on the header.

                eligResult = urlfetch.fetch(url=get_elig_url, method=urlfetch.GET, payload='', headers={"Authorization":eligAuthheader['Authorization'], 'instanceid': INSTANCE_ID, "charset":"utf-8", "content-type":"application/json"})


Finally, because simplejson correctly interprets NULL values as None, we must add a special formatting function for pretty printing.

def jsonGetStr(s):
    try:
        if s is not None:
            return (str(s))
        else:
            return ""
    except:
        raise


Test Your First Complete Healthx Hello World Application

 
To test your application, login with as a user subscribed to a service within the appropriate organization. Do not attempt to use your developer account, it is unlikely to be subscribed to the appropriate organization. For the APP_ID in this sample application, you can login with this user:


Username: Ulysses.Euclid
PWD: euclid_01

When you click the button in your application, your code will fetch the data from the Healthx API and should return a series of name value pairs formatted into a nice table.
 
 
The sample uses inline markup, but you could also use the django framework, which works well with Google App Engine, to manipulate these results. If you did not get these results, here are some troubleshooting steps:
 
  • Check that your application looks exactly like this.
  • Confirm that your dev_appserver is running properly, and is listening on the port you think it is.

Uploading your application to Google App Engine's hosting

 
Upload your application according to Google's instructions. You may first need to create an application at http://appengine.google.com before you can upload it. Use appcfg.py from the command line to begin the upload or the Google App Engine Launcher. You will be prompted for your username and password.
 

Uploading Your Application

appcfg.py update c:/HxElig/ 

 Congratulations, you've already made your first Healthx API application! Next, take a look at our developer documentation for more information on how exactly to use the Healthx API.