google-app-engine
Cannot reach Endpoint method with cURL
I have created a Cloud Endpoint through Android Studio as part of an Android project. I am not intending to use this part of the Cloud Endpoint with Android. I need to access this Cloud Endpoint with cURL. I am getting the error: 404 - Not Found The Endpoint is online, as I can see the index.html at the usual URL: http://appid.appspot.com/ Hello, Endpoints! Enter your name and press the button below to call your Google Cloud Endpoints API. In order to find the URL I used the discovery URL for apis: https://appid.appspot.com/_ah/api/discovery/v1/apis That delivered this JSON (sensitive data obfuscated): { "kind": "discovery#directoryList", "discoveryVersion": "v1", "items": [ { "kind": "discovery#directoryItem", "id": "discovery:v1", "name": "discovery", "version": "v1", "title": "APIs Discovery Service", "description": "Provides information about other Google APIs, such as what APIs are available, the resource, and method details for each API.", "discoveryRestUrl": "https://appid.appspot.com/_ah/api/discovery/v1/apis/discovery/v1/rest", "discoveryLink": "./apis/discovery/v1/rest", "icons": { "x16": "http://www.google.com/images/icons/feature/filing_cabinet_search-g16.png", "x32": "http://www.google.com/images/icons/feature/filing_cabinet_search-g32.png" }, "documentationLink": "https://developers.google.com/discovery/", "preferred": true }, { "kind": "discovery#directoryItem", "id": "myApi:v1", "name": "myApi", "version": "v1", "description": "This is an API", "discoveryRestUrl": "https://appid.appspot.com/_ah/api/discovery/v1/apis/myApi/v1/rest", "discoveryLink": "./apis/myApi/v1/rest", "icons": { "x16": "https://www.gstatic.com/images/branding/product/1x/googleg_16dp.png", "x32": "https://www.gstatic.com/images/branding/product/1x/googleg_32dp.png" }, "preferred": true } ] } I took the discoveryRestUrl for the api myApi. https://appid.appspot.com/_ah/api/discovery/v1/apis/myApi/v1/rest { "kind": "discovery#restDescription", "etag": "\"ODRTh3xaRR64wpeXJSlF33HMN-0/uPLUFYnKhGLgMnhurkbMaKcMDpA\"", "discoveryVersion": "v1", "id": "myApi:v1", "name": "myApi", "version": "v1", "description": "This is an API", "ownerDomain": "backend.appid.companydomain.com", "ownerName": "backend.appid.companydomain.com", "icons": { "x16": "https://www.gstatic.com/images/branding/product/1x/googleg_16dp.png", "x32": "https://www.gstatic.com/images/branding/product/1x/googleg_32dp.png" }, "protocol": "rest", "baseUrl": "https://appid.appspot.com/_ah/api/myApi/v1/sayHi/", "basePath": "/_ah/api/myApi/v1/sayHi/", "rootUrl": "https://appid.appspot.com/_ah/api/", "servicePath": "myApi/v1/sayHi/", "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": { "MyBean": { "id": "MyBean", "type": "object", "properties": { "data": { "type": "string" } } } }, "methods": { "sayHi": { "id": "myApi.sayHi", "path": "{name}", "httpMethod": "POST", "parameters": { "name": { "type": "string", "required": true, "location": "path" } }, "parameterOrder": [ "name" ], "response": { "$ref": "MyBean" }, "scopes": [ "https://www.googleapis.com/auth/userinfo.email" ] } } } I took the URL from here: "baseUrl": "https://appid.appspot.com/_ah/api/myApi/v1/sayHi/". My curl command: curl --header "Content-Type: application/json" -X POST -d '{"name": "Testing"}' http://appid.appspot.com/_ah/api/myApi/v1/sayHi What URL should I use? Is it more likely that something isn't set up correctly? #Jeff O'Neill - Update 1 Testing using the following URL: http://appid.appspot.com/myApi/v1/sayHi <html><head> <meta http-equiv="content-type" content="text/html;charset=utf-8"> <title>404 Not Found</title> </head> <body text=#000000 bgcolor=#ffffff> <h1>Error: Not Found</h1> <h2>The requested URL <code>/myApi/v1/sayHi</code> was not found on this server.</h2> <h2></h2> </body></html> Update 2 I experimented with this Endpoint: /** * A simple endpoint method that takes a name and says Hi back */ #ApiMethod(name = "sayHi2", path = "test") public MyBean sayHi2() { MyBean response = new MyBean(); response.setData("This is a message"); return response; } I can call this with: curl --header "Content-Type: application/json" -X POST https://appid.appspot.com/_ah/api/myApi/v1/test I still cannot explain why the original Endpoint cannot be reached, but if adding a path annotation fixes it then I am happy.
This is because #Named("name") here is a path parameter. Note this part of your discovery document: "sayHi": { "id": "myApi.sayHi", "path": "{name}", This means to call this method, you append the name to the base path, so the correct command is this: $ curl --header "Content-Type: application/json" -X POST -d '' https://appid.appspot.com/_ah/api/myApi/v1/sayHi/test { "data": "Hi, test", "kind": "myApi#resourcesItem", "etag": "\"yN6wlOVUuMN6KwnZ3LSrHdbVqwM/EMLxMt_QPFPG4ZrTIVpiyuCWflg\"" }
Related Links
Google App Engine TCP/IP connection
getServingUrl occasionally returning relative URL in appengine development server
How to do bulk deletes from Google App Engien Datastore
Data transition over multiple application versions
Understanding ReferenceProperty backend behavior in GAE
deployment of mahout on Google app engine
Avoiding unnecessarily large IDs in App Engine
XG-Transactions Fail in Google App Engine's Local Java Server — Run fine when deployed on Live GAE
How is the user authentication with Google accounts working inside the GAE technically
How to get all records from GAE datastore with particular parent?
Profiling datastore queries in Google App Engine
Declare a dependency to Google App Engine with Ivy as a whole
GAE Go Json-RPC call example
How To Use Entity Groups And Ancestors with DjangoForms
How to order by the field stored in the separate model?
Can't connect to localhost from Chrome extension