В настоящее время 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 для корректного сопоставления.
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-набора, я хочу передать китайское имя пользователя
На самом деле это не работает: я пробовал, потому что заголовок не может содержать символы не из ASCII. Необходимо выполнить преобразование кодировки, но после кодирования символов система выдаёт ошибку «пользователь не существует», поскольку на стороне Discourse, принимающей запрос, кодировка не восстанавливается!!
Заголовки должны быть закодированы в UTF-8, а не с использованием URI-кодирования.
Предоставлены следующие тестовые данные
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.
Я попробовал, но, похоже, тоже не работает. Хотя я не знаю Python.
Та же самая подсказка…
Работает ли тот же вызов с именем пользователя в кодировке ASCII?
(Я предполагаю, что нет, и именно это вы имеете в виду под «я не могу использовать API в обычном режиме»)
Если да, то есть ли у веб-сайта ещё один прокси перед ним или используется стандартная установка?
Да, этот вызов закодировал его как экранированное представление последовательности байтов UTF-8, а не сами байты.