Работа с двойным кодированием в HTTP-запросах Flurl на получение

У меня возникли проблемы с пониманием того, как передавать закодированные данные в запросе с помощью flurl. У нас есть API, который выглядит так:

https://servicename.com/domain/api/{identifier}?parameter=value

И в некоторых конкретных случаях у нас есть идентификаторы, которые содержат косую черту /

Мы создаем запрос, используя следующий код:

var clientRequest = this.configuration.Client
            .Request(this.configuration.RequestPath)
            .AppendPathSegment(identifier)
            .WithHeader("Requesting-System", "api");

И мы вызываем это, используя:

using (var response = await clientRequest.GetAsync(cancellationToken))
{
    return await response.Content.ReadAsStringAsync();
}

В настоящее время. Используя простой подход, просто передавайте идентификатор с косой чертой; скажем, abc/123. Приведенный выше код генерирует clientRequest с путем

https://servicename.com/domain/api/abc/123?parameter=value

Что, как и следовало ожидать, завершается с ошибкой 400. Таким образом, решение для этого, основанное на наших спецификациях API, состоит в том, чтобы закодировать косую черту как %2F и передать ее в URL-адресе. К счастью, Flurl делает это довольно легко в теории, разрешая необязательный параметр в методе AppendPathSegment, который вызовет кодирование. Поэтому мы исправляем вышеизложенное, чтобы использовать

.AppendPathSegment(identifier, true)

Который генерирует clientRequest с путем

https://servicename.com/domain/api/abc%2F123?parameter=value

Именно то, что я ожидал увидеть. Если я вызову этот URL-адрес с помощью почтальона, я увижу правильный ответ, который я ожидаю от API.

Однако, когда я вызываю его с помощью метода GetAsync (такого же, как указано выше), я все равно получаю ошибку 400 Sub-Resource notcognized; и в моих журналах я вижу, что фактический запрос был сделан для

https://servicename.com/domain/api/abc/123?parameter=value

Есть ли во время вызова службы момент, когда Flurl декодирует строку URL? Если да, то как передать %2F?

Пробовали двойное кодирование, чтобы запрос содержал идентификатор abc%252F123. Учитывая вышесказанное, я ожидал, что это будет декодировано в abc%2F123, которое затем будет отправлено в наш API. Но в этом случае декодирование не происходит, и URL-адрес запроса

https://servicename.com/domain/api/abc%252F123?parameter=value

Заранее большое спасибо за помощь.


person The Aurochs    schedule 10.10.2018    source источник
comment
Извините за задержку. в моих журналах я вижу фактический запрос... Как именно вы это регистрируете? Я настроил ваш точный сценарий и выполнил запрос к точное место, где HttpRequestMessage завершается и передается HttpClient, и может гарантировать, что URL-адрес не закодирован и не закодирован дважды. Сегмент пути в этой точке равен abc%2F123.   -  person Todd Menier    schedule 12.10.2018
comment
Извинения не нужны; очень ценю, что вы нашли время, чтобы посмотреть на все эти проблемы в первую очередь. Мы используем Serilog и SEQ для наших решений для ведения журналов, но мы почти уверены, что проблема здесь не в этом — например, fiddler показывает тот же URL-адрес с abc/123.   -  person The Aurochs    schedule 12.10.2018


Ответы (1)


Похоже, это ошибка или причуда (в зависимости от того, кого вы спрашиваете) с System.Uri, который HttpClient использует глубоко в вызове куча. Обходной путь заключается в том, чтобы добавить это в app.config или web.config:

<uri>
  <schemeSettings>
    <add name="http" genericUriParserOptions="DontUnescapePathDotsAndSlashes" />
  </schemeSettings>
</uri>

Вся заслуга в этом принадлежит этому ответу.

Если это вообще возможно, я бы в первую очередь не разрешал использовать зарезервированные символы URL в ваших идентификаторах. Это только кажется, что приглашает причуды. Если это невозможно, возможно, придумайте свою собственную escape-последовательность для представления косой черты.

person Todd Menier    schedule 12.10.2018
comment
Похоже, что в конечном итоге это, вероятно, станет причиной; Я поиграл с flurl напрямую и с помощью модульных тестов, и вы правы; Я не смог воспроизвести проблему. Спасибо за помощь и за то, что дали нам несколько разных точек зрения, чтобы атаковать это с - person The Aurochs; 15.10.2018
comment
Этот ответ был полезен? - person Todd Menier; 19.11.2018
comment
Спасибо за ваше время и терпение Тодд; это было полезно. В конце концов наша проблема заключалась в том, что наша среда выполнения TargetFramework не была установлена ​​​​на 4.7 после обновления наших проектов для использования этой версии. Этот ответ увел нас от нескольких тупиков расследования. Приму в надежде, что это будет полезно другим пользователям. Ваше здоровье - person The Aurochs; 19.11.2018