Имена пользователей Unicode

В настоящее время Unicode-имена пользователей в Discourse не работают с API.

Можно ли исправить эту ошибку?

Я только что попробовал, и у меня всё работает:

○ → curl -s -L -H 'api-key: «redacted»' -H 'api-username: doesnotexist' https://try.discourse.org/u/运思/notifications.json
{"errors":["Вы не имеете права просматривать запрошенный ресурс. Имя пользователя API или ключ недействительны."],"error_type":"invalid_access"}

○ → curl -s -L -H 'api-key: «redacted»' -H 'api-username: 运思' https://try.discourse.org/u/运思/notifications.json | jq '.users[0]'
{
  "id": 41,
  "username": "运思",
  "name": "Michael Brown",
  "avatar_template": "/user_avatar/try.discourse.org/运思/{size}/208_2.png",
  "trust_level": 1,
  "assign_icon": "user-plus",
  "assign_path": "/u/运思/activity/assigned"
}

Можете показать, как именно это не работает у вас?

Спасибо, Майкл Браун.

Я протестировал это: в браузере всё работает, но в среде программирования — нет, так как правило гласит, что для передачи этого протокола могут использоваться только символы ASCII.

Причина ошибки:

TypeError: Invalid character in header content [“Api-Username”]

Обратите внимание на лог: рекомендуется добавить кодирование или декодирование в UTF-8 для корректного сопоставления.

  1. Тестовый интерфейс

  1. Веб-адрес

https://xxxxxxxx/posts.json

Accept:application/json
api-key:f9c13aafa9b21baf778161bff66a62533ba650b6e4542e3e9788e98c55ded869
Api-Username:system

Результат теста:

OK

Accept:application/json
api-key:f9c13aafa9b21baf778161bff66a62533ba650b6e4542e3e9788e98c55ded869
Api-Username:风之旅人

{“status”:500,“error”:“Internal Server Error”}

Accept:application/json
api-key:f9c13aafa9b21baf778161bff66a62533ba650b6e4542e3e9788e98c55ded869
Api-Username:%E8%BF%90%E6%80%9D

У вас нет прав на просмотр запрошенного ресурса. Имя пользователя API или ключ недействительны.

Причина ошибки:

Использование китайских символов в заголовке недопустимо. Их необходимо закодировать с помощью encodeURI() для передачи на сервер, а сервер должен декодировать их с помощью decodeURI(), чтобы распознать.

Предлагается добавить проверку: если имя пользователя не найдено, попытаться применить decodeURI для его сопоставления.

Что вы используете? Ошибка выглядит как ошибка Python? Библиотека requests это поддерживает, но возможно, используемые вами библиотеки — нет.

In [1]: import requests

In [2]: api_key = '«redacted»'

In [3]: r = requests.get('https://try.discourse.org/u/运思/notifications.json', headers = {
  'api-key': api_key,
  'api-username': '运思'.encode()
})

In [4]: r.status_code
Out[4]: 200

In [5]: r.json()['users'][0]
Out[5]: 
{'id': 41,
 'username': '运思',
 'name': 'Michael Brown',
 'avatar_template': '/user_avatar/try.discourse.org/运思/{size}/208_2.png',
 'trust_level': 1,
 'assign_icon': 'user-plus',
 'assign_path': '/u/运思/activity/assigned'}

Попробуйте вызвать .encode(), чтобы явно преобразовать значение заголовка в bytes… хотя, признаюсь, поскольку не всё является «8-битно чистым», я согласен с этим предложением:

как разумное.

Поиск по форумам: старые версии API можно использовать с Query

Новые версии API не работают с Query

Совместимо ли это с Query? Исправьте эту проблему

Например:

https://www.xxx.com/posts.json?api_key=714552c6148e1617aeab526d0606184b94a80ec048fc09894ff1a72b740c5f19&api_username=system

Надеемся, что это будет исправлено.

Это не произойдет. Теперь вам нужно передавать параметры API как заголовки, а не как параметры запроса. Это не изменится.

Но заголовок не может передавать символы не из ASCII-набора, я хочу передать китайское имя пользователя

Может, как доказано выше @supermathie:

cURL

Python:

На самом деле это не работает: я пробовал, потому что заголовок не может содержать символы не из ASCII. Необходимо выполнить преобразование кодировки, но после кодирования символов система выдаёт ошибку «пользователь не существует», поскольку на стороне Discourse, принимающей запрос, кодировка не восстанавливается!!

