Tornado web server in webfaction - python

I am starting with web development. I am trying to develop and webapp using the Instagram API and Django. I was looking that a lot of people it's using Tornado Web Server for Real Time Subscriptions. So I am using Webfaction as a host and found this code so I can wrap my Django project with the "WSGI Container" that Tornado Web Server provides:
import os
import tornado.httpserver
import tornado.ioloop
import tornado.wsgi
import tornado.web
import sys
import django.core.handlers.wsgi
sys.path.append('/path/to/project')
class HelloHandler(tornado.web.RequestHandler):
def get(self):
self.write('Hello from tornado')
def main():
os.environ['DJANGO_SETTINGS_MODULE'] = 'myproject.settings' # path to your settings module
wsgi_app = tornado.wsgi.WSGIContainer(django.core.handlers.wsgi.WSGIHandler())
tornado_app = tornado.web.Application(
[
('/hello-tornado', HelloHandler),
('.*', tornado.web.FallbackHandler, dict(fallback=wsgi_app)),
]
)
http_server = tornado.httpserver.HTTPServer(tornado_app)
http_server.listen(8080)
tornado.ioloop.IOLoop.instance().start()
if __name__ == "__main__":
main()
So I run this python script inside my Webfaction server and everytime I try to access "http://mywebsite.com/hello-tornado/" does not seem to work. I know I am running that Tornado web server on that port but do not know how too access from the browser or something like that. What I am doing wrong here? Thanks for your help and patience. Will cyber high-five for every answer.
EDIT: What I am really trying to do is that I want to receive all the calls from the subscriptions that I make with the Instagram RealTime Subscription API through Tornado, for that I have a callback url "http://mysite.com/sub" and I want to be able to receive through Tornado.

You are starting the server at port 8080, Web browsers use port 80 by default, try using: http://mywebsite.com:8080/hello-tornado
if you want to use port 80 and you already have a web server running in the box you can try following Ali-Akber Saifee suggestion, or run the WSGI application directly from the server, using something like mod_python (http://www.modpython.org), you will lose the ability to run Tornado code, but Django will work.

You have to create a custom app (listening on port), note the port that is assigned to your app then configure tornado to serve on that port: http_server.listen(my port)
You can also avoid tornado and start directly by installing a django app.

Related

Python Twisted Authentication Without HTTP Authentication

I'm setting up a Flask server, and want to use a Twisted ReverseProxyResource to proxy over another local server. In Flask, I have a current_user.is_authenticated boolean which I use to protect pages. How can I lock the ReverseProxyResource using this variable, so that it cannot be accessed when a user is logged out? The twisted.web.guard module requires me to set up another HTTP authentication system entirely, and the library doesn't seem to have any other built-in solution.
I've set up some demo code, (based off a previous question) attempting to place the Flask server inside of the Twisted reactor. I'm using the ReverseProxyResource to allow for two-way communication with a Shellinabox server on port 4200.
from flask import Flask
from twisted.internet import reactor
from twisted.web.proxy import ReverseProxyResource
from twisted.web.resource import Resource
from twisted.web.server import Site
from twisted.web.wsgi import WSGIResource
app = Flask(__name__)
#app.route('/example')
def index():
return 'Flask within Twisted?'
flask_site = WSGIResource(reactor, reactor.getThreadPool(), app)
root = Resource()
site_example = ReverseProxyResource('localhost', 4200, b'')
root.putChild(b'ssh', site_example)
reactor.listenTCP(8081, Site(root))
reactor.run()
I'd be okay switching to another reverse proxy, but only Twisted has worked so far. I'm also not wanting to switch to the Klein framework due to what I already have established in Flask.

How to Serve a Local App Using Waitress and Nginx

I have a dash(plotly) app set up using flask as the server and can serve it on our Windows Server to port:8041 using waitress. My code to launch waitress is below;
#!/usr/bin/env python3
from waitress import serve
from src.pacedash.app import server as application
if __name__ == "__main__":
serve(application, threads=100, port=8041)
Everything works great if I use python run_waitress.py, except that when someone on our network navigates to the servename:8041 there is a "Not Secure" warning next to the url. Our IT vendor was able to get a cert file and key, but I'm not sure how to bring those into my current setup.
I have been trying to use nginx, but I can't find a guide to setting it up with waitress and I'm not too familiar with web apps or wsgi because I primarily work as the lone data person here.
I have been working on this same issue and have a solution. The nginx .conf file needs have a location defined like this:
location /myapp/ {
# Define the location of the proxy server to send the request to
proxy_pass http://localhost:8041/myapp/;
# standard proxy_set_header stuff below...
}
Then in your Dash application set the url_base_pathname to the same value:
app = dash.Dash(__name__, url_base_pathname='/myapp/')
I would use ngrok to expose your web app. It's amazingly simple:
Read this: https://ngrok.com/
I could be misinterpreting what you need, because I am not familiar with waitress (why not serve the app locally just using flask?), but if you need to test the live app, ngrok is what you should use.

Flask as proxy doesn't work when deployed to tornado

I wrote a flask app as kind of a proxy, to analyse the data passing through it and provide a web page where I get the result. All seems to went well when using the default development server that comes with flask, say using:
app.run()
But when I tried to deploy the app to a server, for example tornado or wsgiref.simple_server in Python standard library using:
from tornado.wsgi import WSGIContainer
from tornado.httpserver import HTTPServer
from tornado.ioloop import IOLoop
from app import app
http_server = HTTPServer(WSGIContainer(app))
http_server.listen(5000)
IOLoop.instance().start()
or
from wsgiref.simple_server import make_server
from app import app
httpd = make_server('', 5000, app)
httpd.serve_forever()
This two ways result in getting 404 error on requests got 200 OK previously.
The requests my app gets, since it serves as a proxy, are with absolute urls in the request lines like POST http://example.com/test HTTP/1.1. When I'm using the development server, this request is handled by the function registered under /test normally, something like:
#app.route('/test', methods=['GET', 'POST'])
def handle_test():
...
and the request.url, as I checked, is http://example.com/test.
When using the other two ways, the request is handled by the error handler with code 404, and the handle_test() function is never invoked. The request.url, which seems to cause the problem, is http://example.com/http://example.com/test, definitely not what I want.
So I want to know:
What changed the url to the wrong one, and when did this happen.
Why the app behaves differently on default development server and servers like tornado.
Of course, how to get rid of this problem.
Thanks!
Tornado does not currently support proxy-style requests; see https://github.com/tornadoweb/tornado/issues/1036
Tornado's WSGIContainer is also a poor choice for proxies because of its single-threaded concurrency model (see http://www.tornadoweb.org/en/stable/wsgi.html#tornado.wsgi.WSGIContainer). Even if the aforementioned bug were fixed, your proxy would perform poorly. I recommend either using a multithreaded WSGI server (like gunicorn or uwsgi, although I don't know whether they support proxy-style requests) or rewriting the proxy as a native Tornado app (without flask) to take advantage of asynchronous features.

