Ошибка службы данных WCF - 302 Перемещено в SaveChanges (), связанное с HTTPS + балансировщик нагрузки? - PullRequest
2 голосов
/ 23 августа 2011

Проблема: Сбой DataServiceContext.SaveChanges () с ответом «302 - перемещено».

Предпосылки / предполагаемая причина: Балансировщик нагрузки!- Мы недавно изменили нашу инфраструктуру, чтобы наши веб-серверы теперь располагались за балансировщиком нагрузки, который также обрабатывает ssl.Клиенты обращаются к сервису как HTTPS, но IIS завершает обработку HTTP-запросов, поскольку SSL был выполнен балансировщиком нагрузки (я уверен, что большинство из вас знакомы с этим типом установки).В любом случае мы получаем фид, содержащий URI, которые используют HTTP, а не HTTPS.(см. GET запрос / ответ ниже с http в ответе вместо httpS).Поведение довольно странное, так как когда я вызываю saveChanges (), он отправляет MERGE (как и ожидалось), и я получаю обратно 302:

HTTP/1.1 302 Object moved
Location: https://some.domain.org/CMSProfileService/ProfileDataService.svc/Mails(guid'80fef993-a4b5-4343-a908-28c2c6517a81')
Connection: close

, но WCF продолжает пытаться MERGE снова и снова, используя HTTP (примерно 50 раз), а затем, наконец, выдает исключение с сообщением "" Произошла ошибка при обработке этого запроса. ", внутреннее сообщение об исключении" Найдено ".:)

Когда я указываю прямо на сервер (в обходloadbalancer и ssl) все работает отлично. Все также работает нормально, когда SSL зарегистрирован непосредственно в IIS.

Должен быть какой-то параметр конфигурации / свойство, которое я не нахожу. Viteks answer toПодобный вопрос меня немного пугает.

Это необработанный GET-запрос от fiddler

GET https://some.domain.org/CMSProfileService2/ProfileDataService.svc/Mails()?$filter=Status%20eq%20'Queued'&$orderby=Timestamp&$expand=Attachments HTTP/1.1
User-Agent: Microsoft ADO.NET Data Services
DataServiceVersion: 1.0;NetFx
MaxDataServiceVersion: 2.0;NetFx
UserName: 
Accept: application/atom+xml,application/xml
Accept-Charset: UTF-8
Host: some.domain.org
Connection: Keep-Alive

и вот необработанный ответ (обрезано):

HTTP/1.1 200 OK
Set-Cookie: ARPT=RPZVOOS192.168.94.118CKOUM; path=/
Cache-Control: no-cache
Content-Length: 45849
Content-Type: application/atom+xml;charset=utf-8
Server: Microsoft-IIS/7.5
DataServiceVersion: 1.0;
X-AspNet-Version: 4.0.30319
X-Powered-By: ASP.NET
Date: Mon, 22 Aug 2011 14:56:46 GMT

<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<feed xml:base="http://some.domain.org/CMSPRofileService2/ProfileDataService.svc/" xmlns:d="http://schemas.microsoft.com/ado/2007/08/dataservices" xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata" xmlns="http://www.w3.org/2005/Atom">
  <title type="text">Mails</title>
  <id>http://some.domain.org/CMSProfileService2/ProfileDataService.svc/Mails</id>
  <updated>2011-08-22T14:56:47Z</updated>
  <link rel="self" title="Mails" href="Mails" />
  <entry>
    <id>http://some.domain.org/CMSPRofileService2/ProfileDataService.svc/Mails(guid'c7edb158-7a61-4fca-a40e-7f4a3a0b2bbd')</id>
    <title type="text"></title>
    <updated>2011-08-22T14:56:47Z</updated>
    <author>
      <name />
    </author>
    <link rel="edit" title="Mail" href="Mails(guid'c7edb158-7a61-4fca-a40e-7f4a3a0b2bbd')" />
    <link rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/Attachments" type="application/atom+xml;type=feed" title="Attachments" href="Mails(guid'c7edb158-7a61-4fca-a40e-7f4a3a0b2bbd')/Attachments">
      <m:inline>
        <feed>
          <title type="text">Attachments</title>
          <id>http://some.domain.org/CMSPRofileService2/ProfileDataService.svc/Mails(guid'c7edb158-7a61-4fca-a40e-7f4a3a0b2bbd')/Attachments</id>
          <updated>2011-08-22T14:56:47Z</updated>
          <author>
            <name />
          </author>
          <link rel="self" title="Attachments" href="Mails(guid'c7edb158-7a61-4fca-a40e-7f4a3a0b2bbd')/Attachments" />
        </feed>
      </m:inline>
    </link>
    <category term="XXX.YYY.Profile.Repository.Mail" scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme" />
    <content type="application/xml">
      <m:properties>
        <d:MailId m:type="Edm.Guid">c7edb158-7a61-4fca-a40e-7f4a3a0b2bbd</d:MailId>
        <d:Timestamp m:type="Edm.DateTime">2011-07-28T12:51:37.69</d:Timestamp>
        <d:ApplicationCode>EREF</d:ApplicationCode>
        <d:Status>Queued</d:Status
