I'm making a GAE app using Python 2.7.11. This is my first project building a GAE app, and I'm new to web development also. Link here. I am trying to access the Google Book's API in order to retrieve book information. Everything works flawlessly when deployed locally. I type a book's name into the search field, my handler flies off, hits 2 Google APIs (search, then volume), parses the results and appends it to the page.
When I deploy my app to GAE, I get the following error (with stack trace):
Traceback (most recent call last):
File "/base/data/home/runtimes/python27/python27_lib/versions/third_party/webapp2-2.5.2/webapp2.py", line 1535, in __call__
rv = self.handle_exception(request, response, e)
File "/base/data/home/runtimes/python27/python27_lib/versions/third_party/webapp2-2.5.2/webapp2.py", line 1529, in __call__
rv = self.router.dispatch(request, response)
File "/base/data/home/runtimes/python27/python27_lib/versions/third_party/webapp2-2.5.2/webapp2.py", line 1278, in default_dispatcher
return route.handler_adapter(request, response)
File "/base/data/home/runtimes/python27/python27_lib/versions/third_party/webapp2-2.5.2/webapp2.py", line 1102, in __call__
return handler.dispatch()
File "/base/data/home/runtimes/python27/python27_lib/versions/third_party/webapp2-2.5.2/webapp2.py", line 572, in dispatch
return self.handle_exception(e, self.app.debug)
File "/base/data/home/runtimes/python27/python27_lib/versions/third_party/webapp2-2.5.2/webapp2.py", line 570, in dispatch
return method(*args, **kwargs)
File "/base/data/home/apps/s~my-life-app/1.392279800807967905/myapp.py", line 320, in post
response_body = urlopen(request).read()
File "/base/data/home/runtimes/python27/python27_dist/lib/python2.7/urllib2.py", line 127, in urlopen
return _opener.open(url, data, timeout)
File "/base/data/home/runtimes/python27/python27_dist/lib/python2.7/urllib2.py", line 410, in open
response = meth(req, response)
File "/base/data/home/runtimes/python27/python27_dist/lib/python2.7/urllib2.py", line 523, in http_response
'http', request, response, code, msg, hdrs)
File "/base/data/home/runtimes/python27/python27_dist/lib/python2.7/urllib2.py", line 448, in error
return self._call_chain(*args)
File "/base/data/home/runtimes/python27/python27_dist/lib/python2.7/urllib2.py", line 382, in _call_chain
result = func(*args)
File "/base/data/home/runtimes/python27/python27_dist/lib/python2.7/urllib2.py", line 531, in http_error_default
raise HTTPError(req.get_full_url(), code, msg, hdrs, fp)
HTTPError: HTTP Error 403: Forbidden
Here is the part of my code that performs the API calls. (It's very sloppy, sorry. I've just been trying to fix this issue before cleaning the code up).
headers = {'Accept': 'application/json'}
book = Book(parent=books_key)
book.name = self.request.get('name')
googleBookSearch = "https://www.googleapis.com/books/v1/volumes?q="
googleBookVol = "https://www.googleapis.com/books/v1/volumes/ID"
escapedBookName = urllib.quote(book.name)
apiCall = googleBookSearch + escapedBookName + "&" + api_key2
request = Request(apiCall, headers=headers)
response_body = urlopen(request).read()
parsed_book = json.loads(response_body)
if parsed_book['totalItems'] != 0:
volumeID = parsed_book['items'][0]['id']
googleBookVol = googleBookVol.replace("ID", volumeID)
googleBookVol = googleBookVol + "?" + api_key2
logging.info(googleBookVol)
request = Request(googleBookVol, headers=headers)
response_body = urlopen(request).read()
response_body = json.loads(response_body)
book.name = response_body['volumeInfo']['title']
pageCount = response_body['volumeInfo']['pageCount']
book.pages = int(pageCount)
bookCover = response_body['volumeInfo']['imageLinks']['smallThumbnail']
book.cover = str(bookCover)
book.published = str(response_body['volumeInfo']['publishedDate'])
book.author = str(response_body['volumeInfo']['authors'][0])
book.put()
self.redirect("/books")
According to Google's API documentation, these APIs are only accessing public data so no OAuth or API key is required. Needless to say, that didn't work. I've added my API Key, which still didn't work. I've enabled Google Books API from the Developer Console. The only thing left to me is Oauth, but my head is spinning trying to read the pages upon pages of documentation, some of which is vastly different to each other, so I don't know what to implement. The web app does not require signing in of any kind, and the API requests only use public data. Thanks.
Is there anyone who can help?
EDIT: This is the log portion of what I got back from Google that I pulled from Cloud Console logs. The first portion is the exact URL as shown also by logging.info.
{
metadata:
{
severity:
"ERROR"
projectId:
"598422355661"
serviceName:
"appengine.googleapis.com"
zone:
"us6"
labels:
{…}
timestamp:
"2016-04-23T17:40:38.988615Z"
projectNumber:
"598422355661"
}
protoPayload:
{
@type:
"type.googleapis.com/google.appengine.logging.v1.RequestLog"
appId:
"s~my-life-app"
versionId:
"1"
requestId:
"571bb39600ff0f15c71037dd9b0001737e6d792d6c6966652d617070000131000100"
ip:
"189.61.48.66"
startTime:
"2016-04-23T17:40:38.988615Z"
endTime:
"2016-04-23T17:40:39.020226Z"
latency:
"0.031611s"
megaCycles:
"20"
method:
"POST"
resource:
"/sign"
httpVersion:
"HTTP/1.1"
status:
500
responseSize:
"870"
referrer:
"http://my-life-app.appspot.com/books"
userAgent:
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/49.0.2623.112 Safari/537.36"
urlMapEntry:
"myapp.app"
host:
"my-life-app.appspot.com"
cost:
1.29081e-7
instanceIndex:
-1
instanceId:
"00c61b117cb28d6a28da9eadf0f9ad4279a74be43a1ca345cb"
line:
[
0:
{
time:
"2016-04-23T17:40:38.991900Z"
severity:
"INFO"
logMessage:
"https://www.googleapis.com/books/v1/volumes?q=Pale+Blue+Dot&key=AIzaSyD9o4jKfQvvCAr8glvom4llEAssu8ojmgk"
}
1:
{
time:
"2016-04-23T17:40:39.011339Z"
severity:
"ERROR"
logMessage:
"HTTP Error 403: Forbidden
Traceback (most recent call last):
File "/base/data/home/runtimes/python27/python27_lib/versions/third_party/webapp2-2.5.2/webapp2.py", line 1535, in __call__
rv = self.handle_exception(request, response, e)
File "/base/data/home/runtimes/python27/python27_lib/versions/third_party/webapp2-2.5.2/webapp2.py", line 1529, in __call__
rv = self.router.dispatch(request, response)
File "/base/data/home/runtimes/python27/python27_lib/versions/third_party/webapp2-2.5.2/webapp2.py", line 1278, in default_dispatcher
return route.handler_adapter(request, response)
File "/base/data/home/runtimes/python27/python27_lib/versions/third_party/webapp2-2.5.2/webapp2.py", line 1102, in __call__
return handler.dispatch()
File "/base/data/home/runtimes/python27/python27_lib/versions/third_party/webapp2-2.5.2/webapp2.py", line 572, in dispatch
return self.handle_exception(e, self.app.debug)
File "/base/data/home/runtimes/python27/python27_lib/versions/third_party/webapp2-2.5.2/webapp2.py", line 570, in dispatch
return method(*args, **kwargs)
File "/base/data/home/apps/s~my-life-app/1.392300489206286534/myapp.py", line 333, in post
response_body = urlopen(request).read()
File "/base/data/home/runtimes/python27/python27_dist/lib/python2.7/urllib2.py", line 127, in urlopen
return _opener.open(url, data, timeout)
File "/base/data/home/runtimes/python27/python27_dist/lib/python2.7/urllib2.py", line 410, in open
response = meth(req, response)
File "/base/data/home/runtimes/python27/python27_dist/lib/python2.7/urllib2.py", line 523, in http_response
'http', request, response, code, msg, hdrs)
File "/base/data/home/runtimes/python27/python27_dist/lib/python2.7/urllib2.py", line 448, in error
return self._call_chain(*args)
File "/base/data/home/runtimes/python27/python27_dist/lib/python2.7/urllib2.py", line 382, in _call_chain
result = func(*args)
File "/base/data/home/runtimes/python27/python27_dist/lib/python2.7/urllib2.py", line 531, in http_error_default
raise HTTPError(req.get_full_url(), code, msg, hdrs, fp)
HTTPError: HTTP Error 403: Forbidden"
}
]
appEngineRelease:
"1.9.36"
}
insertId:
"2016-04-23|10:40:40.411640-07|10.106.197.137|1661671430"
log:
"appengine.googleapis.com/request_log"
httpRequest:
{
status:
500
}
operation:
{
id:
"571bb39600ff0f15c71037dd9b0001737e6d792d6c6966652d617070000131000100"
producer:
"appengine.googleapis.com/request_id"
}
}
For future strugglers, make sure to add appropriate country string in your request
&country=US
The Books API uses the IP address of the client to geo-locate the user. Since we must honor copyright laws from various countries, and have country-specific rights from publishers, we need to know the country where the requests come from in order to serve the proper content.