How to have one Flask app listen on two different ports?

Is it possible to have a single flask app with routes on two different ports? My Flask app needs to listen for webhooks and due to some security biz it can't receive foreign POST requests on the default port. Is it possible to do something like this?
#app.route('/hook/<sourcename>', methods=["POST"], port=5051)
def handle_hook(sourcename):
print 'asdf'
If you don't need any socket code inside C plugins, gevent could help, e.g. with
import gevent
from gevent.pywsgi import WSGIServer
app = Flask(__name__)
https_server = WSGIServer((HOST, HTTPS_PORT), app, keyfile=PRIVKEY, certfile=CERT)
https_server.start()
http_server = WSGIServer((HOST, HTTP_PORT), app)
http_server.start()
while True:
gevent.sleep(60)
A server by default only listens to a single port. Wouldn't it make more sense, since the additional port requires additional functionality, to implement a front-end server on the second port that proxies the POST request locally? There are many well-documented ways to do this such as this one

Python Web Server

I want a simple python web server for the following use case:
I want to write a simple server that will accept HTTP requests from my application running on Google App Engine.
The server will accept HTTP requests, and then send iphone notifications. (Basically, I need this extra server to account for the lack of socket support in google app engine).
I guess I need the server to be able to maintain this persistent connection with Apple's Push Notification Service. So I'll need to have some sort of thread always open for this. So I need some sort of web server that can accept the request pass it off to the other thread with the persistent connection to APNS.
Maybe multiple processes and one of pythons queuing tools to communicate between them? Accept the HTTP request, then enqueue a message to the other process?
I was wondering what someone with a bit of experience would suggest. I'm starting to think that maybe even writing my own simple server is a good option (http://fragments.turtlemeat.com/pythonwebserver.php).
One option would be the (appropriately named) SimpleHTTPServer, which is part of the Python standard library. Another, more flexible but more complicated option would be to write your server in Twisted.
I've been writing simple http servers using gevent and bottle -- an example:
#!/usr/bin/env python
import gevent.monkey
gevent.monkey.patch_all()
import bottle
bottle.debug(True)
import gevent.wsgi
from bottle import route, run, request, response, static_file, abort
#route('/echo')
def echo():
s = request.GET.get('s', 'o hai')
return '<html><head><title>echo server</title></head><body>%s</body></html>\r\n' % (s)
#route('/static/:filename')
def send_static(filename):
root = os.getcwd() + '/static'
return static_file(filename, root=root)
if __name__ == '__main__':
app = bottle.app()
wsgi_server = gevent.wsgi.WSGIServer(('0.0.0.0', 8000), app)
print 'Starting wsgi search on port 8000'
wsgi_server.serve_forever()
So you could write a simple server that sticks a job into a Queue (see gevent.queue) and have another worker greenlet that handles reading requests from the queue and processing them...

Categories

Resources