I'm using the following code snippet to run WSGIServer in python:
from bottle import request, Bottle, abort
app = Bottle()
.. other stuff ...
from gevent.pywsgi import WSGIServer
from geventwebsocket import WebSocketError
from geventwebsocket.handler import WebSocketHandler
server = WSGIServer(("0.0.0.0", 8080), app,
handler_class=WebSocketHandler)
server.serve_forever()
The server works fine but every time I send a request to this server, there is nothing printed out on console (the way bottle or flask do when you run their server directly). Those console logs would really help me understand what requests the browser is making. I tried inserting debug=True in several places in above code, but none seemed to work. What am I doing wrong ?
I believe you should add this line before starting the server .
app.debug = True
Related
I am using Loguru to handle the logging in my flask rest api. When testing the app locally it logs exactly as expected. When I deploy my app to my linux server running apache the logging stops. I can run the app manually on the server using python app.py and the logging works again but that just spins up the development server.
from flask import Flask
from loguru import logger
import logging
import os
class InterceptHandler(logging.Handler):
def emit(self, record):
# Retrieve context where the logging call occurred, this happens to be in the 6th frame upward
logger_opt = logger.opt(depth=6, exception=record.exc_info)
logger_opt.log(record.levelno, record.getMessage())
# create the Flask application
app = Flask(__name__)
logger.add(
'logs/events.log',
level='DEBUG',
format='{time} {level} {message}',
backtrace=True,
rotation='5 MB',
retention=9
)
app.logger.addHandler(InterceptHandler())
logging.basicConfig(handlers=[InterceptHandler()], level=20)
if __name__ == '__main__':
app.run(debug=False)
Figured out the issue. By default using the werkzeug dev server it was using the logs/events.log file. When I deployed the application to the apache server, it rerouted the logs that would have been placed here and put them in with the apache server logs
I have a Flask server-app/React client-app into which I am trying to integrate flask_socketio. I have replicated the standard introductory example from the flask_socketio docs and it works fine with my React front-end.
However, when I try to replicate the results in flask, using the exact same steps I cannot send or receive messages. I can see a client has connected in the output when I run my flask app, and in the browser console I have a console.log telling me I am connected to the server, but emit (or send) don't seem to work the way the intro example did.
I have eventlet installed, and the docs say that flask_socketio should recognize this automatically. Here are some code snippets for reference.
app/socket/__ init __.py
from flask_socketio import SocketIO
socketio = SocketIO(cors_allowed_origins='http://localhost:3000')
app/socket/socket.py
from flask_cors import cross_origin
from flask_socketio import send, emit
from . import socketio
#cross_origin
#socketio.on('connect')
def handle_connection():
print('a user has connected')
emit('mymessage', 'Hi client, I am server.') # I've tried `send` here too
#cross_origin
#socketio.on('mymessage')
def handle_message(message):
print('Message from client: ' + message)
app/__ init __.py
from flask import Flask
from flask_cors import CORS
from .socket import socketio
def create_app():
app = Flask(__name__)
# Cross Origin Resource Sharing
CORS(app)
# Socket.IO
socketio.init_app(app)
return (socketio, app)
app/app.py
from . import create_app
socketio, app = create_app()
if __name__ == '__main__':
socketio.run(app, host='localhost', port=5000)
#app.run("0.0.0.0", port=5000, threaded=True, use_reloader=False)
React component
const socket = io('http://localhost:5000');
class Figures extends React.Component {
setSocketListeners () {
socket.on('connect', () => {
console.log('connected to socket');
socket.emit('mymessage', 'Hi server, I am client.');
})
socket.on('mymessage', function(data) {
console.log('Message from server: ' + data)
})
}
componentDidMount() {
this.setSocketListeners()
}
...
Output:
terminal
* Restarting with stat
* Debugger is active!
* Debugger PIN: 216-814-307
(4089) wsgi starting up on http://127.0.0.1:5000
127.0.0.1 - - [14/Aug/2019 02:40:35] "POST /socket.io/?EIO=3&transport=polling&t=MoEsrSZ&sid=a4f73c34553f478cabde2f919b48fe98 HTTP/1.1" 200 219 0.002675
(4089) accepted ('127.0.0.1', 36512)
(4089) accepted ('127.0.0.1', 36514)
127.0.0.1 - - [14/Aug/2019 02:40:36] "GET /socket.io/?EIO=3&transport=polling&t=MoEsrSf&sid=a4f73c34553f478cabde2f919b48fe98 HTTP/1.1" 200 235 1.612156
browser
connected to socket
EDIT:
Preliminary debugging seems to suggest this is some issue with 'create_app()'. See link from #miguelgrinberg. Still no progress on how to fix the issue though.
Have enabled socketio.init_app(app, async_mode="eventlet", engineio_logger=True) and disabled debugging in flask to make sure werkzeug isn't being used.
A similar issue was related here
I think you should enable transport mode to WebSocket when opening socket on your frontend code, something like:
const socket = io('http://localhost:5000', {transports: [websocket]});
Also you need to install gevent and gevent-websocket and import socket.io-client like:
import io from 'socket.io-client/dist/socket.io';
I've implemented a working example: https://github.com/roj4s/webicami
I am a new Flask user and i have a problem. I want to redirect all url from http to https but I am having this error:
The connection was reset
This is my Flask code:
#! /usr/bin/python
# -*- coding:utf-8 -*-
from flask import *
from OpenSSL import SSL
import psycopg2
import os
from datetime import timedelta
import sys
from flask_sslify import SSLify
reload(sys)
sys.setdefaultencoding('utf8')
db_conn = psycopg2.connect("dbname=billjobs host=192.168.42.96 port=50434 user=username password=password")
app = Flask(__name__)
db = db_conn.cursor()
app.permanent_session_lifetime = timedelta(seconds=900)
sslify = SSLify(app)
app.secret_key='\xatYK\x1ba\x1dz\xa6-D\x9d\x97\x83\xfa\xcf\xcbd\xfa\xfb\x1a|\x08\x1af'
context = ('ssl.crt','ssl.key')
#app.route('/')
def pre_log():
return render_template('index.html')
if __name__ == '__main__':
app.run(host="192.168.42.186", ssl_context=context, debug=False)
If I enter directly the address https://192.168.42.186:5000 it work but with http only its not
Thanks for helping me in advance
You cannot do this using ssl_context and Werkzung (default server of Flask) now. A functionality to allow this was proposed and rejected in 2014: auto http to https redirect; citing:
That requires running another HTTP server. Werkzeug is not capable of that and IMO it's out of scope. run_simple should only be used for development anyway.
So what's going on is your Flask application calls run_simple underneath, passing ssl_context and some other variables. SSLify has no impact on your routing as long as you use ssl_context, because sole presence of this variable makes Werkzung host only using https schema. To get redirection from http to https, you need either to set up another server, listening at http and redirecting to https or migrate to other, more advanced server which allows redirection easily.
I recommend to migrate to Apache or gunicorn. Flask provides comprehensive instructions on deployment: Deployment Options. Keep in mind that built-in server of Flask (Werkzung) is not suitable for production, as authors of Flask write:
While lightweight and easy to use, Flask’s built-in server is not
suitable for production as it doesn’t scale well and by default serves
only one request at a time.
Using Apache you could redirect all http requests using VirtualHost rule, listening at 80:
<VirtualHost *:80>
ServerName mysite.example.com
DocumentRoot /usr/local/apache2/htdocs
Redirect /secure https://mysite.example.com/secure
</VirtualHost>
See more on this on Redirect Request to SSL Apache wiki.
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.
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.