rp346
rp346

Reputation: 7028

nginx to flask doesn't preserve path

With Nginx I am forwarding request to flask app to serve some cert files.

custom_list.html

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Files</title>
        <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css"
              integrity="sha384-1q8mTJOASx8j1Au+a5WDVnPi2lkFfwwEAa8hDDdjZlpLegxhjVME1fgjWPGmkzs7" crossorigin="anonymous">

        <style type="text/css">
            table {
                font-family: arial, sans-serif;
                border-collapse: collapse;
                width: 100%;
            }

            td, th {
                border: 1px solid #dddddd;
                text-align: left;
                padding: 8px;
            }

            tr:nth-child(even) {
                background-color: #dddddd;
            }
        </style>

    </head>
    <body>

    <div class="container">

        <div class="row">
            <div align="center" class="col-lg-12">
                <h2 class="page-header">Files</h2>
            </div>
            <table>
                <tr>
                    <th>Name</th>
                    <th>Expiry</th>
                </tr>

                {% for file in files %}
                <tr>
                    <td><a href=" {{ url_for('send_image',filename=file.name) }}">{{ file.name }}</a></td>
                    <td>{{ file.exp }}</td>
                    <td></td>
                </tr>

                {% endfor %}
            </table>
        </div>
    </div>
    {% if error %}
    <div class="alert">
        <strong>Error : </strong> {{ error }}
    </div>
    {% endif %}
    </div>
    <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js"
            integrity="sha384-0mSbJDEHialfmuBBQP6A4Qrprq5OVfW37PRR3j5ELqxss1yVqOtnepnHVP9aJ7xS"
            crossorigin="anonymous"></script>
    </body>
    </html>

app.py

    import datetime
    import os
    import os.path as op
    from OpenSSL import crypto as c
    from flask import Flask, render_template, send_from_directory

    app = Flask(__name__, static_folder='')


    @app.route('/', methods=['Get', 'POST'])
    def index():
        files_details = []
        for base, dirs, files in os.walk('files'):
            for file in files:
                if file.split(".")[-1] == "crt" or file.split(".")[-1] == "base":
                    f = open("files/base.crt", "r")
                    print()
                    cert = c.load_certificate(c.FILETYPE_PEM, f.read())
                    exp = datetime.datetime.strptime(cert.get_notAfter().decode("utf-8"), "%Y%m%d%H%M%SZ").strftime(
                        "%Y-%m-%d-%H:%M:%S")
                    files_details.append({"name": file,
                                          "exp": exp})
                else:
                    files_details.append({"name": file, "exp": "N/A"})

            for fil in files_details:
                print(fil.get('name'))

            return render_template("custom_list.html", files=files_details, test="test")


    @app.route('/flask/files/<filename>')
    def send_image(filename):
        return send_from_directory(f"files/", filename)


    if __name__ == '__main__':
        app.run(host='0.0.0.0', port=5000, debug=True)

Following is Nginx Config

    upstream base-cert {
        server base-cert:5000;
    }

    server {
        listen         80 default_server;
        server_name    localhost;
        keepalive_timeout 70;
        gzip on;
        gzip_disable "msie6";
        gzip_vary on;
        gzip_proxied any;
        gzip_comp_level 6;
        gzip_buffers 16 8k;
        gzip_http_version 1.1;
        gzip_types text/plain text/css application/json application/x-javascript application/javascript text/xml application/xml application/xml+rss text/javascript;

        ....

        location /utility/base-cert/ {
            proxy_pass http://base-cert;
        }
    }

I am can access https://example.com/utility/base-cert. But when I click on some file to download it, path is changes in a browser to https://example.com/files/ca.crt.

It should be https://example.com/utility/base-cert/files/ca.crt

What I am missing here ?

Upvotes: 0

Views: 176

Answers (1)

Dauros
Dauros

Reputation: 10502

For a quick fix you can add the /utility/base-cert/ prefix to the endpoints, so the generated URLs will have it as well.

Or you can set the SCRIPT_NAME WSGI environment variable that sets the "root" URL of the app. However it is ignored by Flask bultin server, so you have to use a WSGI server, e.g. gunicorn:

gunicorn --env SCRIPT_NAME=/utility/base-cert --bind 0.0.0.0:5000 app:app

Upvotes: 1

Related Questions