<html>
<head>
    <meta name="viewport" content="width=device-width,initial-scale=1">
    <title>OctoPrint Reverse Proxy Test</title>

    <link rel="shortcut icon" href="{{ url_for('static', filename='img/tentacle-32x32.png') }}">
    <link rel="mask-icon" href="{{ url_for('static', filename='img/mask.svg') }}" color="#56BE37">
    <link rel="mask-icon-theme" href="{{ url_for('static', filename='img/mask-theme.svg') }}" color="#56BE37">
    <link rel="apple-touch-icon" sizes="114x114" href="{{ url_for('static', filename='img/apple-touch-icon-114x114.png') }}">
    <link rel="apple-touch-icon" sizes="144x144" href="{{ url_for('static', filename='img/apple-touch-icon-144x144.png') }}">

    <!-- le CSS -->

    <link rel="stylesheet" href="{{ url_for("static", filename="css/bootstrap.min.css") }}">
    <link rel="stylesheet" href="{{ url_for("static", filename="css/bootstrap-responsive.min.css") }}">
    <link rel="stylesheet" href="{{ url_for("static", filename="vendor/font-awesome-5.15.1/css/all.min.css") }}">
    <link rel="stylesheet" href="{{ url_for("static", filename="vendor/font-awesome-5.15.1/css/v4-shims.min") }}">

    {% for url in theming %}
        <link rel="stylesheet" href="{{ url|e }}">
    {% endfor %}

    <!-- le javascript -->

    <script>
        var BASE_URL = "{{ url_for('index') }}";

        var CLIENT_IP = "{{ client_ip|e }}";
        var SERVER_PROTOCOL = "{{ server_protocol|e }}";
        var SERVER_NAME = "{{ server_name|e }}";
        var SERVER_PORT = {{ server_port|e }};
        var SERVER_PATH = "{{ server_path|e }}";
        var COOKIE_SUFFIX = "{{ cookie_suffix|e }}";
    </script>
    <script src="{{ url_for("static", filename="js/lib/jquery/jquery.min.js") }}"></script>
    <script src="{{ url_for("static", filename="js/lib/knockout.js") }}"></script>
    <script src="{{ url_for("static", filename="js/lib/bootstrap/bootstrap.js") }}"></script>
    <script src="{{ url_for("static", filename="js/lib/lodash.min.js") }}"></script>
    <script src="{{ url_for("static", filename="js/lib/sprintf.min.js") }}"></script>

    {% assets "js_client" %}
        <script type="text/javascript" src="{{ ASSET_URL }}"></script>
    {% endassets %}

    <script src="{{ url_for("static", filename="js/app/helpers.js") }}"></script>
    <script src="{{ url_for("static", filename="js/reverse_proxy_test/reverse_proxy_test.js") }}"></script>
</head>
<body>
    <div id="navbar" class="navbar navbar-inverse navbar-static-top">
        <div class="navbar-inner">
            <span class="brand">OctoPrint Reverse Proxy Test</span>
        </div>
    </div>
    <div id="reverse_proxy_test" class="container" style="padding-top: 1em">
        <div class="alert alert-error" data-bind="visible: !cookieSuffixMatch">
            <strong>Warning!</strong> The used cookie suffix doesn't match between client and server. That means that logging
            into OctoPrint's UI won't work properly. Please check your configuration and fix it.
        </div>

        <p>
            This page helps you identify issues in your reverse proxy configuration. It will show you information about
            some of the variables that OctoPrint uses to set cookies and generate fully qualified URLs. If you see
            any mismatches highlighted in red below, that means that something is not configured properly and you
            need to fix it.
        </p>

        <p>
            The table also shows you the client IP that your server saw you as. Make sure that this client IP is what
            OctoPrint should be seeing, and not for example your reverse proxy itself.
        </p>

        <p>
            For each variable, information is displayed what influences the value the server sees and thus where to
            start debugging in case of any observed mismatches.
        </p>

        <table class="table table-bordered table-hover">
            <thead>
                <th>Variable</th>
                <th>Source</th>
                <th>Client</th>
                <th>Server</th>
            </thead>
            <tr>
                <td>Client IP</td>
                <td><code>X-Forwarded-For</code></td>
                <td>-</td>
                <td>{{ client_ip|e }}</td>
            </tr>
            <tr data-bind="css: { success: serverProtocolMatch, error: !serverProtocolMatch }">
                <td>Protocol</td>
                <td><code>X-Forwarded-Protocol</code>, <code>X-Scheme</code> or config</td>
                <td data-bind="text: serverProtocol"></td>
                <td>{{ server_protocol|e }}</td>
            </tr>
            <tr data-bind="css: { success: serverNameMatch, error: !serverNameMatch }">
                <td>Host</td>
                <td><code>X-Forwarded-Host</code>, <code>Host</code>, <code>X-Forwarded-Server</code> or config</td>
                <td data-bind="text: serverName"></td>
                <td>{{ server_name|e }}</td>
            </tr>
            <tr data-bind="css: { success: serverPortMatch, error: !serverPortMatch }">
                <td>Port</td>
                <td><code>X-Forwarded-Host</code>, <code>Host</code>, <code>X-Forwarded-Port</code>, <code>X-Forwarded-Protocol</code>, <code>X-Scheme</code> or config</td>
                <td data-bind="text: serverPort"></td>
                <td>{{ server_port|e }}</td>
            </tr>
            <tr data-bind="css: { success: serverPathMatch, error: !serverPathMatch }">
                <td>Path</td>
                <td><code>X-Script-Name</code> or config</td>
                <td data-bind="text: serverPath"></td>
                <td>{{ server_path|e }}</td>
            </tr>
            <tr data-bind="css: { success: cookieSuffixMatch, error: !cookieSuffixMatch }">
                <td>Cookie Suffix</td>
                <td>Built from port & path</td>
                <td data-bind="text: cookieSuffix"></td>
                <td>{{ cookie_suffix|e }}</td>
            </tr>
        </table>

        {% if authenticated %}
            <p>
                OctoPrint received the following <strong>request headers</strong> from your client that were used to determine the above values:
            </p>

            <ul>
                {% for key, value in headers.items() %}
                    <li><code>{{ key|e }}</code>: <code>{{ value|e }}</code></li>
                {% endfor %}
            </ul>

            <p>
                Your server side Client IP was determined to be {{ client_ip|e }}. Your <code>X-Forwarded-For</code> header
                {% if headers["X-Forwarded-For"] %} (<code>{{ headers["X-Forwarded-For"]|e }}</code>){% endif %} might
                have influenced that. Make sure that this is the IP that OctoPrint should be seeing. It will be the right most
                IP in the <code>X-Forwarded-For</code> header that is not among your <strong>configured trusted downstreams</strong>:
            </p>

            <ul>
                {% for host in trusted_proxies %}
                    <li><code>{{ host|e }}</code></li>
                {% endfor %}
            </ul>
        {% else %}
            <p>
                To receive more information about the request headers that OctoPrint received, please
                <a href="{{ url_for("reverse_proxy_test", authenticated="") }}">request the authenticated version of this page</a>.
                Note that this will only work if the above settings are reporting green across the board.
            </p>
        {% endif %}

        <p>
            Please refer to <a href="https://faq.octoprint.org/reverse-proxy" target="_blank" rel="noopener noreferrer">the Reverse Proxy FAQ entry</a>
            for information on correct configuration and examples.
        </p>

    </div>

</body>
</html>
