Как я могу вернуть выходные данные JSON, когда не удается выполнить аутентификацию repoze.who?
Я пишу repoze.who
плагин и хотите вернуть JSON из repoze.who
промежуточное ПО аутентификации и все еще управляющий кодом статуса HTTP. Как это может быть сделано?
1 ответ
Один из способов сделать это - реализовать repoze.who
Интерфейс претендента. Следующее решение использует тот факт, что исключения WebOb, в webob.exc
, может использоваться как приложение WSGI. В следующем примере показано, как это можно использовать в гипотетическом плагине Facebook, где API 2.x позволяет пользователям не предоставлять доступ к своей электронной почте, что может потребоваться для успешной регистрации / аутентификации:
import json
from webob.acceptparse import MIMEAccept
from webob.exc import HTTPUnauthorized, HTTPBadRequest
FACEBOOK_CONNECT_REPOZE_WHO_NOT_GRANTED = 'repoze.who.facebook_connect.not_granted'
class ExampleJSONChallengerPlugin(object):
json_content_type = 'application/json'
mime_candidates = ['text/html',
'application/xhtml+xml',
json_content_type,
'application/xml',
'text/xml']
def is_json_request_env(self, environ):
"""Checks whether the current request is a json request as deemed by
TurboGears (i.e. response_type is already set) or if the http
accept header favours 'application/json' over html.
"""
if environ['PATH_INFO'].endswith('.json'):
return True
if 'HTTP_ACCEPT' not in environ:
return False
# Try to mimic what Decoration.lookup_template_engine() does.
return MIMEAccept(environ['HTTP_ACCEPT']) \
.best_match(self.mime_candidates) is self.json_content_type
def challenge(self, environ, status, app_headers, forget_headers):
if FACEBOOK_CONNECT_REPOZE_WHO_NOT_GRANTED in environ:
response = HTTPBadRequest(detail={
'not_granted':
environ.pop(FACEBOOK_CONNECT_REPOZE_WHO_NOT_GRANTED),
})
elif status.startswith('401 '):
response = HTTPUnauthorized()
else:
response = None
if response is not None and self.is_json_request_env(environ):
response.body = json.dumps({
'code': response.code,
'status': response.title,
'explanation': response.explanation,
'detail': response.detail,
})
response.content_type = self.json_content_type
return response
Центральным моментом здесь является то, что response
, экземпляр подкласса webob.exc.WSGIHTTPException
, используется как приложение WSGI, но также, если response
"s body
Если атрибут установлен, то он не генерируется автоматически, это факт, который мы используем для явного задания тела ответа в строковом представлении нашего словаря в формате JSON. Если вышеуказанный претендент вызывается во время обработки запроса к URL-адресу, оканчивающемуся на ".json" или Accept
заголовок включает application/json
тело ответа может выглядеть примерно так:
{
"status": "Bad Request",
"explanation": "The server could not comply with the request since it is either malformed or otherwise incorrect.",
"code": 400,
"detail": {"not_granted": ["email"]}
}
а если нет, то тело будет отображено как HTML:
<html>
<head>
<title>400 Bad Request</title>
</head>
<body>
<h1>400 Bad Request</h1>
The server could not comply with the request since it is either
malformed or otherwise incorrect.<br /><br />
{'not_granted': [u'email']}
</body>
</html>