Поддержка заголовка "Expect: 100-continue" с ASP.NET MVC

Я реализую REST API с использованием ASP.NET MVC, и появился небольшой камень преткновения в виде Expect: 100-continue заголовок запроса для запросов с телом сообщения.

RFC 2616 утверждает, что:

После получения запроса, который включает в себя поле заголовка запроса Expect с ожиданием "100-продолжить", сервер происхождения ДОЛЖЕН либо ответить со статусом 100 (Продолжить) и продолжить чтение из входного потока, либо ответить с помощью кода окончательного состояния. Исходный сервер НЕ ДОЛЖЕН ждать тела запроса перед отправкой ответа 100 (Продолжить). Если он отвечает с помощью окончательного кода состояния, он МОЖЕТ закрыть транспортное соединение или МОЖЕТ продолжать читать и отбрасывать оставшуюся часть запроса. Он НЕ ДОЛЖЕН выполнять запрошенный метод, если возвращает окончательный код состояния.

Для меня это звучит так, как будто мне нужно сделать два ответа на запрос, то есть он должен немедленно отправить ответ HTTP 100 Continue, а затем продолжить чтение из исходного потока запроса (т.е. HttpContext.Request.InputStream) без завершения запроса и, наконец, отправки результирующего кода состояния (в качестве аргумента, скажем, это результат 204 Нет содержимого).

Итак, вопросы:

  1. Правильно ли я читаю спецификацию, что мне нужно сделать два ответа на запрос?
  2. Как это можно сделать в ASP.NET MVC?

wrt (2) Я попытался использовать следующий код, прежде чем приступить к чтению входного потока...

HttpContext.Response.StatusCode = 100;
HttpContext.Response.Flush();
HttpContext.Response.Clear();

... но когда я пытаюсь установить окончательный код состояния 204, я получаю сообщение об ошибке:

System.Web.HttpException: сервер не может установить состояние после отправки заголовков HTTP.

3 ответа

Решение

100-продолжить должен обрабатываться IIS. Есть ли причина, почему вы хотите сделать это явно?

.NET Framework по умолчанию всегда отправляет expect: 100-continue заголовок для каждого сообщения HTTP 1.1. Это поведение можно программно контролировать по запросу через System.Net.ServicePoint.Expect100Continue свойство вроде так:

HttpWebRequest httpReq = GetHttpWebRequestForPost();
httpReq.ServicePoint.Expect100Continue = false;

Он также может управляться глобально программно:

System.Net.ServicePointManager.Expect100Continue = false;

... или глобально через конфигурацию:

<system.net>
  <settings>
    <servicePointManager expect100Continue="false"/>
  </settings>
</system.net>

Спасибо Лэнсу Олсону и Филу Хааку за эту информацию.

IIS обрабатывает 100.

Тем не менее, нет, это не два ответа. В HTTP, когда Expect: 100-continue входит как часть заголовков сообщения, клиент должен ждать, пока не получит ответ, прежде чем отправлять содержимое.

Из-за того, как asp.net спроектирован, у вас мало контроля над потоком вывода. Любые данные, которые записываются в поток, автоматически помещаются в ответ 200 с кусочным кодированием всякий раз, когда вы очищаете, будь то в режиме буферизации или нет.

К сожалению, все это скрыто во внутренних методах повсюду, и в результате вы полагаетесь на asp.net, как и MVC, но в значительной степени не можете обойти это.

Подождите, пока вы не попытаетесь получить доступ к входному потоку небуферизованным способом. Целый груз боли.

Себ

Другие вопросы по тегам