Почему мои журналы heroku показывают бесконечное количество повторений одного и того же запроса? - PullRequest
3 голосов
/ 27 мая 2020

Первая публикация на 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();
});

Любая помощь будет принята с благодарностью. На этот раз я несколько дней бился головой о стену.

...