Здравствуйте! Я занимаюсь разработкой веб-приложения в React, которое получает данные SSE от сервера Express с Nginx.
SERVER. JS
const express = require('express');
const bodyParser = require('body-parser');
const cors = require('cors');
const crypto = require('crypto');
const app = express();
var lastClientRes = null;
function eventsHandler(req, res, next) {
const headers = {
'Content-Type': 'text/event-stream',
'Connection': 'keep-alive',
'Cache-Control': 'no-cache'
};
res.writeHead(200, headers);
const clientId = Date.now();
const newClient = {
id: clientId,
nonce: null,
cart: null,
res
};
requests.push(newClient);
const data = `data: ${JSON.stringify({client: clientId})}\n\n`;
res.write(data);
req.on('close', () => {
console.log(`${clientId} Connection closed`);
clients = clients.filter(c => c.id !== clientId);
});
}
function sendEventsToAll(newNest) {
clients.forEach(c => c.res.write(`data: ${JSON.stringify(newNest)}\n\n`))
}
async function addCart(req, res) {
const newCart = req.body;
requests.forEach(r => {
if(newCart.client == r.id){
var nonce = crypto.randomBytes(16).toString('base64');
r.nonce = nonce;
r.cart = newCart.cart;
r.res.write(`data: ${JSON.stringify({nonce: nonce})}\n\n`);
}
})
}
async function addCart(req, res) {
const newCart = req.body;
requests.forEach(r => {
if(newCart.client == r.id){
var nonce = crypto.randomBytes(16).toString('base64');
r.nonce = nonce;
r.cart = newCart.cart;
r.res.write(`data: ${JSON.stringify({nonce: nonce})}\n\n`);
}
})
}
async function confirmCart(req, res){
var nonce = req.body.nonce;
var found = -1;
requests.forEach((item, i) => {
if(item.nonce == nonce){
found = i;
return;
}
});
if(found)
{
console.log("OK");
requests[found].res.write(`data: ${JSON.stringify({confirm: true})}\n\n`);
}
}
app.use(cors());
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({extended: false}));
app.post('/addCart', addCart);
app.post('/confirmCart', confirmCart);
app.get('/events', eventsHandler);
app.get('/status', (req, res) => res.json({clients: clients.length}));
const PORT = 3001;
let requests= [];
let clients = [];
let nests = [];
app.listen(PORT, () => console.log(`SSE service listening on port ${PORT}`));
ИНДЕКС: JS
import React from 'react';
import ReactDOM from 'react-dom';
import axios from 'axios';
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
jsonCart: "",
cartNonce: "",
clientId: "",
cartConfirmed: false,
cart: Array(),
timerId: null,
listening: false,
cartConfermato: ""
};
}
buy(){
if (!this.state.listening) {
const events = new EventSource('https://api.myDomain.com/events', );
events.onmessage = (event) => {
const parsedData = JSON.parse(event.data);
console.log(event.data);
if(parsedData.client != null)
{
this.setState({
clientId: parsedData.client,
});
this.sendCart();
}
if(parsedData.nonce != null)
this.setState({
cartNonce: parsedData.nonce,
});
if(parsedData.confirm == true)
this.setState({
cartNonce: "",
cartConfermato: "Il carrello è stato confermato!"
});
};
this.setState({
listening: true
});
}
}
sendCart(){
var cart = JSON.stringify(this.state.cart.slice());
this.setState({
jsonCart: cart
});
axios.post(`https://api.myDomain.com/addCart`, {client: this.state.clientId, cart: cart});
}
*** ... ***
const events = новый EventSource ('https://api.myDomain.com/events',);
ax ios .post (https://api.myDomain.com/addCart
, {client: this.state.clientId, cart: cart});
В http все работает отлично, но если я установлю https, генерирующий сертификаты с помощью certbot, я больше не получу «события» от express server.
Единственные ошибки, которые появляются в консоли chrome, это
Я заменил sub.domain своим доменом
Эти ошибки появляются через несколько минут после первый запрос
GET https://sub.domain.com/events net::ERR_INCOMPLETE_CHUNKED_ENCODING 200 (OK)
2sub.domain.com/addCart:1 POST https://sub.domain.com/addCart 504 (Gateway Time-out)
(index):1 Access to XMLHttpRequest at 'https://sub.domain.com/addCart' from origin 'https://example.com' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
createError.js:16 Uncaught (in promise) Error: Network Error
at e.exports (createError.js:16)
at XMLHttpRequest.p.onerror (xhr.js:83)
e.exports @ createError.js:16
p.onerror @ xhr.js:83
error (async)
(anonymous) @ xhr.js:80
e.exports @ xhr.js:12
e.exports @ dispatchRequest.js:50
Promise.then (async)
u.request @ Axios.js:61
r.forEach.u.<computed> @ Axios.js:86
(anonymous) @ bind.js:9
value @ index.js:156
state.listening.EventSource.onmessage @ index.js:121
index.js:114 {"client":1579885346578}
index.js:150 send
sub.domain.com/events:1 GET https://sub.domain.com/events net::ERR_INCOMPLETE_CHUNKED_ENCODING 200 (OK)
2sub.domain.com/addCart:1 POST https://sub.domain.com/addCart net::ERR_ABORTED 504 (Gateway Time-out)