diff --git a/appengine/urlfetch/requests/.gitignore b/appengine/urlfetch/requests/.gitignore new file mode 100644 index 00000000000..a65b41774ad --- /dev/null +++ b/appengine/urlfetch/requests/.gitignore @@ -0,0 +1 @@ +lib diff --git a/appengine/urlfetch/app.yaml b/appengine/urlfetch/requests/app.yaml similarity index 100% rename from appengine/urlfetch/app.yaml rename to appengine/urlfetch/requests/app.yaml diff --git a/appengine/urlfetch/requests/appengine_config.py b/appengine/urlfetch/requests/appengine_config.py new file mode 100644 index 00000000000..c903d9a0ac5 --- /dev/null +++ b/appengine/urlfetch/requests/appengine_config.py @@ -0,0 +1,18 @@ +# Copyright 2016 Google Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from google.appengine.ext import vendor + +# Add any libraries installed in the "lib" folder. +vendor.add('lib') diff --git a/appengine/urlfetch/requests/main.py b/appengine/urlfetch/requests/main.py new file mode 100644 index 00000000000..3d0ffb50f82 --- /dev/null +++ b/appengine/urlfetch/requests/main.py @@ -0,0 +1,49 @@ +# Copyright 2016 Google Inc. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# [START app] +import logging + +from flask import Flask + +# [start imports] +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() +# [END imports] + +app = Flask(__name__) + + +@app.route('/') +def index(): + # [START requests_get] + url = 'http://www.google.com/humans.txt' + response = requests.get(url) + response.raise_for_status() + return response.text + # [END requests_get] + + +@app.errorhandler(500) +def server_error(e): + logging.exception('An error ocurred during a request.') + return """ + An internal error occurred:
{}
+ See logs for full stacktrace. + """.format(e), 500 +# [END app] diff --git a/appengine/urlfetch/requests/main_test.py b/appengine/urlfetch/requests/main_test.py new file mode 100644 index 00000000000..23666009aa4 --- /dev/null +++ b/appengine/urlfetch/requests/main_test.py @@ -0,0 +1,24 @@ +# Copyright 2016 Google Inc. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + + +def test_index(testbed): + # Import main here so that the testbed is active, otherwise none of the + # stubs will be available and it will error. + import main + + app = main.app.test_client() + response = app.get('/') + assert response.status_code == 200 + assert 'Google' in response.data.decode('utf-8') diff --git a/appengine/urlfetch/requests/requirements.txt b/appengine/urlfetch/requests/requirements.txt new file mode 100644 index 00000000000..a3a231c99db --- /dev/null +++ b/appengine/urlfetch/requests/requirements.txt @@ -0,0 +1,3 @@ +Flask==0.10.1 +requests==2.10.0 +requests-toolbelt==0.6.0 diff --git a/appengine/urlfetch/snippets/app.yaml b/appengine/urlfetch/snippets/app.yaml new file mode 100644 index 00000000000..102ed60d1b5 --- /dev/null +++ b/appengine/urlfetch/snippets/app.yaml @@ -0,0 +1,7 @@ +runtime: python27 +api_version: 1 +threadsafe: yes + +handlers: +- url: .* + script: main.app diff --git a/appengine/urlfetch/main.py b/appengine/urlfetch/snippets/main.py similarity index 83% rename from appengine/urlfetch/main.py rename to appengine/urlfetch/snippets/main.py index 552a40a1a2c..00950102429 100644 --- a/appengine/urlfetch/main.py +++ b/appengine/urlfetch/snippets/main.py @@ -35,12 +35,12 @@ class UrlLibFetchHandler(webapp2.RequestHandler): def get(self): # [START urllib-get] - url = "http://www.google.com/" + url = 'http://www.google.com/humans.txt' try: result = urllib2.urlopen(url) self.response.write(result.read()) - except urllib2.URLError, e: - logging.error("Caught exception fetching url {}".format(e)) + except urllib2.URLError: + logging.exception('Caught exception fetching url') # [END urllib-get] @@ -49,15 +49,15 @@ class UrlFetchHandler(webapp2.RequestHandler): def get(self): # [START urlfetch-get] - url = "http://www.google.com/" + url = 'http://www.google.com/humans.txt' try: result = urlfetch.fetch(url) if result.status_code == 200: self.response.write(result.content) else: self.response.status_code = result.status_code - except urlfetch.Error, e: - logging.error("Caught exception fetching url {}".format(e)) + except urlfetch.Error: + logging.exception('Caught exception fetching url') # [END urlfetch-get] @@ -65,8 +65,8 @@ class UrlPostHandler(webapp2.RequestHandler): """ Demonstrates an HTTP POST form query using urlfetch""" form_fields = { - "first_name": "Albert", - "last_name": "Johnson", + 'first_name': 'Albert', + 'last_name': 'Johnson', } def get(self): @@ -75,13 +75,13 @@ def get(self): form_data = urllib.urlencode(UrlPostHandler.form_fields) headers = {'Content-Type': 'application/x-www-form-urlencoded'} result = urlfetch.fetch( - url="http://localhost:8080/submit_form", + url='http://localhost:8080/submit_form', payload=form_data, method=urlfetch.POST, headers=headers) self.response.write(result.content) - except urlfetch.Error, e: - logging.error("Caught exception fetching url {}".format(e)) + except urlfetch.Error: + logging.exception('Caught exception fetching url') # [END urlfetch-post] diff --git a/appengine/urlfetch/main_test.py b/appengine/urlfetch/snippets/main_test.py similarity index 65% rename from appengine/urlfetch/main_test.py rename to appengine/urlfetch/snippets/main_test.py index af33ed2ae12..aa84d48649d 100644 --- a/appengine/urlfetch/main_test.py +++ b/appengine/urlfetch/snippets/main_test.py @@ -20,31 +20,24 @@ @pytest.fixture -def app(): +def app(testbed): return webtest.TestApp(main.app) def test_url_lib(app): response = app.get('/') - assert response.status_int == 200 - assert "I'm Feeling Lucky" in response.body + assert 'Google' in response.body -@mock.patch("main.urlfetch") -def test_url_fetch(urlfetch_mock, app): - urlfetch_mock.fetch = mock.Mock( - return_value=mock.Mock(content="I'm Feeling Lucky", - status_code=200)) +def test_url_fetch(app): response = app.get('/url_fetch') - assert response.status_int == 200 - assert "I'm Feeling Lucky" in response.body + assert 'Google' in response.body @mock.patch("main.urlfetch") def test_url_post(urlfetch_mock, app): urlfetch_mock.fetch = mock.Mock( - return_value=mock.Mock(content="Albert", + return_value=mock.Mock(content='Albert', status_code=200)) response = app.get('/url_post') - assert response.status_int == 200 - assert "Albert" in response.body + assert 'Albert' in response.body