Re: повторная отправка POST запросов ?

Maxim Dounin mdounin на mdounin.ru
Ср Дек 25 20:13:18 UTC 2019


Hello!

On Thu, Dec 26, 2019 at 12:32:04AM +0500, Илья Шипицин wrote:

> ср, 25 дек. 2019 г. в 23:20, Maxim Dounin <mdounin at mdounin.ru>:
> 
> > Hello!
> >
> > On Wed, Dec 25, 2019 at 02:58:15PM +0500, Илья Шипицин wrote:
> >
> > > ср, 25 дек. 2019 г. в 14:38, Sergey Kandaurov <pluknet at nginx.com>:
> > >
> > > >
> > > > > On 24 Dec 2019, at 23:35, Илья Шипицин <chipitsine at gmail.com> wrote:
> > > > >
> > > > > привет!
> > > > >
> > > > > допустим, такая ситуация. есть POST запрос, у него есть хедеры и,
> > > > собственно, тело запроса. мы отправили хедеры на бекенд, тело не успели
> > > > отправить, и бекенд нам сделал TCP RST.
> > > > >
> > > > > должен ли такой POST повторно отправляться, если не указан
> > > > non_idempotent ? (судя по моим экспериментам - не отправляется. но ведь
> > > > тело не было отправлено ? значит мы должны попасть под условие, что
> > такой
> > > > запрос можно отправить повторно ?)
> > > >
> > > > Как только мы успешно установили соединение и перешли к отправке
> > запроса
> > > > (не важно, успели начать отправку тела или нет), запрос считается
> > > > отправленным,
> > > > т.к. в общем случае мы не знаем, был ли он обработан или нет.
> > > >
> > >
> > > я предлагаю такую логику.
> > > бекенд умеет отличать полностью полученный запрос от неполного запроса
> > > (например, по Content-Length)
> > > навряд ли бекенд будет обрабатывать неполностью полученный запрос
> > >
> > > и считать отправленными только полностью отправленные запросы
> >
> > Считать-то можно, но у бекенда может быть своё мнение по этому
> > вопросу.  Каких-либо явных утверждений в RFC 2616 / RFC 7231,
> > которые бы говорили о том, что так можно - я в своё время не
> > нашёл.  И по факту так скорее всего нельзя, так как на тело
> > бекенду во многих случаях может быть наплевать.
> >
> 
> есть достаточно странный кейс, когда отправляется POST без тела. не
> конкретно в наших приложениях, а в принципе.
> я по некоторым разбирался, зачем так делают (ну то есть, можно же GET, но
> специально сделали POST). ответ меня поразил -
> по RFC нельзя кешировать POST. ну и чтобы наверняка без кеша, мы выбрали
> POST )) ну а тело ... надо не надо было
> 
> в описанном выше случае, действительно, тело (запроса) не предполагалось.
> 
> если тело предполагается, но не было отправлено, допустим бекенд вменяемый,
> что вполне может быть. он запрос не обработал.
> можно ретраить.
> 
> каких-то явных противоречий в этом не вижу

Явных противоречий тут и нет: скорее всего бекенд смотрит на тело, 
и в тех немногих случаях, когда мы точно знаем, что оно отправлено 
не полностью - скорее всего можно ретраить.

Однако проблем тут две:

- "Скорее всего можно" - не значит "точно можно", наступить на 
  ситуацию, когда бекенд на тело не смотрит - на практике вполне 
  можно.  И каких-либо явных причин требовать от бекенда, чтобы 
  смотрел - я, как я уже писал выше, не вижу, и если у такого 
  бекенда вдруг что-то пойдёт не так - виноват будет nginx.  (Если эти 
  причины вдруг есть - с удовольствием ознакомлюсь с соответствующей 
  цитатой из RFC.)

- Условие "когда мы точно знаем" не выполняется приблизительно 
  никогда: в подавляющем большинстве случаев тело вместе с 
  запросом уже сложено в буфер сокета, и что там с ним стало 
  дальше - узнать невозможно.  То есть мы про микрооптимизацию 
  оцень небольшого процента запросов.

Вместе эти две проблемы привели меня в своё время к выводу, что не  
стоит тут пытаться что-то наоптимизировать, кому надо - сделают 
правильно с защитой на уровне приложения, кому не надо - получают 
гарантированно корректное поведение из коробки.

-- 
Maxim Dounin
http://mdounin.ru/


Подробная информация о списке рассылки nginx-ru