Для моего хобби-проекта я пытался полностью преобразовать веб-страницу в 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"}
в разделе «Запрос полезной нагрузки», так что, кажется, работает нормально.
В настройках прокси:
<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