34

Can I use Requests on Google App Engine? I think this library is perfect to create a REST client.

Piotr Dobrogost
  • 41,292
  • 40
  • 236
  • 366
Dilvane Zanardine
  • 2,118
  • 3
  • 23
  • 23

7 Answers7

43

Install the requests-toolbelt library: https://github.com/sigmavirus24/requests-toolbelt

For App Engine it could be something like: pip install requests-toolbelt -t lib

(See: https://cloud.google.com/appengine/docs/python/tools/using-libraries-python-27#installing_a_library)

Then add:

from requests_toolbelt.adapters import appengine
appengine.monkeypatch()

In your main.py or equivalent.

Edit: this solution is now part of the official documentation: https://cloud.google.com/appengine/docs/python/issue-requests#issuing_an_http_request (in the REQUESTS tab)

Eyal Levin
  • 16,271
  • 6
  • 66
  • 56
  • 2
    FYI, the appengine.monkeypatch() line should be in your imports before you import any modules that use requests. – J Wang Feb 12 '18 at 00:25
  • this should be the accepted answer, it worked with me – Diab Aug 16 '18 at 15:22
  • While this works for most cases, it should be noted that this method uses the App Engine's [`urlfetch`](https://cloud.google.com/appengine/docs/standard/python/issue-requests) which is available under the free quota but has some limitations. For example, it does not currently support client-side certificates, which works with the [approach in the currently accepted answer](https://stackoverflow.com/a/28544823/384617) that uses sockets. – David Pärsson Aug 05 '19 at 06:44
27

Yes. On Google Appengine (version 1.9.18) requests version 2.3.0 works IN PRODUCTION (but not on SDK) if you have billing enabled, which enables sockets support.

Update: As of 31 Jan 2017 Requests is working in production with version 2.9.1 in production. However, it's not working with Google cloud SDK 141.0.0

requests on the Appengine SDK fails with all https:// requests:

  ConnectionError: ('Connection aborted.', error(13, 'Permission denied'))

requests version 2.4.1 fails in production with:

  File "distlib/requests/adapters.py", line 407, in send
    raise ConnectionError(err, request=request)
  ConnectionError: ('Connection aborted.', error(13, 'Permission denied'))

requests version 2.5.1 fails in production with:

  File "distlib/requests/adapters.py", line 415, in send
    raise ConnectionError(err, request=request)
  ConnectionError: ('Connection aborted.', error(13, 'Permission denied'))

requests version 2.3.0 works in production, but may cause problems with Debians removed SSLv3 support in the SDK (requests 2.3.0 comes with its own now outdated urllib3). As workaround it is possible to delete the line containing PROTOCOL_SSLv3 in the source of request's urllib3 copy.

  'module' object has no attribute 'PROTOCOL_SSLv3'

Info on sockets support: https://cloud.google.com/appengine/docs/python/sockets/

Jonathan
  • 8,453
  • 9
  • 51
  • 74
cat
  • 2,871
  • 1
  • 23
  • 28
  • 3
    you can fix https:// requests simply by loading the SSL library http://stackoverflow.com/a/34135758/172322 – Yahel Dec 07 '15 at 14:20
  • requests to a https website works even when I did not enable billing - why is that? – Kevin Lee Dec 12 '15 at 18:02
  • I just found out that as long as the socket library isn't actually used (by the request library), App Engine will not throw an exception if billing has not been enabled (i.e. unused imports and unused code is fine). This is because I made simple GET requests only. What was actually called in the underlying code was App Engine's URL fetch library when I checked my quota used (in my use case, using urllib2 instead of requests may be a better option). Also, it works without including the SSL library for my case; App Engine's URL fetch supports https – Kevin Lee Dec 13 '15 at 08:02
  • loading the ssl library works as a fix on the live server, but not on the dev server, it seems –  Jan 10 '16 at 16:01
  • changing requests to version 2.3.0 and including `ssl` library in app.yml fixed the issue for me! thanks – kornesh Aug 31 '16 at 16:01
  • How about version 2.6? – Andrew Stromme Dec 07 '16 at 16:09
8

Not yet but hopefully very soon. Support for GAE is being worked on - see issue #498 (App Engine Fixes).

Requests uses urllib3 which in turn uses httplib which is supported on GAE as a wrapper for urlfetch API. Although urllib3 uses some modules not available on GAE this usage is deliberately made optional so that urllib3 can be used on GAE.

Piotr Dobrogost
  • 41,292
  • 40
  • 236
  • 366
8

this is now possible, I got it working using this combination of workarounds in appengine_config.py:

# Step 1: first add requests and requests-toolbelt to your requirements.txt (or however you install them via pip)
# Step 2: in appengine_config.py add the following snippet:

# see https://cloud.google.com/appengine/docs/python/issue-requests#issuing_an_http_request
import requests
import requests_toolbelt.adapters.appengine

# Use the App Engine Requests adapter. This makes sure that Requests uses
# URLFetch.
requests_toolbelt.adapters.appengine.monkeypatch()

# also monkey patch platform.platform() from https://code.google.com/p/googleappengine/issues/detail?id=12982
import platform

def patch(module):
    def decorate(func):
        setattr(module, func.func_name, func)
        return func
    return decorate


@patch(platform)
def platform():
    return 'AppEngine'
jcjones1515
  • 471
  • 4
  • 12
  • Thank you, except that there is no indentation needed for `def platform()` – vkb Nov 28 '16 at 21:32
  • this should be the accepted answer as for now google does write this into their documentation. requests_toolbelt monkey patch works. – Ian Zhao Dec 27 '17 at 06:16
3

No, in a more recent post, the developers say they do not support GAE because it's too different from python.

Ann Kilzer
  • 1,266
  • 3
  • 16
  • 39
  • They don't support it, but you can still use the library. Just download the source and import it directly. If you need to use sockets to get around `urlfetch()` limits, use [sockets](https://developers.google.com/appengine/docs/python/sockets/) – user3058197 Jul 23 '14 at 23:11
  • Do you have sockets enabled? – user3058197 Jul 24 '14 at 19:36
  • Sorry, @Ann, I forgot that there were some tweaks required to the requests source to make it play nicely with App Engine. Try [this](https://github.com/kennethreitz/requests/pull/739/files) out, I think. If you're having problems and would like to use Requests, I can post the source I use that works... let me know. – user3058197 Jul 25 '14 at 21:40
2

To fix up requests to work with Google App Engine but also allow my application to run outside of GAE, I added the following code:

try:
    from google.appengine.api import urlfetch
    from requests_toolbelt.adapters import appengine
    appengine.monkeypatch()
except ImportError:
    pass
remeika
  • 1,075
  • 11
  • 16
0

Yes you can use the requests module. GCP does not support the use of Requests library out of the box. So we will have to make some tweeks to make it work. In order to deploy an application on the Google App Engine, we need to make a main.py(where main python flask app resides) and app.yaml(configuration file needed to run it in GCP). Here is a sample code for the app.yaml file for python 2.7 environment

runtime: python27
api_version: 1
threadsafe: true

handlers:
- url: /.*
  redirect_http_response_code: 301
  script: main.app

libraries:
- name: flask
  version: 0.12

Now we need to configure the requests library to use URLfetch internally. To use requests, we'll need to install both requests and requests-toolbelt using the vendoring instructions. (https://cloud.google.com/appengine/docs/standard/python/tools/using-libraries-python-27#installing_a_library). Basically we need to install our custom libraries.

  1. Create a directory to store your third-party libraries, such as lib/ mkdir lib
  2. Upload the requests and requests-toolbelt libraries from your system or download them directly into the lib folder created in earlier step.
  3. Use pip (version 6 or later) with the -t flag to copy the libraries into the folder you created in the previous step. For example: pip install -t lib/ (pip install -t lib/ requests)
  4. Create a file named appengine_config.py in the same folder as your app.yaml file.
  5. Edit the appengine_config.py file and provide your library directory to the vendor.add() method. Sample appengine_config.py file

    from google.appengine.ext import vendor
    # Add any libraries install in the "lib" folder.
    vendor.add('lib/requests')
    vendor.add('lib/requests_toolbelt')
    
  6. Once installed, use the requests_toolbelt.adapters.appengine module to configure requests to use URLFetch. Copy the below code to the start of your main.py file

    import requests
    from requests_toolbelt.adapters import appengine
    appengine.monkeypatch(validate_certificate=True)
    

(https://cloud.google.com/appengine/docs/standard/python/issue-requests)

Now we can easily use the requests library to make get/post requests. Test your app:

dev_appserver.py --port=<port number> app.yaml
thirtydot
  • 224,678
  • 48
  • 389
  • 349
Jatin Mahajan
  • 149
  • 1
  • 8