Skip to content

Commit f3e075b

Browse files
committed
New code samples for Python quickstart for Endpoints Frameworks v2
1 parent c022b16 commit f3e075b

File tree

9 files changed

+226
-0
lines changed

9 files changed

+226
-0
lines changed
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
runtime: python27
2+
threadsafe: true
3+
api_version: 1
4+
5+
handlers:
6+
# The endpoints handler must be mapped to /_ah/api.
7+
- url: /_ah/api/.*
8+
script: main.api
9+
10+
libraries:
11+
- name: pycrypto
12+
version: 2.6
13+
- name: ssl
14+
version: 2.7.11
15+
16+
env_variables:
17+
# Replace with your Endpoints service name.
18+
ENDPOINTS_SERVICE_NAME: your-service.appspot.com
19+
# Replace with the version ID of your uploaded Endpoints service.
20+
ENDPOINTS_SERVICE_VERSION: 2016-08-01r0
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
from google.appengine.ext import vendor
2+
3+
# Add any libraries installed in the `lib` folder.
4+
vendor.add('lib')
Lines changed: 149 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,149 @@
1+
# Copyright 2016 Google Inc. All rights reserved.
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
"""This is a sample Hello World API implemented using Google Cloud
16+
Endpoints."""
17+
18+
# [START imports]
19+
import endpoints
20+
from protorpc import message_types
21+
from protorpc import messages
22+
from protorpc import remote
23+
# [END imports]
24+
25+
26+
# [START messages]
27+
class Greeting(messages.Message):
28+
"""Greeting that stores a message."""
29+
message = messages.StringField(1)
30+
31+
32+
class GreetingCollection(messages.Message):
33+
"""Collection of Greetings."""
34+
items = messages.MessageField(Greeting, 1, repeated=True)
35+
36+
37+
STORED_GREETINGS = GreetingCollection(items=[
38+
Greeting(message='hello world!'),
39+
Greeting(message='goodbye world!'),
40+
])
41+
# [END messages]
42+
43+
44+
# [START greeting_api]
45+
@endpoints.api(name='greeting', version='v1')
46+
class GreetingApi(remote.Service):
47+
48+
@endpoints.method(
49+
# This method does not take a request message.
50+
message_types.VoidMessage,
51+
# This method returns a GreetingCollection message.
52+
GreetingCollection,
53+
path='greetings',
54+
http_method='GET',
55+
name='greetings.list')
56+
def list_greetings(self, unused_request):
57+
return STORED_GREETINGS
58+
59+
# ResourceContainers are used to encapsuate a request body and url
60+
# parameters. This one is used to represent the Greeting ID for the
61+
# greeting_get method.
62+
GET_RESOURCE = endpoints.ResourceContainer(
63+
# The request body should be empty.
64+
message_types.VoidMessage,
65+
# Accept one url parameter: and integer named 'id'
66+
id=messages.IntegerField(1, variant=messages.Variant.INT32))
67+
68+
@endpoints.method(
69+
# Use the ResourceContainer defined above to accept an empty body
70+
# but an ID in the query string.
71+
GET_RESOURCE,
72+
# This method returns a Greeting message.
73+
Greeting,
74+
# The path defines the source of the URL parameter 'id'. If not
75+
# specified here, it would need to be in the query string.
76+
path='greetings/{id}',
77+
http_method='GET',
78+
name='greetings.get')
79+
def get_greeting(self, request):
80+
try:
81+
# request.id is used to access the URL parameter.
82+
return STORED_GREETINGS.items[request.id]
83+
except (IndexError, TypeError):
84+
raise endpoints.NotFoundException(
85+
'Greeting {} not found'.format(request.id))
86+
# [END greeting_api]
87+
88+
# [START multiply]
89+
# This ResourceContainer is similar to the one used for get_greeting, but
90+
# this one also contains a request body in the form of a Greeting message.
91+
MULTIPLY_RESOURCE = endpoints.ResourceContainer(
92+
Greeting,
93+
times=messages.IntegerField(2, variant=messages.Variant.INT32,
94+
required=True))
95+
96+
@endpoints.method(
97+
# This method accepts a request body containing a Greeting message
98+
# and a URL parameter specifying how many times to multiply the
99+
# message.
100+
MULTIPLY_RESOURCE,
101+
# This method returns a Greeting message.
102+
Greeting,
103+
path='greetings/multiply/{times}',
104+
http_method='POST',
105+
name='greetings.multiply')
106+
def multiply_greeting(self, request):
107+
return Greeting(message=request.message * request.times)
108+
# [END multiply]
109+
110+
111+
# [START auth_config]
112+
WEB_CLIENT_ID = 'replace this with your web client application ID'
113+
ANDROID_CLIENT_ID = 'replace this with your Android client ID'
114+
IOS_CLIENT_ID = 'replace this with your iOS client ID'
115+
ANDROID_AUDIENCE = WEB_CLIENT_ID
116+
ALLOWED_CLIENT_IDS = [
117+
WEB_CLIENT_ID, ANDROID_CLIENT_ID, IOS_CLIENT_ID,
118+
endpoints.API_EXPLORER_CLIENT_ID]
119+
# [END auth_config]
120+
121+
122+
# [START authed_greeting_api]
123+
@endpoints.api(
124+
name='authed_greeting',
125+
version='v1',
126+
# Only allowed configured Client IDs to access this API.
127+
allowed_client_ids=ALLOWED_CLIENT_IDS,
128+
# Only allow auth tokens with the given audience to access this API.
129+
audiences=[ANDROID_AUDIENCE],
130+
# Require auth tokens to have the following scopes to access this API.
131+
scopes=[endpoints.EMAIL_SCOPE])
132+
class AuthedGreetingApi(remote.Service):
133+
134+
@endpoints.method(
135+
message_types.VoidMessage,
136+
Greeting,
137+
path='greet',
138+
http_method='POST',
139+
name='greet')
140+
def greet(self, request):
141+
user = endpoints.get_current_user()
142+
user_name = user.email() if user else 'Anonymous'
143+
return Greeting(message='Hello, {}'.format(user_name))
144+
# [END authed_greeting_api]
145+
146+
147+
# [START api_server]
148+
api = endpoints.api_server([GreetingApi, AuthedGreetingApi])
149+
# [END api_server]
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
# Copyright 2016 Google Inc. All rights reserved.
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
import main
16+
import mock
17+
from protorpc import message_types
18+
19+
20+
def test_list_greetings(testbed):
21+
api = main.GreetingApi()
22+
response = api.list_greetings(message_types.VoidMessage())
23+
assert len(response.items) == 2
24+
25+
26+
def test_get_greeting(testbed):
27+
api = main.GreetingApi()
28+
request = main.GreetingApi.get_greeting.remote.request_type(id=1)
29+
response = api.get_greeting(request)
30+
assert response.message == 'goodbye world!'
31+
32+
33+
def test_multiply_greeting(testbed):
34+
api = main.GreetingApi()
35+
request = main.GreetingApi.multiply_greeting.remote.request_type(
36+
times=4,
37+
message='help I\'m trapped in a test case.')
38+
response = api.multiply_greeting(request)
39+
assert response.message == 'help I\'m trapped in a test case.' * 4
40+
41+
42+
def test_authed_greet(testbed):
43+
api = main.AuthedGreetingApi()
44+
45+
with mock.patch('main.endpoints.get_current_user') as user_mock:
46+
user_mock.return_value = None
47+
response = api.greet(message_types.VoidMessage())
48+
assert response.message == 'Hello, Anonymous'
49+
50+
user_mock.return_value = mock.Mock()
51+
user_mock.return_value.email.return_value = '[email protected]'
52+
response = api.greet(message_types.VoidMessage())
53+
assert response.message == 'Hello, [email protected]'

0 commit comments

Comments
 (0)