I'm running flask restx behind gunicorn and apache. My team only gets one server for all our tools so it's kind of necessary.
But in order to work w/ port 443 and https, I'm having to proxy my requests through apache and gunicorn. Apache config:
<VirtualHost *:443>
ServerName webdev02.mycompany.com
## Vhost docroot
DocumentRoot "/etc/httpd/htdocs"
<Directory "/etc/httpd/htdocs">
Options Indexes FollowSymLinks MultiViews
AllowOverride All
Require all granted
</Directory>
## Logging
ErrorLog "/var/log/httpd/httpd_error_log"
ServerSignature Off
CustomLog "/var/log/httpd/httpd_access_log" "mainserver"
## Server aliases
ServerAlias webdev02.mycompany.com
## Custom fragment
## Custom fragment
SetEnvIf X-Forwarded-For "^.*\..*\..*\..*" forwarded
CustomLog "/var/log/httpd/httpd_access_log" combined env=!forwarded
CustomLog "/var/log/httpd/httpd_access_log" proxy env=forwarded
<Location "literally 11 other applications">
RequestHeader set X-Forwarded-Port 443
ProxyPass http://127.0.0.1:80##/
</Location>
<Location /my_application>
ProxyPass http://127.0.0.1:8082/
</Location>
<Location /swaggerui> # this has to be done to find the swaggerui page
ProxyPass http://127.0.0.1:8082/swaggerui
</Location>
<Location /swagger.json> # because my_application represents the project running on port 8082, I have to redirect here to retrieve the swagger.json file
ProxyPass http://webdev02.mycompany.com/my_application/swagger.json
</Location>
<Location /hosts/> # this is the start of my problems
ProxyPass http://webdev02.mycompany.com/my_application/hosts/
</Location>
SetEnv HTTPS On
</VirtualHost>
Flask code:
#main.py
from flask import Flask
from api_model import api
from api_view import namespace
from werkzeug.middleware.proxy_fix import ProxyFix
app = Flask(__name__)
app.wsgi_app = ProxyFix(app.wsgi_app, x_proto=1, x_port=1, x_for=1, x_host=1, x_prefix=1)
api.init_app(app)
api.add_namespace(namespace)
#api_view.py
from flask import request
from flask_restx import Namespace, Resource
from api_controller import ApiController
from api_model import host_get_model, host_put_model_send, host_put_model_return, host_fail_model
controller = ApiController()
namespace = Namespace('hosts', 'host endpoints')
@namespace.route('/<vmname>')
class Host(Resource):
"""Read, update and delete a specific host"""
# @namespace.response(204, 'host not found')
@namespace.response(500, 'Internal Server error')
@namespace.marshal_with(host_get_model, mask='')
def get(self, vmname):
"""Get host information"""
arguments = {"vmname": vmname}
result, status_code = controller.get_host_from_db(arguments)
return result, status_code
@namespace.route('/')
class Host(Resource):
@namespace.expect(host_put_model_send, validate=True)
@namespace.marshal_with(host_put_model_return, mask='')
def put(self):
"""Update host information"""
data = request.json
arguments = {"vmname": data["vmname"], "patchwindow": data["PatchWindow"]}
result, status_code = controller.update_host_from_db(arguments)
return result, status_code
#api_model.py
from flask_restx import fields, Api
api = Api(title="My_API", description="testing", doc="/")
host_get_model = api.model('host_get', {
'vmname': fields.String(
required=True,
example='localhost',
description='Fully Qualified Domain Name of server'
),
'OS': fields.String(
readonly=True,
example='Linux',
description='OS Type. Currently just Linux is available'
),
'PatchWindow': fields.String(
readonly=True,
example='Mon_1800',
description='Current PatchWindow'
)
})
A curl requests works like so:
curl -X 'GET' \
'https://webdev02.mycompany.com/my_application/hosts/myserver.mycompany.com' \
-H 'accept: application/json'
{"vmname": "myserver.mycompany.com", "OS": "Red Hat Enterprise Linux 8", "PatchWindow": "1_Mon_AM_6"}
the problem: my swagger page does not recognize that it is behind Apache and Gunicorn. When I go to my swagger doc page, select that same endpoint above and hit execute, it outputs the CURL like this:
curl -X 'GET' \
'https://webdev02.mycompany.com/hosts/myserver.mycompany.com' \
-H 'accept: application/json'
What do I need to do to get my swagger example to match the actual location I'm creating w/ Apache?