Как включить числовой (хэш) символ # в сегмент пути?

Мне нужно загрузить файл (используя существующие конечные точки Flurl-Http [1]), имя которого содержит «#», который, конечно, должен быть экранирован до %23, чтобы не конфликтовать с обнаружением uri-фрагментов.

Но Flurl всегда экранирует остальные, но не этот символ, что приводит к неработающему uri, где половина пути и все параметры запроса отсутствуют, потому что они были проанализированы как uri-фрагмент:

Url url = "http://server/api";
url.AppendPathSegment("item #123.txt");
Console.WriteLine(url.ToString());

Возвращает: http://server/api/item%20#123.txt

Это означает, что HTTP-запрос (с использованием Flurl.Http) попытается загрузить только несуществующий ресурс http://server/api/item%20.

Даже когда я предварительно экранирую сегмент, результат все равно становится точно таким же:

url.AppendPathSegment("item %23123.txt");
Console.WriteLine(url.ToString());

Снова возвращает: http://server/api/item%20#123.txt.

Есть ли способ остановить это «волшебство»?

[1] Это означает, что у меня есть делегаты/интерфейсы, где вводом является существующий экземпляр Flurl.Url, который я должен изменить.


person springy76    schedule 31.07.2017    source источник
comment
когда вы используете% 23, что вы имеете в виду, что «результат точно такой же»?   -  person pm100    schedule 31.07.2017
comment
@ pm100 Я снова получаю http://server/api/item%20#123.txt - обновил вопрос после вашего комментария.   -  person springy76    schedule 31.07.2017


Ответы (2)


Похоже, вы обнаружили ошибку. Вот задокументированные правила кодирования, которым следует Flurl:

  • Значения строки запроса полностью закодированы в URL.
  • Для сегментов пути зарезервированные символы, такие как / и %, не кодируются.
  • Для сегментов пути кодируются недопустимые символы, такие как пробелы.
  • Для сегментов пути ? кодируется, поскольку строки запроса обрабатываются особым образом.

Согласно 2-му пункту, он не должен кодировать # в пути, поэтому он правильно обрабатывает AppendPathSegment("item #123.txt"). Однако, когда вы сами кодируете # в %23, Flurl определенно не должен его декодировать. Но я подтвердил, что это то, что происходит. Я предлагаю вам создать задачу на GitHub, и она будет решена.

Тем временем вы можете написать свой собственный метод расширения, чтобы покрыть этот случай. Что-то вроде этого должно работать (и вам даже не нужно предварительно кодировать #):

public static Url AppendFileName(this Url url, string fileName) {
    url.Path += "/" + WebUtility.UrlEncode(fileName);
    return url;
}
person Todd Menier    schedule 31.07.2017
comment
Приятно получать отзывы от самого сопровождающего проекта :) Я заметил код в Url.EncodeIllegalCharacters, который сначала вызывает Uri.UnescapeDataString, а затем упаковывает результат с помощью Uri.EscapeUriString, но в соответствии с [stackoverflow.com/a/34189188/442376] никогда не бывает веской причины использовать EscapeUriString - person springy76; 02.08.2017
comment
Я снова призываю вас зарегистрировать это на GitHub, чтобы я не забыл взглянуть на него. Я уверен, что была причина для 2 вызовов в этом методе, но я не помню сразу. Несмотря на это, вы доказали, что это неправильно и должно быть исправлено. - person Todd Menier; 03.08.2017

В итоге я использовал Uri.EscapeDataString(foo), потому что предложенный WebUtility.UrlEncode заменяет пробел на «+», чего я не хотел.

person flam3    schedule 15.01.2020