I am trying to deploy my python pricing module which takes product details (string) as argument, on to GAE. The tornado wrapper is working fine on localhost (localhost:8888/?q=) but giving server error 500 on GAE.
Code in Pricing-OOP.py file:
class MainHandler(tornado.web.RequestHandler):
def get(self):
q = self.get_query_argument("q")
res = Pricing(q).pricing()
self.write(json.dumps(res))
def make_app():
return tornado.web.Application([
(r"/", MainHandler),
],debug=True)
if __name__ == '__main__':
Pickleload()
app = make_app()
container = tornado.wsgi.WSGIContainer(app)
http_server = tornado.httpserver.HTTPServer(container)
http_server.listen(8888)
tornado.ioloop.IOLoop.current().start()
app.yaml file:
service: tornado
runtime: python27
threadsafe: no
handlers:
- url: /.*
script: Pricing-OOP.py
The gcloud app logs tail is as follows:
2017-07-26 03:03:30 tornado[20170726t082447] "GET / HTTP/1.1" 500
2017-07-26 03:03:30 tornado[20170726t082447] "GET /favicon.ico HTTP/1.1" 500
2017-07-26 03:03:33 tornado[20170726t082447] "GET / HTTP/1.1" 500
2017-07-26 03:03:34 tornado[20170726t082447] "GET /favicon.ico HTTP/1.1" 500
How do I correct this?
There are a few notes regarding deploying on Google App Engine in the Tornado docs.
In particular, a Tornado application on GAE must be run as a WSGI application. You cannot do things like open ports on the local machine,
and unfortunately it also prevents the use of asynchronous aspects of Tornado (which are often the main driver for using it in the first place).
In your case, instead of creating the HttpServer yourself, you should just create the WSGIAdapter:
# Pricing-OOP.py
# ...
def make_app():
return tornado.web.Application([
(r"/", MainHandler),
],debug=False)
application = make_app()
application = tornado.wsgi.WSGIAdapter(application)
You then tell GAE where to find application by referencing it in the script directive of your configuration file:
# app.yaml
# ...
handlers:
- url: /.*
script: Pricing-OOP.application
Because you are now a "pure" WSGI application, you need to run it in a container. The Google Cloud SDK includes a development server in dev_appserver.py that can be used to host your app:
$ dev_appserver.py . # in directory containing app.yaml
That being done, you can run the same application code both locally and in your GAE instance.
Related
I have a flask web app deployed to google app engine. However, it is not forcing my link to https. However, if I refresh it, it will go to the ssl https version. But the user can still remove the s and jump back into the http version. Is there any way to completely remove the http protocol on my site and have it redirect to the ssl version. Here is the app.yaml file I'm using currently. I also tried adding in redirect_http_response_code: 301 with no luck to remove the http protocol
runtime: python
env: flex
entrypoint: gunicorn -b :$PORT main:app
runtime_config:
python_version: 3.7
# This sample incurs costs to run on the App Engine flexible environment.
# The settings below are to reduce costs during testing and are not appropriate
# for production use. For more information, see:
# https://cloud.google.com/appengine/docs/flexible/python/configuring-your-app-with-app-yaml
manual_scaling:
instances: 1
resources:
cpu: 1
memory_gb: 0.5
disk_size_gb: 10
handlers:
- url: /.*
secure: always
script: auto
I prefer not to install additional software packages for relatively simple things, so I do it myself. For GAE flex there are a few things to handle. I've added comments below to help explain.
#app.before_request
def redirect_http():
# http -> https
if (
# Flask tells us when request is http. This might not be needed for you but
# I need it because I use this code for GAE standard as well.
not request.is_secure and
# Load balancers forward https requests as http but set headers to let you
# know that original request was https
not request.headers.get('X-Forwarded-Proto') == 'https' and
# GAE cron urls must be http
not request.path.startswith("/cron")
):
return redirect("https" + request.url[4:], code=301)
# naked domain -> www
if request.url.startswith("https://example.com"):
return redirect('https://www.' + request.url[8:], code=301)
The Flask packages recommended by #tzovourn do other important things as well so you may want to consider those (I personally do all those things myself since it isn't hard to do them).
I noticed that you are using App Engine Flexible. As per documentation, setting secure: always in app.yaml doesn't work for App Engine Flexible.
Documentation recommends to secure your HTTP requests by using the Flask Talisman library.
Another way to configure your Flask application to redirect all incoming requests to HTTPS is to use the Flask-SSLify extension
I'm refactoring an existing codebase. I switched from using the appcfg.py to using the gcloud command, which seemed to go fine. Our entire codebase was running on one default frontend instance, which I'm now trying to break into services. To start, I created one "worker" backend service, and I'm using a cron job to test.
I can see the worker in the console, but no instance is started. The logs for that service are rapidly flooded with 404's to /_ah/start. I've tried manual and basic scaling. The documentation states that it's okay not to have a startup script, and that a 404 at that endpoint is considered success. However, the instance is not starting.
Logs
worker.yaml
service: worker
runtime: python27
api_version: 1
instance_class: B2
manual_scaling:
instances: 1
threadsafe: false
handlers:
- url: /work/.*
script: worker.app
secure: always
login: admin
worker.py
import webapp2
import handlers
config = {
#...
}
app = webapp2.WSGIApplication([
webapp2.Route(
'/work/test<:/?>',
handlers.Test,
methods=['GET'],
),
], debug=True, config=config)
dispatch.yaml
dispatch:
- url: "*/work/*"
module: worker
i'm new to the cloud endpoint of GAE. I've made a small example, but it does not work,
this is the terminal output:
INFO 2014-04-17 16:34:50,293 sdk_update_checker.py:242] Checking for updates to the SDK.
INFO 2014-04-17 16:34:51,227 sdk_update_checker.py:286] This SDK release is newer than the advertised release.
WARNING 2014-04-17 16:34:51,240 api_server.py:374] Could not initialize images API; you are likely missing the Python "PIL" module.
INFO 2014-04-17 16:34:51,244 api_server.py:171] Starting API server at: http://localhost:64102
INFO 2014-04-17 16:34:51,248 dispatcher.py:182] Starting module "default" running at: http://localhost:8080
INFO 2014-04-17 16:34:51,253 admin_server.py:117] Starting admin server at: http://localhost:8000
INFO 2014-04-17 16:34:58,926 module.py:627] default: "GET /_ah/api/static/proxy.html?jsh=m%3B%2F_%2Fscs%2Fapps-static%2F_%2Fjs%2Fk%3Doz.gapi.en.5SU5w8-2ONg.O%2Fm%3D__features__%2Fam%3DAQ%2Frt%3Dj%2Fd%3D1%2Fz%3Dzcms%2Frs%3DAItRSTMA_WMz6FduGUvb6_l_lrFfWB57ig HTTP/1.1" 200 7327
INFO 2014-04-17 16:34:59,038 module.py:627] default: "POST /_ah/spi/BackendService.getApiConfigs HTTP/1.1" 404 -
INFO 2014-04-17 16:34:59,038 module.py:627] default: "GET /_ah/api/discovery/v1/apis HTTP/1.1" 500 60
as you see there's a 404 and a 500, which i don't know why
this is the code i wrote:
import endpoints
from protorpc import messages
from protorpc import message_types
from protorpc import remote
package = 'mypackage'
class YourResponseMessageClass(messages.Message):
message = messages.StringField(1)
#endpoints.api(name='myendpoint', version='v1')
class ExampleAPI(remote.Service):
#endpoints.method(message_types.VoidMessage,
YourResponseMessageClass,
name='foo.bar')
def user_get(self, request):
return YourResponseMessageClass(message="ciao")
APPLICATION = endpoints.api_server([ExampleAPI])
i've all the file in the same folder (can i move the api in subfolder btw?), and my yaml file looks like this:
application: ls-gae-api
version: 1
runtime: python27
api_version: 1
threadsafe: yes
handlers:
- url: /favicon\.ico
static_files: favicon.ico
upload: favicon\.ico
# Endpoints handler
- url: /_ah/api/.*
script: myfile.APPLICATION
libraries:
- name: webapp2
version: "2.5.2"
- name: endpoints
version: 1.0
Correct path for Endpoints handler must be the following:
# Endpoints handler
- url: /_ah/spi/.*
script: myfile.APPLICATION
Note the spi part (you have api).
I've been trying to use web.py to run a simple web app on Google App Engine but have been running into some pretty basic errors. I've searched over the site and haven't found anything to address my issue. Here is the outline of the code I'm trying to run:
import web
urls = (
"/","Index"
)
app = web.application(urls,globals())
render = web.template.render('pages/', base="layout")
class Index:
def GET(self):
#code...
if __name__ == "__main__":
app.cgirun()
and this is the app.yaml code:
application: #appname
version: 1
runtime: python27
api_version: 1
threadsafe: true
handlers:
- url: /.*
script: home.app
- url: /static
static_dir: static
But then I get this in the log:
2013-08-22 06:11:13 Running command: "['C:\\Python27\\pythonw.exe', 'C:\\Program Files\\Google\\google_appengine\\dev_appserver.py', '--skip_sdk_update_check=yes', '--port=8080', '--admin_port=8000', 'C:\\.....\\root\\home-gae']"
INFO 2013-08-22 06:11:16,956 devappserver2.py:557] Skipping SDK update check.
WARNING 2013-08-22 06:11:16,976 api_server.py:317] Could not initialize images API; you are likely missing the Python "PIL" module.
INFO 2013-08-22 06:11:17,006 api_server.py:138] Starting API server at: http://localhost:64510
INFO 2013-08-22 06:11:17,013 dispatcher.py:164] Starting module "default" running at: http://localhost:8080
INFO 2013-08-22 06:11:17,019 admin_server.py:117] Starting admin server at: http://localhost:8000
ERROR 2013-08-22 10:11:24,303 wsgi.py:235]
Traceback (most recent call last):
File "C:\Program Files\Google\google_appengine\google\appengine\runtime\wsgi.py", line 223, in Handle
result = handler(dict(self._environ), self._StartResponse)
AttributeError: application instance has no __call__ method
INFO 2013-08-22 06:11:24,313 module.py:593] default: "GET / HTTP/1.1" 500 -
The AttributeError is confusing me because there does appear to be a call method in web/application module. Any ideas? Any thoughts would be appreciated.
I found a way to work it out.
import web
urls = (
"/.*", "hello"
)
application = web.application(urls, globals())
#app = web.application(urls, globals())
class hello:
def GET(self):
return "HelloWorld"
#app = app.gaerun()
#app.cgirun()
app = application.wsgifunc()
using "app = application.wsgifunc() ", then the code would work well.
First, there is a little problem with your app.yaml. You need to put your static handler before the catch-all handler:
handlers:
- url: /static
static_dir: static
- url: /.*
script: home.app
Otherwise, you will not be able to serve static files.
To fix your issue with the website not loading, it looks like the development server is trying to treat your CGI app as a WSGI app. Try to fit you home.py file to the official example for web.py on GAE. That is, get rid of the if __name__ == "__main__:" part and simply replace it with:
app = app.gaerun()
I am new to Google App Engine. I am able to start the appserver from the command prompt of Windows and its showing "Info : The server is running at http://localhost:8080/" but still when I enter the address on my browser its showing the Sever not found error.
There are a quite a few reasons this could be happening. If you have checked your firewall settings I'm willing to bet that there is an issue with your app.yaml file.
If your main python script is called main and is located in the root directory of your application code a working example of an app.yaml file is:
application: yourapplicationname
version: 1
runtime: python
api_version: 1
- url: .*
script: main.py
Also make sure that within your main.py file the routes are correct.
eg:
from google.appengine.ext import webapp
class Main(webapp.RequestHandler):
def get(self):
self.response.out.write('Hello World')
def main():
application = webapp.WSGIApplication([('/', Main)],
debug=True)
util.run_wsgi_app(application)
if __name__ == '__main__':
main()