I'm trying to use cloud points to build my API(at local server).
But I meet some problem now. I add the cloud endpoints code at helloworld.py , like this:
class StringMsg(messages.Message):
"""Greeting that stores a message."""
msg = messages.StringField(1)
class SringListMsg(messages.Message):
"""Collection of Greetings."""
items = messages.StringField(1, repeated=True)
#endpoints.api(name='test', version='v3', description="FIRST")
class test(remote.Service):
#endpoints.method(
StringMsg,
SringListMsg
)
# path='test',
# http_method='GET',
# name='test')
def test(self, request):
msg = request.msg
splitted = msg.split()
return SringListMsg(items=splitted)
api = endpoints.api_server([test])
According to Google's document, cloud endpoints have to be app.yaml. So, I put it at my app.yaml, like this:
application: blabla
version: 1
runtime: python27
api_version: 1
threadsafe: true
handlers:
- url: /_ah/spi/.*
script: helloworld_api.api
- url: /.*
script: main.app
libraries:
- name: webapp2
version: latest
- name: jinja2
version: latest
- name: pycrypto
version: "2.6"
- name: endpoints
version: 1.0
NOW, in my case I need to start three modules, so I use
dev_appserver.py app.yaml dispatch.yaml backend.yaml frontmodule.yaml
And I go to
localhost:8080/_ah/api/explorer
I did't see my API, and I get error:
Skipping dispatch.yaml rules because /_ah/api/explorer is not a dispatcher path
But I DIDN'T add /_ah/api/explorer at my dispatch.yaml.
Somebody help me please!!!
Related
I have the following directory structure for my GAE project:
endpoints/
insights/
insights.py
init.py
lib/
__init__.py
insights.yaml
so in order to get access to the third libraries within lib folder I add the next code in __init__.py file.
import os
import sys
def add_lib_path():
lib_directory = os.path.dirname(os.path.abspath(__file__))
if lib_directory not in sys.path:
sys.path.insert(0, lib_directory)
and I added this code in the insights.py file before the import statements:
from lib import add_lib_path
add_lib_path()
the problem is that now I can import third libraries correctly but my #app.route('/something', methods=['POST']) are not working.
I send a post request and it returns status 200 but it doesn't go inside my #app.route code, I can actually send any route and it just pass out returning 200 but not data and not error.
My imports look like this:
from lib import add_lib_path
add_lib_path()
from flask import Flask, request
And my code inside #app.route('/something', methods=['POST']) looks like this:
def someDef():
some code ...
return response
my yaml file looks like this:
runtime: python27
api_version: 1
threadsafe: false
service: insights
handlers:
- url: /.*
script: endpoints/insights/insights.py
libraries:
- name: ssl
version: latest
Any suggestions about this? Thanks in advance!
The wildcard URL handler in your app.yaml is intercepting the /something post:
handlers:
- url: /.*
script: application.app
You will need to either map out individual urls in your app, or make unique url set for your insights, like /insights/.* in app.yaml. Either way, you can't have a catch-all url handler in your app.yaml if there are other urls you want to give special treatment to, like sending to a separate service.
ok I just changed in the app.yaml file the threadsafe to true, then I added the script like this endpoints.insights.insights.app, using Python module path (with dots not slash) and in my insights.py file I changed #app.route('/something', methods=['POST']) to #app.route('/insights/something', methods=['POST']) .. I added the complete URL that I defined in the app.yaml file and now it's working.
Thanks to #GAEfan for the help, I'll accept the GAEfan answer because it helped me a lot
I'm trying to make a simple form that receives an input from the user and respond by displaying same input on the webpage using python2.7 and Google app engine running locally.Using SublimeText. I'm getting errors "HTTP ERROR 500" and tried to solve it as shown below but no luck.
This is the app.yaml file:
runtime: python27
api_version: 1
threadsafe: true
handlers:
- url: /
script: test.app
This is the test file:
import webapp2
form="""
<form action="/testform">
<input name= "q">
<input type="submit">
</form>
"""
class MainPage(webapp2.RequestHandler):
def get(self):
self.response.out.write(form)
class TestHandler(webapp2.RequestHandler):
def get(self):
q = self.resquest.get("q")
self.response.out.write(q)
app = webapp2.WSGIApplication([('/', MainPage), ('/testform', TestHandler)], debug=True)
When I run the file above I receive this message:
The url "/testform" does not match any handlers.
I already try including a separate handler for the /testform URL:
handlers:
- url: /
script: test.app
- url: /testform
script: test.app
When I do that then I receive the following message:
localhost is currently unable to handle this request.
HTTP ERROR 500
I also try changing / to .* and also to /.* on the app.yaml file to handle all URL's like this:
handlers:
- url: .*
script: test.app
and:
handlers:
- url: /.*
script: test.app
Having the same result:
localhost is currently unable to handle this request.
HTTP ERROR 500
Converting comments to an answer to not leave the question hanging.
In the initial version of you app.yaml file you only have one handler with the url: / pattern. The /testform request doesn't match this single handler, which explains the initial error message:
The url "/testform" does not match any handlers.
All subsequent attempts went OK from handler mapping prospective (I'd go for the url: .* one as it's shorter, but that's just a personal preference, any of them should do), the error message actually changed into:
localhost is currently unable to handle this request. HTTP ERROR 500
But this error has a different root cause - the resquest vs request typo in the (now properly mapped) TestHandler.get() method.
My cronjob does not run when I click Run Now in http://localhost:8000/cron
My app contains the following files
hello.py
import webapp2
class MainPage(webapp2.RequestHandler):
def get(self):
self.response.headers["Content-Type"] = "text/plain"\
self.response.write("Congratulations, it's a web app!")
routes = [('/', MainPage)]
my_app = webapp2.WSGIApplication(routes, debug=True)
app.yaml
application: hello
version: 1
runtime: python27
api_version: 1
threadsafe: false
handlers:
- url: /.*
script: hello.my_app
- url: /tasks/summary
script: hello.application
cron_script.py
from google.appengine.ext import webapp
from google.appengine.ext.webapp.util import run_wsgi_app
class CronTask(webapp.RequestHandler):
def get(self):
f = open("test.txt","w") #opens file with name of "test.txt"
f.write("I am a test file.")
f.write("Maybe someday, he will promote me to a real file.")
f.write("Man, I long to be a real file")
f.write("and hang out with all my new real file friends.")
f.close()
application = webapp.WSGIApplication([('/tasks/summary', CronTask)],
debug=True)
if __name__ == '__main__':
run_wsgi_app(application)
cron.yaml
cron:
- description: daily summary job
url: /tasks/summary
target: beta
schedule: every 1 minutes
Your cron.yaml file will make requests to /tasks/summary.
Your app.yaml directs them to your hello.application.
But your matching hello.py file doesn't have a matching route for /tasks/summary.
You could expand your existing route pattern to match that path:
routes = [('/.*', MainPage)]
But more likely you'll add specific route for it (and you'll need to add the matching handler code for it as well):
routes = [('/tasks/summary', CronHandler)]
I want to build a python client to talk to my python Google Cloud Endpoints API. My simple HelloWorld example is suffering from an HTTPException in the python client and I can't figure out why.
I've setup simple examples as suggested in this extremely helpful thread. The GAE Endpoints API is running on localhost:8080 with no problems - I can successfully access it in the API Explorer. Before I added the offending service = build() line, my simple client ran fine on localhost:8080.
When trying to get the client to talk to the endpoints API, I get the following error:
File "/Applications/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/google/appengine/dist27/gae_override/httplib.py", line 526, in getresponse
raise HTTPException(str(e))
HTTPException: Deadline exceeded while waiting for HTTP response from URL: http://localhost:8080/_ah/api/discovery/v1/apis/helloworldendpoints/v1/rest?userIp=%3A%3A1
I've tried extending the http deadline. Not only did that not help, but such a simple first call on localhost should not be exceeding a default 5s deadline. I've also tried accessing the discovery URL directly within a browser and that works fine, too.
Here is my simple code. First the client, main.py:
import webapp2
import os
import httplib2
from apiclient.discovery import build
http = httplib2.Http()
# HTTPException happens on the following line:
# Note that I am using http, not https
service = build("helloworldendpoints", "v1", http=http,
discoveryServiceUrl=("http://localhost:8080/_ah/api/discovery/v1/apis/{api}/{apiVersion}/rest"))
# result = service.resource().method([parameters]).execute()
class MainPage(webapp2.RequestHandler):
def get(self):
self.response.headers['Content-type'] = 'text/plain'
self.response.out.write("Hey, this is working!")
app = webapp2.WSGIApplication(
[('/', MainPage)],
debug=True)
Here's the Hello World endpoint, helloworld.py:
"""Hello World API implemented using Google Cloud Endpoints.
Contains declarations of endpoint, endpoint methods,
as well as the ProtoRPC message class and container required
for endpoint method definition.
"""
import endpoints
from protorpc import messages
from protorpc import message_types
from protorpc import remote
# If the request contains path or querystring arguments,
# you cannot use a simple Message class.
# Instead, you must use a ResourceContainer class
REQUEST_CONTAINER = endpoints.ResourceContainer(
message_types.VoidMessage,
name=messages.StringField(1),
)
package = 'Hello'
class Hello(messages.Message):
"""String that stores a message."""
greeting = messages.StringField(1)
#endpoints.api(name='helloworldendpoints', version='v1')
class HelloWorldApi(remote.Service):
"""Helloworld API v1."""
#endpoints.method(message_types.VoidMessage, Hello,
path = "sayHello", http_method='GET', name = "sayHello")
def say_hello(self, request):
return Hello(greeting="Hello World")
#endpoints.method(REQUEST_CONTAINER, Hello,
path = "sayHelloByName", http_method='GET', name = "sayHelloByName")
def say_hello_by_name(self, request):
greet = "Hello {}".format(request.name)
return Hello(greeting=greet)
api = endpoints.api_server([HelloWorldApi])
Finally, here is my app.yaml file:
application: <<my web client id removed for stack overflow>>
version: 1
runtime: python27
api_version: 1
threadsafe: yes
handlers:
- url: /_ah/spi/.*
script: helloworld.api
secure: always
# catchall - must come last!
- url: /.*
script: main.app
secure: always
libraries:
- name: endpoints
version: latest
- name: webapp2
version: latest
Why am I getting an HTTP Deadline Exceeded and how to I fix it?
On your main.py you forgot to add some variables to your discovery service url string, or you just copied the code here without it. By the looks of it you were probably suppose to use the format string method.
"http://localhost:8080/_ah/api/discovery/v1/apis/{api}/{apiVersion}/rest".format(api='helloworldendpoints', apiVersion="v1")
By looking at the logs you'll probably see something like this:
INFO 2015-11-19 18:44:51,562 module.py:794] default: "GET /HTTP/1.1" 500 -
INFO 2015-11-19 18:44:51,595 module.py:794] default: "POST /_ah/spi/BackendService.getApiConfigs HTTP/1.1" 200 3109
INFO 2015-11-19 18:44:52,110 module.py:794] default: "GET /_ah/api/discovery/v1/apis/helloworldendpoints/v1/rest?userIp=127.0.0.1 HTTP/1.1" 200 3719
It's timing out first and then "working".
Move the service discovery request inside the request handler:
class MainPage(webapp2.RequestHandler):
def get(self):
service = build("helloworldendpoints", "v1",
http=http,
discoveryServiceUrl=("http://localhost:8080/_ah/api/discovery/v1/apis/{api}/{apiVersion}/rest")
.format(api='helloworldendpoints', apiVersion='v1'))
Hi I'm new to Google App Engine and Cloud Endpoints.
I have an app engine that serves web application.
And I want to use it with Cloud Endpoints.
So I just added source codes from here:
https://cloud.google.com/appengine/docs/python/endpoints/getstarted/backend/write_api
But I cannot deploy app and get this error message:
Checking if Endpoints configuration has been updated.
07:13 AM Failed to update Endpoints configuration. The app returned an error when the Google Cloud Endpoints server attempted to communicate with it.
07:13 AM See the deployment troubleshooting documentation for more information: https://developers.google.com/appengine/docs/python/endpoints/test_deploy#troubleshooting_a_deployment_failure
And this is my source codes
import endpoints
from protorpc import messages
from protorpc import message_types
from protorpc import remote
package = 'Hello'
class Greeting(messages.Message):
"""Greeting that stores a message."""
message = messages.StringField(1)
class GreetingCollection(messages.Message):
"""Collection of Greetings."""
items = messages.MessageField(Greeting, 1, repeated=True)
STORED_GREETINGS = GreetingCollection(items=[
Greeting(message='hello world!'),
Greeting(message='goodbye world!'),
])
#endpoints.api(name='helloworld', version='v1')
class HelloWorldApi(remote.Service):
"""Helloworld API v1."""
#endpoints.method(message_types.VoidMessage, GreetingCollection,
path='hellogreeting', http_method='GET',
name='greetings.listGreeting')
def greetings_list(self, unused_request):
return STORED_GREETINGS
ID_RESOURCE = endpoints.ResourceContainer(
message_types.VoidMessage,
id=messages.IntegerField(1, variant=messages.Variant.INT32))
#endpoints.method(ID_RESOURCE, Greeting,
path='hellogreeting/{id}', http_method='GET',
name='greetings.getGreeting')
def greeting_get(self, request):
try:
return STORED_GREETINGS.items[request.id]
except (IndexError, TypeError):
raise endpoints.NotFoundException('Greeting %s not found.' %
(request.id,))
APPLICATION = endpoints.api_server([HelloWorldApi])
exactly same with tutorial
and my app.yaml
application: my application id
version: application version
runtime: python27
api_version: 1
threadsafe: true
handlers:
- url: /data
script: MLP.app
login: admin
- url: /insert_db
script: MLP.app
login: admin
- url: /validete
script: MLP.app
login: admin
- url: /stylesheets
static_dir: stylesheets
- url: /js
static_dir: js
- url: /.*
script: MLP.app
- url: /_ah/spi/.*
script: MLP_mobile_backend.APPLICATION
libraries:
- name: webapp2
version: latest
- name: jinja2
version: latest
- name: pycrypto
version: latest
- name: endpoints
version: 1.0
MLP.py is just web service with webapp2
How can I solve the problem?
From the app.yaml line script: MLP_mobile_backend.APPLICATION, it means your code sample must live in a MLP_mobile_backend.py file at the root of your app engine project
.
├── app.yaml
├── MLP.py
└── MLP_mobile_backend.py
with an endpoint api server named APPLICATION defined in that file just as in your code sample above.
APPLICATION = endpoints.api_server([HelloWorldApi])
After those requirements are fulfilled, this line points to how to access your endpoints:
#endpoints.api(name='helloworld', version='v1')
So for example, let's say you're running your devserver's module on port 8080 and you want to access the hellogreeting path:
#endpoints.method(message_types.VoidMessage, GreetingCollection,
path='hellogreeting', http_method='GET',
name='greetings.listGreeting')
you can use cURL or httpie or your browser to locally navigate to the devserver's default module at http://localhost:8080/_ah/api/helloworld/v1/hellogreeting or with Google's API explorer at http://localhost:8080/_ah/api/explorer which should result in this response body:
{
"items": [
{
"message": "hello world!"
},
{
"message": "goodbye world!"
}
]
}
Once you get it set up locally, you can then deploy it.
More here