Flask/Python/Gunicorn/Nginx WebApp 在提交 Flask WTForm 时从目标网页删除 https
Flask/Python/Gunicorn/Nginx WebApp dropping https from target web page when submitting Flask WTForm
这是我第一次在 Whosebug 上提交,希望我能提供足够的细节。
我一直在构建一个 Python/Flask 网络应用程序,大致基于 博客中使用的框架
米格尔·格林伯格
它在我的 PyCharm IDE 中运行良好,问题是当我在 Flask 服务器上使用 Gunicorn 和 NginX 将它部署到 Oracle VirtualBox 上的 ubuntu 服务器时。
Web 应用程序由 10 个 pages/templates 组成,当在 Virtulbox 上部署和 运行 时,我可以在我的主机浏览器上很好地浏览应用程序,直到我提交一个 FlaskForm,然后应该 return 包含所需数据的结果页面。
它应该 return https://127.0.0.1:3000/results 但是 return 只是 http:
http://127.0.0.1:3000/results
(https 已降为 http)
和结果
400 错误请求
纯 HTTP 请求已发送到 HTTPS 端口
nginx/1.18.0 (Ubuntu)
这个错误是不言自明的,我知道它可能在 nginx 配置中的某处我不知道的地方(我试图解决这个问题一周左右)
/etc/nginx/sites-enabled/highceesdev:
server {
# listen on port 80 (http)
listen 80;
server_name _;
location / {
# redirect any requests to the same URL but on https
return 301 https://$host$request_uri;
}
}
server {
# listen on port 443 (https)
listen 443 ssl;
server_name _;
# location of the self-signed SSL certificate
ssl_certificate /home/ubuntu2/HighCees/HighCeesDev/certs/cert.pem;
ssl_certificate_key /home/ubuntu2/HighCees/HighCeesDev/certs/key.pem;
# write access and error logs to /var/log
access_log /var/log/highceesdev_access.log;
error_log /var/log/highceesdev_error.log;
location / {
# forward application requests to the gunicorn server
proxy_pass http://localhost:8000;
proxy_redirect off;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
location /static {
# handle static files directly, without forwarding to the application
alias /home/ubuntu2/HighCees/HighCeesDev/app/static;
expires 30d;
}
}
如果相关,进一步代码如下。
正在提交的 FlaskForm 的定义是
HighCeesDev/app/forms.py:
....
class CreateSong2(FlaskForm):
startdate = DateField('Start Date', default=(datetime.today()-timedelta(90)),format='%Y-%m-%d',validators=(validators.data_required(),))
enddate = DateField('End Date', default=datetime.today(),format='%Y-%m-%d', validators=(validators.data_required(),))
city = RadioField(choices=[('Wellington', 'Wellington'), ('Auckland', 'Auckland'),('Christchurch', 'Christchurch'), ('Dunedin', 'Dunedin')])
submit = SubmitField('Submit')
...
CreateSong2(FlaskForm) 的路由定义和结果
HighCeesDev/app/routes.py:
@app.route('/create_song2',methods=['GET','POST'])
def create_song2():
latedate = Song.query.order_by(Song.date.desc()).first()
startdate = Song.query.order_by(Song.date.asc()).first()
convertedlatedate1=latedate.date
convertedlatedate2 = convertedlatedate1.strftime("%d/%m/%Y")
convertedstartdate1=startdate.date
convertedstartdate2 = convertedstartdate1.strftime("%d/%m/%Y")
form = CreateSong2()
if form.validate_on_submit():
session['startdate'] = form.startdate.data
session['enddate'] = form.enddate.data
session['shcity'] = form.city.data
shcity = form.city.data
purge_files()
return redirect(url_for('results'))
return render_template('create_song2.html',form=form, latedate=latedate, startdate=startdate,convertedlatedate2=convertedlatedate2, convertedstartdate2=convertedstartdate2)
和
@app.route('/results',methods=['GET','POST'])
def results():
startdate = session['startdate']
endate= session['enddate']
shcity = session['shcity']
form=Results()
startedate = extract_date_sequel(startdate)
finishedate = extract_date_sequel(endate)
song = Song.query.filter(Song.date <= finishedate,Song.date >= startedate,Song.city==shcity).order_by(Song.date.asc())
song2 = Song.query.with_entities(Song.high_temp).filter(Song.date <= finishedate,Song.date >= startedate,Song.city==shcity).order_by(Song.date.asc())
if not check_song_query(song2):
print("check_song_query says its False :-(!!")
flash("No data in that query :-(")
return redirect(url_for('create_song2'))
else:
print("check_song_query says its True!!")
print("song is: ", type(song))
print("song2 is: ",type(song2))
a = []
for i in song2:
stringy = ''
stringy = stringy.join(i._data)
a.append(stringy)
print(type(a))
print(a)
songfile = SongFileEvent.query.all()
dtf = date_time_file_wav()
record = SongFileEvent(song_file_name=dtf)
db.session.add(record)
db.session.commit()
testy2(a)
daft = SongFileEvent.query.order_by(SongFileEvent.id.desc()).first()
songfile = SongFileEvent.query.all()
now = time.time()
purge_files_2(now)
print("purge files was called")
#convert_numbers_to_notes(a)
return render_template('results.html',title='Home', song=song, songfile=songfile, daft=daft)
如果有帮助,希望提供更多详细信息。
非常感谢
帕特
在您的部署中,您的视图是 运行 在 http 请求的上下文中 - http://localhost:8000
和 url_for
将 return URL 与 'http' 协议.
您需要使用特定的 configuration settings 设置 Flask 实例。我发现以下两个设置可以解决此类问题:
一个简单的例子。
# app/config.py
class Config(object):
# common configurations
SECRET_KEY = 'XXXXXXX'
MAX_CONTENT_LENGTH = 32 * 1024 * 1024
### more settings
class DevelopmentConfig(Config):
# specific configurations
SERVER_NAME = "example.local:5072"
PREFERRED_URL_SCHEME = 'http'
### more settings
class ProductionConfig(Config):
# specific configurations
SERVER_NAME = "example.com"
PREFERRED_URL_SCHEME = 'https'
### more settings
# app/__init__.py
def create_app():
app = App(__name__)
# APP_SETTINGS is an environment variable either set to:
# export APP_SETTINGS=app.config.DevelopmentConfig
# or
# export APP_SETTINGS=app.config.ProductionConfig
app.config.from_object(os.environ['APP_SETTINGS'])
### more setup
return app
Nginx 代理设置
location / {
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Real-IP $remote_addr;
proxy_redirect off;
proxy_pass http://localhost:8000;
proxy_set_header X-Sendfile-Type X-Accel-Redirect;
}
这是我第一次在 Whosebug 上提交,希望我能提供足够的细节。
我一直在构建一个 Python/Flask 网络应用程序,大致基于 博客中使用的框架 米格尔·格林伯格
它在我的 PyCharm IDE 中运行良好,问题是当我在 Flask 服务器上使用 Gunicorn 和 NginX 将它部署到 Oracle VirtualBox 上的 ubuntu 服务器时。
Web 应用程序由 10 个 pages/templates 组成,当在 Virtulbox 上部署和 运行 时,我可以在我的主机浏览器上很好地浏览应用程序,直到我提交一个 FlaskForm,然后应该 return 包含所需数据的结果页面。
它应该 return https://127.0.0.1:3000/results 但是 return 只是 http: http://127.0.0.1:3000/results
(https 已降为 http)
和结果
400 错误请求
纯 HTTP 请求已发送到 HTTPS 端口
nginx/1.18.0 (Ubuntu)
这个错误是不言自明的,我知道它可能在 nginx 配置中的某处我不知道的地方(我试图解决这个问题一周左右)
/etc/nginx/sites-enabled/highceesdev:
server {
# listen on port 80 (http)
listen 80;
server_name _;
location / {
# redirect any requests to the same URL but on https
return 301 https://$host$request_uri;
}
}
server {
# listen on port 443 (https)
listen 443 ssl;
server_name _;
# location of the self-signed SSL certificate
ssl_certificate /home/ubuntu2/HighCees/HighCeesDev/certs/cert.pem;
ssl_certificate_key /home/ubuntu2/HighCees/HighCeesDev/certs/key.pem;
# write access and error logs to /var/log
access_log /var/log/highceesdev_access.log;
error_log /var/log/highceesdev_error.log;
location / {
# forward application requests to the gunicorn server
proxy_pass http://localhost:8000;
proxy_redirect off;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
location /static {
# handle static files directly, without forwarding to the application
alias /home/ubuntu2/HighCees/HighCeesDev/app/static;
expires 30d;
}
}
如果相关,进一步代码如下。
正在提交的 FlaskForm 的定义是 HighCeesDev/app/forms.py:
....
class CreateSong2(FlaskForm):
startdate = DateField('Start Date', default=(datetime.today()-timedelta(90)),format='%Y-%m-%d',validators=(validators.data_required(),))
enddate = DateField('End Date', default=datetime.today(),format='%Y-%m-%d', validators=(validators.data_required(),))
city = RadioField(choices=[('Wellington', 'Wellington'), ('Auckland', 'Auckland'),('Christchurch', 'Christchurch'), ('Dunedin', 'Dunedin')])
submit = SubmitField('Submit')
...
CreateSong2(FlaskForm) 的路由定义和结果 HighCeesDev/app/routes.py:
@app.route('/create_song2',methods=['GET','POST'])
def create_song2():
latedate = Song.query.order_by(Song.date.desc()).first()
startdate = Song.query.order_by(Song.date.asc()).first()
convertedlatedate1=latedate.date
convertedlatedate2 = convertedlatedate1.strftime("%d/%m/%Y")
convertedstartdate1=startdate.date
convertedstartdate2 = convertedstartdate1.strftime("%d/%m/%Y")
form = CreateSong2()
if form.validate_on_submit():
session['startdate'] = form.startdate.data
session['enddate'] = form.enddate.data
session['shcity'] = form.city.data
shcity = form.city.data
purge_files()
return redirect(url_for('results'))
return render_template('create_song2.html',form=form, latedate=latedate, startdate=startdate,convertedlatedate2=convertedlatedate2, convertedstartdate2=convertedstartdate2)
和
@app.route('/results',methods=['GET','POST'])
def results():
startdate = session['startdate']
endate= session['enddate']
shcity = session['shcity']
form=Results()
startedate = extract_date_sequel(startdate)
finishedate = extract_date_sequel(endate)
song = Song.query.filter(Song.date <= finishedate,Song.date >= startedate,Song.city==shcity).order_by(Song.date.asc())
song2 = Song.query.with_entities(Song.high_temp).filter(Song.date <= finishedate,Song.date >= startedate,Song.city==shcity).order_by(Song.date.asc())
if not check_song_query(song2):
print("check_song_query says its False :-(!!")
flash("No data in that query :-(")
return redirect(url_for('create_song2'))
else:
print("check_song_query says its True!!")
print("song is: ", type(song))
print("song2 is: ",type(song2))
a = []
for i in song2:
stringy = ''
stringy = stringy.join(i._data)
a.append(stringy)
print(type(a))
print(a)
songfile = SongFileEvent.query.all()
dtf = date_time_file_wav()
record = SongFileEvent(song_file_name=dtf)
db.session.add(record)
db.session.commit()
testy2(a)
daft = SongFileEvent.query.order_by(SongFileEvent.id.desc()).first()
songfile = SongFileEvent.query.all()
now = time.time()
purge_files_2(now)
print("purge files was called")
#convert_numbers_to_notes(a)
return render_template('results.html',title='Home', song=song, songfile=songfile, daft=daft)
如果有帮助,希望提供更多详细信息。
非常感谢
帕特
在您的部署中,您的视图是 运行 在 http 请求的上下文中 - http://localhost:8000
和 url_for
将 return URL 与 'http' 协议.
您需要使用特定的 configuration settings 设置 Flask 实例。我发现以下两个设置可以解决此类问题:
一个简单的例子。
# app/config.py
class Config(object):
# common configurations
SECRET_KEY = 'XXXXXXX'
MAX_CONTENT_LENGTH = 32 * 1024 * 1024
### more settings
class DevelopmentConfig(Config):
# specific configurations
SERVER_NAME = "example.local:5072"
PREFERRED_URL_SCHEME = 'http'
### more settings
class ProductionConfig(Config):
# specific configurations
SERVER_NAME = "example.com"
PREFERRED_URL_SCHEME = 'https'
### more settings
# app/__init__.py
def create_app():
app = App(__name__)
# APP_SETTINGS is an environment variable either set to:
# export APP_SETTINGS=app.config.DevelopmentConfig
# or
# export APP_SETTINGS=app.config.ProductionConfig
app.config.from_object(os.environ['APP_SETTINGS'])
### more setup
return app
Nginx 代理设置
location / {
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Real-IP $remote_addr;
proxy_redirect off;
proxy_pass http://localhost:8000;
proxy_set_header X-Sendfile-Type X-Accel-Redirect;
}