Первая публикация на StackOverflow после многих счастливых лет чтения, так что извиняюсь, если это написано неправильно. Недавно мы запустили наше приложение React / Next JS в производство, размещенное на Heroku. У нас есть отдельный сервер GraphQL Yoga для обработки и отправки нужных данных, также размещенный на Heroku. Вы можете посетить приложение по номеру https://www.sayplants.com. Моя база данных (Prisma) сообщает о 10 000 запросов к нашей базе данных, несмотря на то, что я единственный человек, использующий сайт. Я проверил наши журналы Heroku и увидел очень странную картину. Сначала запрос GET:
2020-05-27T13:40:18.883461+00:00 heroku[router]: at=info method=GET path="/" host=www.sayplants.com request_id=36c364a0-012b-4927-813d-314bd3674657 fwd="176.249.98.203" dyno=web.1 connect=1ms service=150ms status=200 bytes=4252 protocol=https
Затем запрос POST с тем же request_id, но прокси, добавленным в поле «fwd»:
2020-05-27T13:40:18.975987+00:00 heroku[router]: at=info method=POST path="/" host=www.sayplants.com request_id=36c364a0-012b-4927-813d-314bd3674657 fwd="176.249.98.203,54.216.239.50" dyno=web.1 connect=0ms service=89ms status=200 bytes=4251 protocol=https
Затем запрос POST повторяется снова и снова, каждый раз добавляя (тот же) прокси к "fwd" (сокращение Heroku для X-Forwarded-For), так что у нас есть fwd="176.249.98.203, 54.216.239.50"
, а в следующем журнале - fwd="176.249.98.203, 54.216.239.50, 54.216.239.50"
, а затем fwd="176.249.98.203, 54.216.239.50, 54.216.239.50, 54.216.239.50"
и так далее до тех пор, пока сотни одинаковых IP-адресов не будут повторяться снова и снова.
При ближайшем рассмотрении мы смогли удалить это поведение в производственной среде, удалив наши запросы информации о пользователях из Next JS app - удаление следующего:
const User = props => (
<Query {...props} query={CURRENT_USER_QUERY}>
{payload => props.children(payload)}
</Query>
);
User.propTypes = {
children: PropTypes.func.isRequired,
};
export default User;
Где:
const CURRENT_USER_QUERY = gql`
query {
me {
id
email
name
}
}
`;
Но, очевидно, нам нужна пользовательская функциональность! Итак, мы изолировали проблему, но не знаем, как ее решить.
Если вы все еще со мной, для полноты картины это наш серверный преобразователь запросов:
async me(parent, args, ctx, info) {
if(!ctx.request.userId) {
return null;
}
const user = await ctx.db.query.user({
where: { id: ctx.request.userId }
}, info);
return user
},
Где request.userId устанавливается некоторым Express промежуточным программным обеспечением
server.express.use(cookieParser());
server.express.use((req, res, next) => {
const { token } = req.cookies;
if (token) {
const { userId } = jwt.verify(token, process.env.APP_SECRET)
req.userId = userId
}
next();
});
Любая помощь будет принята с благодарностью. На этот раз я несколько дней бился головой о стену.