Заголовки должны быть закодированы в UTF-8, а не с использованием URI-кодирования.

  1. 1: заголовок не может содержать китайские символы
  2. 2: utf8 относится к содержимому поста, а не к заголовку
  3. 3: Discourse не декодируется с помощью UrlEncode, в результате будет отображаться сообщение о том, что пользователь не существует.

Предоставлены следующие тестовые данные

https://www.baowei.ink/posts.json
{
  "title": "标题标题标题标题标题",
  "raw": "标题标题标题标题标题标题标题标题标题标题",
  "category": 10,
}

Успешно

Content-Type: application/json; charset=UTF-8
Api-Key: «redacted»
Api-Username: system

Неудачно

Content-Type: application/json; charset=UTF-8
Api-Key: «redacted»
Api-Username: 风之旅人
Content-Type: application/json; charset=UTF-8
Api-Key: «redacted»
Api-Username: %E9%A3%8E%E4%B9%8B%E6%97%85%E4%BA%BA

Спасибо! Майкл Браун

Вам нужно немедленно сменить этот API-ключ @zengyunsi, считайте его скомпрометированным.

… хотя могу подтвердить, что он работает, если заголовки закодировать в UTF-8:

In [1]: import requests

In [2]: api_key = '«redacted»'

In [3]: r = requests.get('https://www.baowei.ink/posts.json', headers={'api-key': api_key, 'api-username': '风之旅人'.encode()})

In [4]: r.status_code
Out[4]: 200

In [5]: len(r.json()['latest_posts'])
Out[5]: 19

Так ли это и можете ли вы привести пример, спасибо!

Content-Type: Application/json; charset=utf-8
Accept: Application/json; charset=utf-8
Api-Key: f9c13aafa9b21baf778161bff66a62533ba650b6e4542e3e9788e98c55ded869
Api-Username: \xe9\xa3\x8e\xe4\xb9\x8b\xe6\x97\x85\xe4\xba\xba

Всегда запрашивать
Вы не имеете права просматривать запрошенный ресурс. Имя пользователя или ключ API недействительны

Я могу подтвердить, что пример ниже работает:

$ curl -s -L \
-H 'api-key: 60834ccb8eda28cf17bab8efbbb2fbf874eb8b5a75ff17ddbd2346eb292881a0' \
-H 'api-username: 测试用户' \
http://localhost:4200/u/%E6%B5%8B%E8%AF%95%E7%94%A8%E6%88%B7/emails.json

{"email":"discobot_email","secondary_emails":[],"unconfirmed_emails":[],"associated_accounts":[]}

А без заголовка api-*:

$ curl -s -L \
http://localhost:4200/u/%E6%B5%8B%E8%AF%95%E7%94%A8%E6%88%B7/emails.json

{"errors":["You need to be logged in to do that."],"error_type":"not_logged_in"}

Пример на Python с использованием библиотеки requests:

import requests

api_key = '60834ccb8eda28cf17bab8efbbb2fbf874eb8b5a75ff17ddbd2346eb292881a0'
api_username = '测试用户'
api_endpoint = 'http://localhost:4200/u/%E6%B5%8B%E8%AF%95%E7%94%A8%E6%88%B7/emails.json'

r = requests.get(api_endpoint, headers={
                 'api-key': api_key, 'api-username': api_username.encode()})

print(r)

<Response [200]>

Похоже, ваш api-username закодирован неправильно.

>>> '风之旅人'.encode()
b'\xe9\xa3\x8e\xe4\xb9\x8b\xe6\x97\x85\xe4\xba\xba'

Спасибо всем, я попробую. Если вы сможете использовать китайское имя пользователя для вызова операции API, это будет гораздо удобнее. Спасибо!


Это немного странно, и я тоже не могу нормально использовать API

Скорее всего, проблема в области действия ключа API.

:sweat_smile: Я попробовал, но, похоже, тоже не работает. Хотя я не знаю Python.
Та же самая подсказка…

Работает ли тот же вызов с именем пользователя в кодировке ASCII?

(Я предполагаю, что нет, и именно это вы имеете в виду под «я не могу использовать API в обычном режиме»)

Если да, то есть ли у веб-сайта ещё один прокси перед ним или используется стандартная установка?

Да, этот вызов закодировал его как экранированное представление последовательности байтов UTF-8, а не сами байты.