Может ли это также повлиять на пользовательские слаг-адреса (содержащие имя пользователя)?
У нас есть несколько пользователей с UTF-8 именами, и некоторые из них не могут получить доступ к своим профилям…
Это не должно никак влиять на пользователя, так как маршруты полностью различаются.
Можете ли вы предоставить ссылку, где профиль не загружается? Или хотя бы пример имени пользователя, которое вызывает эту ошибку?
Это один из случаев: https://rembetiko.gr/u/σπυρος
Имя пользователя — ΣΠΥΡΟΣ (это заглавная форма слова σπυρος)
Извините за греческий язык ![]()
Эта страница находится за прокси Cloudflare? Можете ли вы проверить, отключив его?
Также какие значения у настроек:
-
разрешенные символы в имени пользователя Unicode -
имена пользователей Unicode
Вот значения (довольно стандартные
)
Да
Я только что отключил прокси и снова протестировал. К сожалению, проблема сохраняется. Я пока оставлю прокси отключенным, чтобы вы могли проверить это самостоятельно, если хотите ![]()
Огромное спасибо за вашу помощь! ![]()
Хм.
Если я попробую загрузить заглавную версию, сначала открывается ссылка: Προφίλ - ΣΠΥΡΟΣ - Ρεμπέτικο Φόρουμ, но затем происходит сбой при последующем запросе JSON к строчной версии.
Похоже, это ошибка в обработке заглавных и строчных букв.
Странно, но этот работает:
https://rembetiko.gr/u/αγγελικη_ντοτη
Имя пользователя — ΑΓΓΕΛΙΚΗ_ΝΤΟΤΗ (снова заглавная форма от αγγελικη_ντοτη)
Возможно, в греческом языке есть два способа привести букву «Σ» к нижнему регистру?
- «ς» — когда она используется в конце слова
- «σ» — в остальных случаях
Значит, это ошибка?
[1] pry(main)> "ΣΠΥΡΟΣ".downcase
=> "σπυροσ"
Да, грамматически это неверно. Правильная форма — «σπυρος».
О, боюсь, это ошибка Ruby:
➜ ruby --version
ruby 3.0.0dev (2020-12-16T18:46:44Z master 93ba3ac036) [x86_64-linux]
➜ irb
irb(main):001:0> "ΣΠΥΡΟΣ".downcase
=> "σπυροσ"
Но когда ссылка создана, всё работает отлично… Значит, должен быть способ заставить это работать… (?)
Не имеет значения, конвертирует ли Ruby имя пользователя в грамматически правильную строчную версию, если он всегда ищет пользователей по нормализованному имени пользователя (User.normalize_username в Ruby) и полю username_lower в базе данных.
Какой запрос JSON завершается неудачей? Скорее всего, существует маршрут, использующий иной механизм сравнения имен пользователей.
Возможно, это связано с тем, что у Ruby и JS разные реализации?
➜ ruby --version
ruby 3.0.0dev (2020-12-16T18:46:44Z master 93ba3ac036) [x86_64-linux]
➜ irb
irb(main):001:0> "ΣΠΥΡΟΣ".downcase
=> "σπυροσ"
➜ node
Welcome to Node.js v12.11.1.
Type ".help" for more information.
> "ΣΠΥΡΟΣ".toLowerCase()
'σπυρος'
В моих тестах Firefox ведет себя так же, как NodeJS.
Конечная точка /u/#{username}.json возвращает только колонку username, а не username_lower, поэтому, возможно, мы полагаемся здесь на браузер? Сейчас разберусь…
О, это плохо. Значит, проблема, скорее всего, вот в чём:
Я собирался предложить добавить username_lower в UserSerializer на сервере вместо выполнения этого на клиенте, но это всё равно оставит у нас несколько других вхождений username.toLowerCase.
Интересно, не будет ли лучшим решением использование mini_racer для вычисления username_lower на сервере, когда он содержит не-ASCII символы. ![]()
Что ж, независимо от того, какой обходной путь мы ищем, я сообщу об этом в Ruby.
Только для справки: PHP делает это так же, как и Ruby… Это заставляет меня думать, что это умышленное решение (?)
Вы можете протестировать код здесь:
Интересно, что Postgres тоже здесь не справляется:
[2] pry(main)> DB.query_single('select lower(?)', 'ΣΠΥΡΟΣ')
=> ["σπυροσ"]
Возможно, нам стоит просто обработать эту особенность в нашем внутреннем методе Discourse, который вычисляет username_lower?
Найти все методы, вызывающие username_lower, перенаправить их в центральную функцию и предусмотреть обработку этого случая (думаю, здесь можно использовать вызов mini_racer, если захотим, или просто вызвать .lower и затем исправить результат с помощью вызова sub).
Обновил заголовок в первом посте для большей ясности.
Дано:
[4] pry(main)> "σπυρος".downcase
=> "σπυρος"
@chrispanag, для вас тривиальное решение — просто изменить имя пользователя на σπυρος. В этом случае имя пользователя и его вариант в нижнем регистре будут полностью совпадать, и всё заработает.
Я сомневаюсь, стоит ли добавлять в ядро специальные обходные пути именно для этого случая, особенно когда существует столь простое решение.
Кроме того, вы можете запретить использование символа Σ в именах пользователей с помощью настройки allowed unicode username characters, что гарантирует, что эта проблема больше никогда не возникнет.
Я полностью за исправление проблем в Ruby и Postgres, но это долгая многолетняя борьба за внесение таких исправлений.
Я полностью согласен: мы сообщаем об ошибках в upstream, а пользователи Discourse могут использовать существующие инструменты для обхода проблем до их устранения.
