Почему полезная нагрузка XMLHttpRequest не достигает сервера Node.JS после перехода на HTTPS? - PullRequest
0 голосов
/ 10 июля 2019

Для моего хобби-проекта я пытался полностью преобразовать веб-страницу в HTTPS.

Веб-страница состоит из:

  • Apache-сервер, на котором размещены HTML / JS / CSS
  • HTTP-сервер Node.JS, обрабатывающий все функции
  • Плагин Socket.IO

Все теперь на порте 443, с прокси, настроенным в Apache, отправка содержимого веб-страницы в localhost:8091, где html-файл доступен во внутренней сети, отправка содержимого Node.JS и Socket.IO в localhost:8000.

Кажется, все работает нормально, за исключением одного: полезная нагрузка от XMLHttpRequests, похоже, больше не достигает сервера Node.JS.

XMLHttpRequest:

function doHttp(content, callback, url, contentType) {

    var action;
    var doUpdate;
    if (content != null) {
        action = JSON.parse(content).action;
    }

    var xhttp = new XMLHttpRequest();
    if (url === null || url === undefined) {
        // Uses a proxy in Apache to forward url/sprinklers/node to localhost:8000 on the server
        var url = window.location.href + "node"
        doUpdate = (action != "load" && action != "checkRow");
    }

    console.log("doHttp url", url)

    xhttp.open("POST", url, true);
    if (contentType === null || contentType === undefined) {
        contentType = "application/json";
    }

    console.log("doHttp contentType", contentType)
    xhttp.setRequestHeader("Content-Type", contentType);

    xhttp.onload = function() {
        if (callback != null) {
            callback(xhttp.responseText);
        }
        if (doUpdate) {
            doDomoticz("update");
        }
    };
    xhttp.onerror = function() {
        throw xhttp.response;
    };

    xhttp.send(content);
}

После загрузки страницы эта функция вызывается с помощью:

Операторы журнала выглядят следующим образом:

doHttp url https://myUrl.com/sprinklers/node
doHttp contentType application/json

Пока все хорошо. Когда я проверяю вкладку сети в Инспекторе Chrome, я вижу {action: "load"} в разделе «Запрос полезной нагрузки», так что, кажется, работает нормально.

Screenshot of developer tools console

В настройках прокси:

<VirtualHost *:8091>
    DocumentRoot /var/www/SprinklerServer

    ErrorLog ${APACHE_LOG_DIR}/port_8091_error.log
    CustomLog ${APACHE_LOG_DIR}/port_8091_access.log combined

    DirectoryIndex sprinklers.html

#    <Directory "/var/www/SprinklerServer">
#        AuthType Basic
#        AuthName "Restricted Content"
#        AuthUserFile /var/www/SprinklerServer/.htpasswd
#        Require valid-user
#    </Directory>
</VirtualHost>
# Password disabled for testing period

<VirtualHost *:443>
    ServerName myUrl.com

    ErrorLog ${APACHE_LOG_DIR}/port_443_error.log
    CustomLog ${APACHE_LOG_DIR}/port_443_access.log combined

    SSLEngine on
    SSLCertificateFile      /etc/letsencrypt/live/myUrl.com/cert.pem
    SSLCertificateKeyFile   /etc/letsencrypt/live/myUrl.com/privkey.pem

    SSLProxyEngine on
    ProxyPreserveHost On
    ProxyRequests Off

    RewriteEngine on
    # Domoticz rule can be ignored for this question
    RewriteRule ^/domoticz$ /domoticz/ [R]
    RewriteRule ^/sprinklers/node$ /sprinklers/node/ [R]
    RewriteRule ^/sprinklers$ /sprinklers/ [R]

    # When Upgrade:websocket header is present, redirect to ws
    # Using NC flag (case-insensitive) as some browsers will pass Websocket
    RewriteCond %{HTTP:Upgrade} websocket [NC]
    RewriteCond %{HTTP:Connection} upgrade [NC]
    RewriteRule .* ws://127.0.0.1:8000/socket.io%{REQUEST_URI}  [P]

    # Domoticz Proxys can be ignored for this question
    ProxyPassMatch "^/domoticz/(.*)$" "https://127.0.0.1:444/$1"
    ProxyPassReverse "^/domoticz/(.*)$" "https://127.0.0.1:444/$1"
    ProxyPassMatch "^/sprinklers/node/(.*)$" "http://127.0.0.1:8000/$1"
    ProxyPassReverse "^/sprinklers/node/(.*)$" "http://127.0.0.1:8000/$1"
    ProxyPassMatch "^/sprinklers/(.*)$" "http://127.0.0.1:8091/$1"
    ProxyPassReverse "^/sprinklers/(.*)$" "http://127.0.0.1:8091/$1"

