I am trying to build a web interface to Mock up a restful interface on networking device this networking device uses Digest Authentication and HTTPS.
I figured out how to integrate Digest Authentication into the web server but I cannot seem to find out how to get https using FLASK if you can show me how please comment on what i would need to do with the code below to make that happen.
from flask import Flask, jsonify
app = Flask(__name__)
#app.route('/')
def index():
return 'Flask is running!'
#app.route('/data')
def names():
data = {"names": ["John", "Jacob", "Julie", "Jennifer"]}
return jsonify(data)
if __name__ == '__main__':
app.run()
Don't use openssl or pyopenssl its now become obselete in python
Refer the Code below
from flask import Flask, jsonify
import os
ASSETS_DIR = os.path.dirname(os.path.abspath(__file__))
app = Flask(__name__)
#app.route('/')
def index():
return 'Flask is running!'
#app.route('/data')
def names():
data = {"names": ["John", "Jacob", "Julie", "Jennifer"]}
return jsonify(data)
if __name__ == '__main__':
context = ('local.crt', 'local.key')#certificate and key files
app.run(debug=True, ssl_context=context)
this also works in a pinch
from flask import Flask, jsonify
from OpenSSL import SSL
context = SSL.Context(SSL.PROTOCOL_TLSv1_2)
context.use_privatekey_file('server.key')
context.use_certificate_file('server.crt')
app = Flask(__name__)
#app.route('/')
def index():
return 'Flask is running!'
#app.route('/data')
def names():
data = {"names": ["John", "Jacob", "Julie", "Jennifer"]}
return jsonify(data)
#if __name__ == '__main__':
# app.run()
if __name__ == '__main__':
app.run(host='127.0.0.1', debug=True, ssl_context=context)
To run HTTPS functionality or SSL authentication in your flask application, first install "pyOpenSSL" python package
pip install pyopenssl
Next step is to create cert.pem and key.pem
openssl req -x509 -newkey rsa:4096 -nodes -out cert.pem -keyout key.pem -days 365
Copy generated cert.pem and key.pem in your flask application project
Add ssl_context=('cert.pem', 'key.pem') in app.run(), like in the example below.
from flask import Flask, jsonify
app = Flask(__name__)
#app.route("/")
def index():
return "Flask is running!"
#app.route("/data")
def names():
data = {"names": ["John", "Jacob", "Julie", "Jennifer"]}
return jsonify(data)
if __name__ == "__main__":
app.run(ssl_context=("cert.pem", "key.pem"))
The top-scoring answer has the right idea, but the API seems to have evolved so that it no longer works as when it was first written, in 2015.
In place of this:
from OpenSSL import SSL
context = SSL.Context(SSL.PROTOCOL_TLSv1_2)
context.use_privatekey_file('server.key')
context.use_certificate_file('server.crt')
I used this, with Python 3.7.5:
import ssl
context = ssl.SSLContext()
context.load_cert_chain('fullchain.pem', 'privkey.pem')
and then supplied the SSL context in the Flask.run call as it said:
app.run(…, ssl_context=context)
(My server.crt file is called fullchain.pem and my server.key is called privkey.pem. These files were supplied to me by my LetsEncrypt Certbot.)
Deploy Flask on a real web server, rather than with the built-in (development) server.
See the Deployment Options chapter of the Flask documentation. Servers like Nginx and Apache both can handle setting up HTTPS servers rather than HTTP servers for your site.
The standalone WSGI servers listed would typically be deployed behind Nginx and Apache in a proxy-forwarding configuration, where the front-end server handles the SSL encryption for you still.
For a quick n' dirty self-signed cert, you can also use flask run --cert adhoc or set the FLASK_RUN_CERT env var.
$ export FLASK_APP="app.py"
$ export FLASK_ENV=development
$ export FLASK_RUN_CERT=adhoc
$ flask run
* Serving Flask app "app.py" (lazy loading)
* Environment: development
* Debug mode: on
* Running on https://127.0.0.1:5000/ (Press CTRL+C to quit)
* Restarting with stat
* Debugger is active!
* Debugger PIN: 329-665-000
The adhoc option isn't well documented (for good reason, never do this in production), but it's mentioned in the cli.py source code.
There's a thorough explanation of this by Miguel Grinberg at Running Your Flask Application Over HTTPS.
If this webserver is only for testing and demoing purposes. You can use ngrok, a open source too that tunnels your http traffic.
Bascially ngrok creates a public URL (both http and https) and then tunnels the traffic to whatever port your Flask process is running on.
https://ngrok.com/product
It only takes a couple minutes to set up. You first have to download the software. Then run the command
./ngrok http [port number your python process is running on]
It will then open up a window in terminal giving you both an http and https url to access your web app.
Super simple:
app.py
from flask import Flask
app = Flask(__name__)
#app.route("/")
def hello():
return "Hello World!"
run:
$ openssl req -x509 -newkey rsa:4096 -nodes -out cert.pem -keyout key.pem -days 365
$ flask run --cert=cert.pem --key=key.pem
You can use mkcert to generate certificate that is trusted by browsers.
mkcert example.com "*.example.com" example.test localhost 127.0.0.1 ::1
Browser will trust all of the following domains and IPs
- "example.com"
- "*.example.com"
- "example.test"
- "localhost"
- "127.0.0.1"
- "::1"
Python Code:
from flask import Flask, jsonify
app = Flask(__name__)
#app.route("/")
def index():
return "Welcome to the Python Flask's Index!"
if __name__ == "__main__":
app.run(port=443, ssl_context=("localhost+3.pem", "localhost+3-key.pem"))
Screenshot:
Related
When I try to use the functionality that uses websockets in my application, I get this error in the console:
File "/Users/user/venv/lib/python3.7/site-packages/simple_websocket/ws.py", line 138, in __init__
raise RuntimeError('Cannot obtain socket from WSGI environment.')
RuntimeError: Cannot obtain socket from WSGI environment.
I also get this error in the browser console:
WebSocket connection to 'ws://localhost:5000/socket.io/?EIO=4&transport=websocket&sid=40NYzDgGYStMR0CEAAAJ' failed:
I tried using gevent, gevent-websocket, and eventlet, but this created other issues, and I'm not sure that I need to use gevent or eventlet for this use case.
Here's the rest of the relevant code:
__ init __.py
from flask_socketio import SocketIO
...
socketio = SocketIO()
def create_app(config_class=Config):
app = Flask(__name__)
app.config.from_object(Config)
socketio.init_app(app, cors_allowed_origins='*')
...
return app
app.py
from app import create_app, socketio
app = create_app()
if __name__ == '__main__':
socketio.run(app)
routes.py
This only accepts POST requests because I send data to this route from a Celery task
from app import socketio
...
#main_bp.route('/send_message', methods=['POST'])
def send_message():
...
socketio.emit('test_message', {'msg':'Test'}, namespace='/test')
return 'Results Sent'
index.html
var socket = io.connect('http://localhost:5000/test');
socket.on('connect', function(){
console.log('Connected to socket')
});
socket.on('test_message', function(message){
console.log('Received test message');
}
)
Note that in the browser console I'll see "Connected to socket", but not "Received test message"
You are using the simple-websocket package. This package has a list of supported web servers. The error indicates that you are using a web server that is not in the supported list.
Supported web servers are:
The Flask dev server (for development purposes only, of course)
Gunicorn
Eventlet
Gevent
From this list, it seems your only choice for a production web server is Gunicorn, since you say that eventlet/gevent won't work for your needs.
The use of Gunicorn is covered in the documentation. In that section, simple-websocket is the third option mentioned. Here is the example start up command:
gunicorn -w 1 --threads 100 module:app
Maybe you can turn on the logger and the engine.io logger. that qould give you an idea what is the issue.
don't use eventlet and gevent together. use anyone and uninstall the other.
On my laptop I can start simple flask app:
import os
import io
from flask import Flask
app = Flask(__name__)
#app.route("/")
def hello():
s = """
This is a localhost!
"""
return (s)
if __name__ == "__main__":
app.run(host='0.0.0.0', port=3000, debug=True)
And when do curl localhost:3000 on my laptop - I can get a good response.
But when I start a docker image and put same code and start it with same version of Python - it shows as running but when I do from within a docker curl localhost:3000 - do not get any response (it just hangs and nothing happens).
How to enable localhost (routing) inside docker?
Thanks.
Change your code to
app.run(host='127.0.0.1', port=3000, debug=True)
and check if localhost is defined in /etc/hosts.
I am trying to host a flask server from my windows computer so I can access it from external devices
I am using Flask/Python and have already tried a few things but can't get it to work
Tried running it on 0.0.0.0, port 33, 5000, etc. but I still can't access it this way
from flask import Flask, request, abort
app = Flask(__name__)
if __name__ == '__main__':
app.run(host='0.0.0.0', port=33)
When I then run the file I get:
Running on http://0.0.0.0:33/ (Press CTRL+C to quit)
But it isn't even running there, nor on any other way I can access it
I expect to be able to access my flask application and send requests to it by using my public IP address
What can I do here to make it work?
You have missed an important line in your code:
After the line
app = Flask(__name__)
You have to write the line:
#app.route('/')
We use the route() decorator to tell Flask what URL should trigger our function.
And then define a function that will tell what task to be performed in the web app hosted in the respective address.
The function might look something like this:
def hello_world():
return 'Hello, World!'
The complete code then will look like:
from flask import Flask
app = Flask(__name__)
#app.route('/')
def hello_world():
return 'Hello, World!'
if __name__ == '__main__':
app.run(host='0.0.0.0', port=33)
Hope this helps.
My backend is an AWS EC2 server that runs on flask, I'm trying to port over my code from http to https. I've used letsencrypt and certbot to create valid certificates. My flask backend accesses the certs and then calls the host. I tried adding SSLify after looking through other posts ( and seeing that it can be used with Flask, but it didn't change anything.
from flask_cors import CORS
from flask_sslify import SSLify
from OpenSSL import SSL
app = Flask(__name__)
CORS(app)
sslify = SSLify(app)
sslify
if __name__ == "__main__":
context = ("../../../../etc/letsencrypt/live/app.mydomain.name/fullchain.pem","../../../../etc/letsencrypt/live/app.mydomain.name/p$
app.run(host='127.0.0.1', port=5000, debug=True, ssl_context=context)
On the React frontend side, I'm using axios
axios.post('https://127.0.0.1:5000/run_query', postData, axiosConfig)
.then(function (response) {
console.log("Successful connection");
console.log(response.data);
influencerList = response.data.query_results;
console.log(influencerList);
currentComponent.setState({IL: influencerList});
})
.catch(function (error) {
console.log(error);
});
using app.run options I listed above on the backend returns
xhr.js:178 OPTIONS https://127.0.0.1:5000/run_query net::ERR_CONNECTION_REFUSED in the Google Chrome Browser Console.
I'm runnning nginx on Linux AMI. The certificates are for RehlOS/CentOS generated through letsencrypt and certbot. My Nginx error.log doesn't return anything, running the backend python file doesn't log anything anymore, like it did before going from HTTP. It just displays this:
* Running on https://ec2-34-209-86-220.us-west-2.compute.amazonaws.com:5000/ (Press CTRL+C to quit)
* Restarting with stat
I also tried changing the post URL to https://ec2-34-209-86-220.us-west-2.compute.amazonaws.com:5000/run-query instead of https://127.0.0.1:5000/run_query but got the exact same error.
I hope it's something simple, any help would be great. Thanks!
I'm using flask app factory pattern like and have this run.py file:
from app import create_app
app = create_app()
if __name__ == '__main__':
app.run(host='localhost', debug=True)
Then I run the app like this:
python run.py
But when I go to http://localhost:5000 it doesn't work.
It says:
Not Found
The requested URL was not found on the server. If you entered the URL
manually please check your spelling and try again.
What could be wrong? it works well when I have 127.0.0.1 address...
I need to run on "localhost" because I'm integrating square payments and their sandbox setup requires I make requests to their API from a 'localhost'.
Also, when I make the request in the browser, on the terminal when flask responds there is this:
127.0.0.1 - - [09/Sep/2017 00:30:45] "GET / HTTP/1.1" 404 -
127.0.0.1 - - [09/Sep/2017 00:30:45] "GET /favicon.ico HTTP/1.1" 404 -
127.0.0.1 - - [09/Sep/2017 00:30:45] "GET /favicon.ico HTTP/1.1" 404 -
So it looks like request reaches flask but flask returns 404.
Here is part of my init.py file:
# from __future__ import print_function
# import flask
from flask import Flask, render_template, url_for, redirect, flash, request, \
session, current_app, abort
import os
# flask sqlaclhemy
from sqlalchemy import func, desc, asc, or_, and_
from flask_admin import Admin, AdminIndexView
from flask_admin.contrib.sqla import ModelView
# Flask secrutiy
from flask_security import (Security, SQLAlchemyUserDatastore,
login_required, current_user)
from flask_login import LoginManager
from flask_mail import Mail
# square connect setup
import uuid
import squareconnect
from squareconnect.rest import ApiException
# from squareconnect.apis.locations_api import LocationsApi
from squareconnect.apis.transactions_api import TransactionsApi
mail = Mail()
class CustomAdminIndexView(AdminIndexView):
def is_accessible(self):
return current_user.is_authenticated and current_user.has_role('admin')
def create_app():
app = Flask(__name__)
app.config.from_object(os.environ['APP_SETTINGS'])
mail.init_app(app)
from models import db, User, Role
db.init_app(app)
user_datastore = SQLAlchemyUserDatastore(db, User, Role)
security = Security(app, user_datastore)
#app.route('/')
def home():
return render_template('home.html')
return app
the simple alternative solution is first to check if the port 5000 is avialable you can check that with this comand :
netstat -lat
find more about available port here :
if you are not obliged to use port 5000 you can try anything else you want ..
if every thing is ok that mean you have a problem with your home page , you don't have a route to '/' , that why you are getting the 404 error when you go to localhost:5000/ :
so to correct it you have 3 solution :
add the app.route('/') in your init.py file
add it directly in your run.py after creating the app (not a good way)
try to use blueprints
as you didn't provide your init.py code let add it to your run.py ,
from app import create_app
app = create_app()
#app.route('/')
def homepage():
return 'hello world'
if __name__ == '__main__':
app.run(host='localhost', port=9874)
another solution as suggest in comment is to check if 127.0.0.1 resolve to localhost find the host file by typing this command and check if you have the same line as mine :
nano /etc/hosts
and open the file :
##
# Host Database
#
# localhost is used to configure the loopback interface
# when the system is booting. Do not change this entry.
##
127.0.0.1 localhost
255.255.255.255 broadcasthost
::1 localhost
Just incase anyone on a mac runs into this issue and has trouble finding any answers (like me), I just discovered that it's because Apple Airplay Receiver runs on port 5000. Disable airplay receiver and try again.
there will be no entry as localhost in your hosts file
example host file
127.0.0.1 localhost
you can check your hosts file in following ways
for linux
sudo vi /etc/hosts
for windows
open this file C:\Windows\System32\Drivers\etc\hosts
if there is no localhost in your hosts file add and save it.
May be you need to install virtual enviroment
pip install virtualenv
does this. Hope this works
You should try switching out localhost for 0.0.0.0.
if __name__ == '__main__':
app.run(host='0.0.0.0', debug=True)
This has it serve on localhost for me.
from flask import Flask
app = Flask(__name__)
#app.route("/")
def hello():
return "Hello"
if name == "main":
app.run(host='0.0.0.0', port=9874)