Skip to content

Instantly share code, notes, and snippets.

@theacodes
Last active August 29, 2015 14:07
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save theacodes/eef7c7156c5782656e21 to your computer and use it in GitHub Desktop.
Save theacodes/eef7c7156c5782656e21 to your computer and use it in GitHub Desktop.
Cloud Endpoints - Issue with resources & multiclass.
application: your-app-id
version: 1
runtime: python27
threadsafe: true
api_version: 1
module: api
handlers:
# Endpoints handler
- url: /_ah/spi/.*
script: main.SERVER
libraries:
- name: pycrypto
version: latest
- name: endpoints
version: 1.0
{
"kind": "discovery#restDescription",
"etag": "\"koCc_mmAOJe4d9CoedmJUnZeEcg/zEs4CPpuJjxZavuDQqmcbLpJTKU\"",
"discoveryVersion": "v1",
"id": "library:v1.0",
"name": "library",
"version": "v1.0",
"description": "This is an API",
"icons": {
"x16": "http://www.google.com/images/icons/product/search-16.gif",
"x32": "http://www.google.com/images/icons/product/search-32.gif"
},
"protocol": "rest",
"baseUrl": "http://0.0.0.0:8080/_ah/api/library/v1.0/",
"basePath": "/_ah/api/library/v1.0/",
"rootUrl": "http://0.0.0.0:8080/_ah/api/",
"servicePath": "library/v1.0/",
"batchPath": "batch",
"parameters": {
"alt": {
"type": "string",
"description": "Data format for the response.",
"default": "json",
"enum": [
"json"
],
"enumDescriptions": [
"Responses with Content-Type of application/json"
],
"location": "query"
},
"fields": {
"type": "string",
"description": "Selector specifying which fields to include in a partial response.",
"location": "query"
},
"key": {
"type": "string",
"description": "API key. Your API key identifies your project and provides you with API access, quota, and reports. Required unless you provide an OAuth 2.0 token.",
"location": "query"
},
"oauth_token": {
"type": "string",
"description": "OAuth 2.0 token for the current user.",
"location": "query"
},
"prettyPrint": {
"type": "boolean",
"description": "Returns response with indentations and line breaks.",
"default": "true",
"location": "query"
},
"quotaUser": {
"type": "string",
"description": "Available to use for quota purposes for server-side applications. Can be any arbitrary string assigned to a user, but should not exceed 40 characters. Overrides userIp if both are provided.",
"location": "query"
},
"userIp": {
"type": "string",
"description": "IP address of the site where the request originates. Use this if you want to enforce per-user limits.",
"location": "query"
}
},
"auth": {
"oauth2": {
"scopes": {
"https://www.googleapis.com/auth/userinfo.email": {
"description": "View your email address"
}
}
}
},
"schemas": {
"MainBookMessage": {
"id": "MainBookMessage",
"type": "object",
"properties": {
"book_name": {
"type": "string"
}
}
}
},
"resources": {
"books": {
"methods": {
"insert": {
"id": "library.books.insert",
"path": "books/insert",
"httpMethod": "POST",
"request": {
"$ref": "MainBookMessage",
"parameterName": "resource"
},
"response": {
"$ref": "MainBookMessage"
},
"scopes": [
"https://www.googleapis.com/auth/userinfo.email"
]
}
}
},
"shelves": {
"methods": {
"insert": {
"id": "library.shelves.insert",
"path": "shelves/insert",
"httpMethod": "POST",
"request": {
"$ref": "MainBookMessage",
"parameterName": "resource"
},
"response": {
"$ref": "MainBookMessage"
},
"scopes": [
"https://www.googleapis.com/auth/userinfo.email"
]
}
}
}
}
}
{
"kind": "discovery#restDescription",
"etag": "\"koCc_mmAOJe4d9CoedmJUnZeEcg/X5s0bH095VzAews1mIaRWZpJO1Q\"",
"discoveryVersion": "v1",
"id": "library:v1.0",
"name": "library",
"version": "v1.0",
"description": "This is an API",
"icons": {
"x16": "http://www.google.com/images/icons/product/search-16.gif",
"x32": "http://www.google.com/images/icons/product/search-32.gif"
},
"protocol": "rest",
"baseUrl": "http://0.0.0.0:8080/_ah/api/library/v1.0/",
"basePath": "/_ah/api/library/v1.0/",
"rootUrl": "http://0.0.0.0:8080/_ah/api/",
"servicePath": "library/v1.0/",
"batchPath": "batch",
"parameters": {
"alt": {
"type": "string",
"description": "Data format for the response.",
"default": "json",
"enum": [
"json"
],
"enumDescriptions": [
"Responses with Content-Type of application/json"
],
"location": "query"
},
"fields": {
"type": "string",
"description": "Selector specifying which fields to include in a partial response.",
"location": "query"
},
"key": {
"type": "string",
"description": "API key. Your API key identifies your project and provides you with API access, quota, and reports. Required unless you provide an OAuth 2.0 token.",
"location": "query"
},
"oauth_token": {
"type": "string",
"description": "OAuth 2.0 token for the current user.",
"location": "query"
},
"prettyPrint": {
"type": "boolean",
"description": "Returns response with indentations and line breaks.",
"default": "true",
"location": "query"
},
"quotaUser": {
"type": "string",
"description": "Available to use for quota purposes for server-side applications. Can be any arbitrary string assigned to a user, but should not exceed 40 characters. Overrides userIp if both are provided.",
"location": "query"
},
"userIp": {
"type": "string",
"description": "IP address of the site where the request originates. Use this if you want to enforce per-user limits.",
"location": "query"
}
},
"auth": {
"oauth2": {
"scopes": {
"https://www.googleapis.com/auth/userinfo.email": {
"description": "View your email address"
}
}
}
},
"schemas": {
"MainBookMessage": {
"id": "MainBookMessage",
"type": "object",
"properties": {
"book_name": {
"type": "string"
}
}
},
"MainShelfMessage": {
"id": "MainShelfMessage",
"type": "object",
"properties": {
"shelf_name": {
"type": "string"
}
}
}
},
"resources": {
"books": {
"methods": {
"insert": {
"id": "library.books.insert",
"path": "books/insert",
"httpMethod": "POST",
"request": {
"$ref": "MainBookMessage",
"parameterName": "resource"
},
"response": {
"$ref": "MainBookMessage"
},
"scopes": [
"https://www.googleapis.com/auth/userinfo.email"
]
}
}
},
"shelves": {
"methods": {
"insert": {
"id": "library.shelves.insert",
"path": "shelves/insert",
"httpMethod": "POST",
"request": {
"$ref": "MainShelfMessage",
"parameterName": "resource"
},
"response": {
"$ref": "MainShelfMessage"
},
"scopes": [
"https://www.googleapis.com/auth/userinfo.email"
]
}
}
}
}
}
import endpoints
from protorpc import messages, remote
an_api = endpoints.api(name='library', version='v1.0')
class ShelfMessage(messages.Message):
shelf_name = messages.StringField(1)
class BookMessage(messages.Message):
book_name = messages.StringField(1)
@an_api.api_class(resource_name='shelves', path='shelves')
class Shelves(remote.Service):
@endpoints.method(ShelfMessage, ShelfMessage, name="insert", path="insert")
def insert(self, request):
return request
@an_api.api_class(resource_name='books', path='books')
class Books(remote.Service):
@endpoints.method(BookMessage, BookMessage, name="insert", path="insert")
def insert(self, request):
return request
SERVER = endpoints.api_server([an_api])
Index: python/lib/endpoints-1.0/endpoints/api_config.py
===================================================================
--- python/lib/endpoints-1.0/endpoints/api_config.py (revision 480)
+++ python/lib/endpoints-1.0/endpoints/api_config.py (working copy)
@@ -1388,8 +1388,9 @@
self.__response_schema = {}
- self.__id_from_name = {}
+ self.__id_from_resource_and_name = {}
+
def __get_request_kind(self, method_info):
"""Categorize the type of the request.
@@ -1954,8 +1955,9 @@
for service in services:
protorpc_methods = service.all_remote_methods()
+ resource_name = service.api_info.resource_name or ''
for protorpc_method_name in protorpc_methods.iterkeys():
- method_id = self.__id_from_name[protorpc_method_name]
+ method_id = self.__id_from_resource_and_name[resource_name + '/' + protorpc_method_name]
request_response = {}
@@ -2098,6 +2100,7 @@
for service in services:
remote_methods = service.all_remote_methods()
+ resource_name = service.api_info.resource_name or ''
for protorpc_meth_name, protorpc_meth_info in remote_methods.iteritems():
method_info = getattr(protorpc_meth_info, 'method_info', None)
@@ -2104,7 +2107,8 @@
if method_info is None:
continue
method_id = method_info.method_id(service.api_info)
- self.__id_from_name[protorpc_meth_name] = method_id
+ self.__id_from_resource_and_name[resource_name + '/' + protorpc_meth_name] = method_id
+
method_map[method_id] = self.__method_descriptor(
service, service.__name__, method_info,
protorpc_meth_name, protorpc_meth_info)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment