Мой случай: я разрабатываю веб-приложение, в котором пользователь может получить информацию о событиях traffi c, текущем потоке трафика c и информацию о рейсах, которые недавно приземлились в определенных c аэропортах. По нескольким причинам я включил Express. js для обработки запросов от внешнего интерфейса, получения данных от соответствующего API и последующей отправки данных обратно клиенту.
ПРОБЛЕМА:
Все работает нормально в режиме локальной разработки - все вызовы API вызываются, как ожидается, данные отправляются клиенту, как и ожидалось. Другими словами, все в порядке и в развитии. В производственном режиме, однако, все не в порядке. Мои POST-маршруты (у меня есть 2 POST-маршрута) работают должным образом, но оставшийся GET-маршрут не работает. При проверке вкладки Networks в Chrome DevTools, код состояния запроса возвращает 503.
У меня есть приложение CRA (с использованием React Hooks), в котором у меня есть три компонента. Каждый из компонентов использует метод выборки для вызова конечной точки:
В FlightList. js:
import React, {useState, useEffect} from 'react';
import Wait from './Wait';
import './FlightList.scss';
export default function FlightList(props) {
const [flights, setFlights] = useState([]);
const [flightData, setflightData] = useState(false);
const [typeOfFlights, settypeOfFlights] = useState('LAN');
useEffect(() => {
fetch('/flights', {
method: 'GET',
headers: { 'Content-Type':'application/json' }
})
.then(res => res.json())
.then(data => {
setFlights(data.flights)
setflightData(true)
}).catch(err => console.log(err))
}, []);
}
На сервере. js:
const express = require('express');
const path = require('path');
const fetch = require('node-fetch');
const app = express();
const bodyParser = require('body-parser');
//production mode
if(process.env.NODE_ENV === 'production'){
app.use(express.static(path.join('./app/build')));
}
app.get('*', (req,res) =>{
res.sendFile(path.resolve(__dirname, './app/build'), 'index.html');
});
app.use(bodyParser.json());
// endpoint-variables
let d = new Date();
let year = d.getFullYear();
let month = d.getMonth() + 1;
let day = d.getDate();
if(month <= 9 ){
month = '0' + month;
}
if(day <= 9 ){
day = '0' + day;
}
// Formatting the year/month/day variables to make it fit into the /flights endpoint
let date = `${year}-${month}-${day}`;
// The flights-endpoint need two timestamps to retrieve estimated flights. By setting agoDate to current hour minus 2,
// I can then send that past timestamp with the request, depending on actual current hour. Same principle for futureDate, but 2 hours in the future.
let agoDate = new Date();
agoDate.setHours(agoDate.getHours()-2);
let futureDate = new Date();
futureDate.setHours(futureDate.getHours()+2);
// GET-routes
app.get('/flights', async (request, response) => {
await fetch(`https://api.swedavia.se/flightinfo/v2/query?filter=(airport eq 'ARN' or airport eq 'BMA') and flightType eq 'A' and flightStatus ne 'DEL' and (estimated ge '${date}T${agoDate.toLocaleTimeString()}' and estimated le '${date}T${futureDate.toLocaleTimeString()}')&count=800`, {
mode: "cors",
method: 'GET',
headers: {
'Ocp-Apim-Subscription-Key' : 'API_KEY_HERE',
'Content-Type': 'application/json',
'Accept': 'application/json',
'Host': 'api.swedavia.se',
'Access-Control-Allow-Origin': 'api.swedavia.se',
}
}).then(response => response.json())
.then((content) => response.send(content))
.catch(err => console.log(err))
});
// End of GET-ROUTES
// POST-ROUTES
app.post('/traffic', async (request, response) => {
let airport = await request.body.airport;
let trafficQuery = `<REQUEST>
<LOGIN authenticationkey="API_KEY_HERE" />
<QUERY objecttype="Situation" schemaversion="1.2" limit="25" includedeletedobjects="false" orderby="Deviation.CreationTime desc">
<FILTER>
<WITHIN name="Deviation.Geometry.WGS84" shape="center" value="${request.body.long} ${request.body.lat}" radius="10000m" />
<AND>
<WITHIN name="Deviation.Geometry.WGS84" shape="center" value="${(airport === 'ARN') ? '17.91 59.51' : '17.95 59.35'}" radius="${airport === 'ARN' ? '25000m' : '15000m'}"/>
</AND>
<NOT>
<EQ name="Deviation.MessageCodeValue" value="ferry" />
</NOT>
</FILTER>
</QUERY>
</REQUEST>`;
await fetch('https://api.trafikinfo.trafikverket.se/v2/data.json', {
mode: 'no-cors',
method: 'POST',
headers: {
'Content-Type': 'text/xml'
},
body: trafficQuery
}).then(response => response.json())
.then((content) => response.send(content))
.catch(err => console.log(err))
});
app.post('/flow', async (request, response) => {
let airport = await request.body.airport;
let cameraQuery =
`<REQUEST>
<LOGIN authenticationkey="API_KEY_HERE" />
<QUERY objecttype="Camera" schemaversion="1">
<FILTER>
<NEAR name="Geometry.WGS84" shape="center" value="${airport === 'ARN' ? '17.92 59.51' : '17.95 59.35'}" maxdistance="${airport === 'ARN' ? '20000' : '15000'}" />
<AND>
<EQ name="Active" value="true" />
</AND>
</FILTER>
</QUERY>
<QUERY objecttype="TravelTimeRoute" schemaversion="1.5" includedeletedobjects="false">
<FILTER>
<NEAR name="Geometry.WGS84" value="${airport === 'ARN' ? '17.92 59.51' : '17.95 59.35'}" maxdistance="${airport === 'ARN' ? '20000' : '15000'}" />
</FILTER>
</QUERY>
</REQUEST>`
await fetch('https://api.trafikinfo.trafikverket.se/v2/data.json', {
mode: 'no-cors',
method: 'POST',
headers: {
'Content-Type': 'text/xml'
},
body: cameraQuery
}).then(response => response.json())
.then((content) => response.send(content))
.catch(err => console.log(err))
})
// End of POST-routes
const port = process.env.PORT || 5000;
app.listen(port);
Я использую node-fetch, чтобы получить доступ к методу fetch в Express. Какие-либо предложения? Хорошего дня, люди!