</VirtualHost>

(Не уверен, какой подсветкой синтаксиса здесь пользоваться. Предложения?)

Как видите, настоящая веб-страница размещена на myUrl.com/sprinklers, и я направляю все вещи Node.JS и Socket.IO через myUrl.com/sprinklers/node.

На серверном скрипте Node.JS: "

var server = http.createServer(function(request, response) {

    console.log("REQUEST")
    console.log(request.url);

    response.setHeader("Access-Control-Allow-Origin", "*");
    response.setHeader("Access-Control-Allow-Methods", "POST, GET");
    response.setHeader("Access-Control-Allow-Headers", "Content-Type");

    if (!fs.existsSync(filePath)) {
        try {
            fs.writeFileSync(filePath, JSON.stringify({data:{}}, null, 4));
        } catch (e) {
            console.error("Can't write file", e);
        }
    }
    fileString = fs.readFileSync(filePath, "utf8");

    try {
      fileJSON = JSON.parse(fileString);
    } catch(e) {
        console.error(e)
    }

    httpString = "";
    httpJSON;

    request.on("error", function(error) {

        console.error(err);


    }).on("data", function(chunk) {

        console.log("CHUNK", chunk)

        httpString += chunk;


    }).on("end", function() {

        if (httpString.length > 0) {

            console.log("HTTPSTRING", httpString)

            httpJSON = JSON.parse(httpString);

            // Call function based on action name
            if (funcs[String(httpJSON.action)] != null) {
                funcs[String(httpJSON.action)](response)

            } else {
                response.statusCode = 500;
                response.write("Received data is either corrupted, or provided action \"" + String(httpJSON.action) + "\" doesn't have a matching function.", "utf8");

            }
        }

        response.end();

    })

}).listen(8000) // Using a proxy that directs all url/node things to localhost:8000
const io = require("socket.io").listen(server)

Операторы журнала, находящиеся там, выдают только то, на каком консоли я запускаю скрипт:

REQUEST
/

CHUNK или HTTPSTRING никогда не достигаются, поэтому кажется, что он никогда не получает никаких данных. Я предполагаю, что это потому, что полезная нагрузка запроса где-то отфильтрована. Я думаю, что прокси, но я не знаю, как это проверить. Я довольно новичок в прокси и HTTPS. Мне потребовалось довольно много времени, чтобы добраться до той точки, в которой я сейчас нахожусь, что было возможно только при большом количестве проб и ошибок.

Я обычно вполне в порядке, когда выясняю причину проблемы и бьюсь столько времени, сколько потребуется, пока она не будет устранена, но на этот раз я действительно застрял. Кто-нибудь знает, что может быть причиной этой проблемы?

Recap

Веб-страница, используемая для запуска по HTTP, работала нормально. Переключился на HTTPS, поставил прокси Apache посередине. Все работает, за исключением того, что данные XMLHttpRequest не достигают сервера Node.JS

1 Ответ

0 голосов
/ 10 июля 2019

У меня был полный ответ, включая исправление, которое я думал Я нашел, но, к сожалению, это не работает.Поэтому вместо этого я просто отвечу на мой первоначальный вопрос: почему это происходит.

На самом деле все просто: я использую RewriteRule, чтобы переписать URL-адреса на случай, если они пропустят завершающий слеш.К сожалению, это не поддерживает данные POST, которые мне нужны.Так как это был широкий вопрос, сосредоточенный на том, почему, я отмечу этот ответ как окончательный и открою новый вопрос, который конкретно касается того, как изменить URL-адрес, чтобы включить косую черту без удаления данных POST.Я опубликую ссылку здесь, когда она закончится.

РЕДАКТИРОВАТЬ:

Я уже решил свой новый вопрос.Оказывается, все, что вам нужно сделать, это убедиться, что RewriteRule использует HTTP-код 307. Более подробно в другом вопросе: Как переписать URL при сохранении данных POST?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...