Заголовок HTTP длины содержимого WCF в исходящем сообщении
Я нахожусь в сложной ситуации, когда конечной точке веб-службы Java, размещенной на IBM HTTP Server (IHS), требуется заголовок Content-Length, хотя он предположительно соответствует HTTP/1.1. Если я отправляю шапку, все работает. Если я отключу его, я получу ответ 500 об ошибке, сообщающий, что мое тело сущности POST было пустым (даже если это не так).
Мы потратили значительное время на наш клиент WCF для этих сервисов (разработанных третьей стороной), и я не могу найти хороший способ добавить заголовок Content-Length к запросу. Я могу добавить произвольные заголовки (например, X-Dan-Lynn-Header) к запросу, используя IClientMessageInspector, как описано в таких сообщениях в блоге, но WCF, похоже, игнорирует заголовок Content-Length.
Мои варианты:
а) выяснить, как заставить WCF добавить заголовок Content-Length в запрос HTTP POST или,
б) найти или написать чрезвычайно простой, но прозрачный HTTP-прокси, который украшает запрос заголовком Content-Length.
Спасибо!
Пример IClientMessageInspector.BeforeSendRequest:
public object BeforeSendRequest(ref Message request, IClientChannel channel)
{
var buffer = request.CreateBufferedCopy(Int32.MaxValue);
var tempRequest = buffer.CreateMessage();
HttpRequestMessageProperty httpRequest = GetHttpRequestProp(tempRequest);
if (httpRequest != null)
{
if (string.IsNullOrEmpty(httpRequest.Headers[HttpRequestHeader.ContentLength]))
{
httpRequest.Headers.Add(HttpRequestHeader.ContentLength, GetMessageLength(buffer).ToString());
httpRequest.Headers.Add("X-Dan-Lynn-Header", "abcdefghijk");
}
}
request = tempRequest;
request.Properties[HttpRequestMessageProperty.Name] = httpRequest;
return null;
}
Пример запроса, сгенерированного WCF (и предшествующим IClientMessageInspector):
POST /path/to/service HTTP/1.1
Content-Type: text/xml; charset=utf-8
X-Dan-Lynn-Header: abcdefghijk
SOAPAction: "http://tempuri.org/path/to/service/action"
Host: service.host.tld
Transfer-Encoding: chunked
Connection: Keep-Alive
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
.......body removed for clarity......
</s:Body>
</s:Envelope>
3 ответа
Догадаться. Установка привязки для использования TransferMode="Streamed" вызывала Transfer-Encoding: chunked. Мы нуждались в потоковой передаче из-за очень больших откликов от веб-службы, поэтому я смог пойти с:
Плохой:
transferMode="Streamed"
Хорошо:
transferMode="StreamedResponse"
Изменение привязки к этому решило проблему:
<basicHttpBinding>
<binding name="MyBinding" closeTimeout="00:30:00" openTimeout="00:30:00"
receiveTimeout="00:30:00" sendTimeout="00:30:00" allowCookies="false"
bypassProxyOnLocal="false" hostNameComparisonMode="StrongWildcard"
maxBufferSize="65536" maxBufferPoolSize="524288" maxReceivedMessageSize="16777216"
messageEncoding="Text" textEncoding="utf-8" transferMode="StreamedResponse"
useDefaultWebProxy="false">
<readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="65536"
maxBytesPerRead="4096" maxNameTableCharCount="16384" />
<security mode="None" />
</binding>
</basicHttpBinding>
В настоящее время я не могу попытаться запустить код, чтобы увидеть, что происходит, но что-то вроде
WCFClient client = new WCFClient();
using (OperationContextScope scope = new OperationContextScope(client.InnerChannel))
{
HttpRequestMessageProperty req = new HttpRequestMessageProperty();
req.Headers.Add("Content-Length", "YOUR CONTENT LENGTH HERE");
OperationContext.Current.OutgoingMessageProperties[HttpRequestMessageProperty.Name] = req;
}
см. http://msdn.microsoft.com/en-us/library/aa395196.aspx для получения дополнительной информации о том, как можно использовать объект OperationContextScope для включения дополнительных заголовков.
Обновление: я должен сказать, что нахожу это странной проблемой. Интересно, почему длина контента не устанавливается? Я не удивлюсь, если ваша настоящая проблема будет где-то еще.
TransferMode=StreamedResponse в app.config также помог мне в решении проблемы, аналогичной вашей. У меня была архитектура WCF для Sync Framework и прокси Squid 3.1.20, мне не понравился Streamed TransferMode. Большое спасибо!