.
.
.

Ответы [ 2 ]

2 голосов
/ 30 августа 2011

Проблема здесь заключается в том, что ссылки для самостоятельного редактирования / ссылки являются HTTP, а не HTTPS, поэтому клиент не может использовать ссылки для доступа к данным. страшный ответ Пера Витека .

К сожалению, сервер не знает, где он находится.

Я могу придумать пару вариантов (ни один из них не особенно хорош):

  1. Используйте пользовательский IDataServiceHost2 , который сообщает Data Services, что его корень - https: // ... через свойство AbsoluteServiceUri. Таким образом службы данных должны создавать соответствующие URL-адреса
  2. Реализация поведения WCF, которое удаляет http: // urls и заменяет их на https://,, что потребовало бы большой буферизации и т. Д. Проверьте пример JSONP , который изменяет ответы с сервера.

1021 * для -Alex- *

0 голосов
/ 05 сентября 2011

Наконец-то решили эту неприятную проблему. На самом деле было две проблемы.

Проблема № 1: Служба данных WCF, размещенная в IIS за балансировщиком нагрузки с https, создает каналы с http URI, а не https. Это понятно и было моей первой догадкой. Через много копаний я наткнулся на эту статью, в которой было довольно простое решение.

В конструкторе моего сервиса я подключаюсь к событию запроса на обработку

ProcessingPipeline.ProcessingRequest += ProcessingPipeline_ProcessingRequest;

В обработчике событий я использовал упомянутую статью и сделал несколько настроек, которые в основном берут хост, схему и порт из clientExpectedUri и применяют их к Uri запроса. Я также просто ищу специальный заголовок, который я назвал «X-Client-Expected-RootUri», который необходимо отправлять клиентам за пределами брандмауэра, если они хотят действительные каналы.

static void ProcessingPipeline_ProcessingRequest(object sender, DataServiceProcessingPipelineEventArgs e)
{
    if (e.OperationContext.RequestHeaders.AllKeys.Contains(ClientExpectsUriKey))
        ProcessUri(new Uri(e.OperationContext.RequestHeaders[ClientExpectsUriKey]));    
}

private static void ProcessUri(Uri clientExpectsRootUri)
{
    if (clientExpectsRootUri != null)
    {
        var requestUri = OperationContext.Current.IncomingMessageProperties.ContainsKey("MicrosoftDataServicesRequestUri") 
                                ? OperationContext.Current.IncomingMessageProperties["MicrosoftDataServicesRequestUri"] as Uri : HttpContext.Current.Request.Url;

        var serviceUri = clientExpectsRootUri;

        var serviceUriBuilder = new UriBuilder(serviceUri);

        var requestUriBuilder = new UriBuilder(requestUri)
                                    {
                                        Host = serviceUriBuilder.Host,
                                        Scheme = serviceUriBuilder.Scheme,
                                        Port = serviceUriBuilder.Port
                                    };

        if (!serviceUriBuilder.Path.EndsWith("/")) //the base uri should end with a slash... 
            serviceUriBuilder.Path = serviceUriBuilder.Path += "/";

        OperationContext.Current.IncomingMessageProperties["MicrosoftDataServicesRootUri"] = serviceUriBuilder.Uri;
        OperationContext.Current.IncomingMessageProperties["MicrosoftDataServicesRequestUri"] = requestUriBuilder.Uri;
    }
}

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

Проблема № 2. Балансировщик нагрузки не настроен для MERGE и других не RFC-методов http. Решение этой проблемы было простым, просто установите usePostTunneling в true для DataServiceContext. Если у кого-то есть скрипты для включения не RFC-методов http для cisco 11503, я бы хотел их иметь. ; -)

...