Commit e9ec4ed1 authored by 张宇's avatar 张宇

rpc_view

parent 15dae3fd
# -*- coding: utf-8 -*-
from gm_rpcd.all import bind, context
ROUTER_PREFIX = 'courier/'
# ROUTER_PREFIX = 'courier/'
ROUTER_PREFIX = ''
bind_prefix = lambda endpoint, **options: bind(ROUTER_PREFIX+endpoint, **options)
......@@ -4,6 +4,7 @@
<config name="application_name" value="courier"/>
<config name="service_list">
<element value="courier"/>
<element value="message"/>
</config>
<config name="initializer_list">
<element value="courier.management_interface.initialize:initialize"/>
......
......@@ -147,8 +147,8 @@ STATIC_URL = '/static/'
#######################################################
####################### LOGGING #######################
#######################################################
# https://docs.djangoproject.com/en/2.2/topics/logging/
# django.utils.log:18, django.conf.global_settings:559
# https://docs.djangoproject.com/en/3.0/topics/logging/
# django.utils.log:18, django.conf.global_settings:561
PROJECT_LOG_PATH = '/data/log/courier/app'
if not os.path.exists(PROJECT_LOG_PATH):
try:
......@@ -274,4 +274,4 @@ COUNT_LIMIT = 100
ES_SEARCH_TIMEOUT = '10s'
DATABASE_ROUTERS = ['courier.db_routers.MessageRouter']
MESSAGE_DB_NAME = 'default'
MESSAGE_SLAVE_DB_NAME = 'slave'
\ No newline at end of file
import multiprocessing
workers = multiprocessing.cpu_count() + 1
bind = '0.0.0.0:8000'
bind = '0.0.0.0:8005'
proc_name = 'courier'
timeout = 3600
preload_app = True
......
......@@ -11,6 +11,7 @@ from adapter.old_system import bind_prefix
from adapter.rpcd.exceptions import RPCPermanentError
from api.models.message import ConversationUserStatus
from rpc import gaia_client
from rpc_framework.decorators import rpc_view
from search.utils import search_conversation_from_es
from services.unread.stat import UserUnread
......@@ -232,3 +233,8 @@ def message_conversation_list_v3(user_ids: List[int],
}
@rpc_view('message/conversation/can_send')
def check_can_send_message(context, target_uid: str) -> Dict:
# print(context.session_id)
print('+++', context, dir(context), context._context.session_id)
return {'a': 'b'}
......@@ -17,4 +17,4 @@ raven==6.10.0
elasticsearch==2.3.0
kafka-python==1.4.7
gunicorn==20.0.4
djangorestframework==3.11.0
\ No newline at end of file
#djangorestframework==3.11.0
\ No newline at end of file
# -*- coding: utf-8 -*-
# -*- coding: utf-8 -*-
import sys
from contextlib import contextmanager
from typing import Optional, Tuple
from gm_rpcd.internals.context import Context
from rpc_framework import exceptions
from rpc_framework.settings import api_settings
class WrappedAttributeError(Exception):
pass
@contextmanager
def wrap_attributeerrors():
"""
Used to re-raise AttributeErrors caught during authentication, preventing
these errors from otherwise being handled by the attribute access protocol.
"""
try:
yield
except AttributeError:
info = sys.exc_info()
exc = WrappedAttributeError(str(info[1]))
raise exc.with_traceback(info[2])
class RPCViewContext(object):
def __init__(self,
context: Context,
authenticators: Optional[Tuple]=None,
interceptors: Optional[Tuple]=None,
negotiator: Optional[Tuple]=None):
self._context = context
self.authenticators = authenticators or ()
self.interceptors = interceptors or ()
# self.negotiator = negotiator or self._default_negotiator()
@property
def user(self):
"""
Returns the user associated with the current request, as authenticated
by the authentication classes provided to the request.
"""
if not hasattr(self, '_user'):
with wrap_attributeerrors():
self._authenticate()
return self._user
@user.setter
def user(self, value):
"""
Sets the user on the current request. This is necessary to maintain
compatibility with django.contrib.auth where the user property is
set in the login and logout functions.
Note that we also set the user on Django's underlying `HttpRequest`
instance, ensuring that it is available to any middleware in the stack.
"""
self._user = value
self._request.user = value
def _authenticate(self):
"""
Attempt to authenticate the request using each authentication instance
in turn.
"""
for authenticator in self.authenticators:
try:
user_auth_tuple = authenticator.authenticate(self)
except exceptions.RPCViewBaseException:
self._not_authenticated()
raise
if user_auth_tuple is not None:
self._authenticator = authenticator
self.user, self.auth = user_auth_tuple
return
self._not_authenticated()
def _not_authenticated(self):
"""
Set authenticator, user & authtoken representing an unauthenticated request.
Defaults are None, AnonymousUser & None.
"""
self._authenticator = None
if api_settings.UNAUTHENTICATED_USER:
self.user = api_settings.UNAUTHENTICATED_USER()
else:
self.user = None
if api_settings.UNAUTHENTICATED_TOKEN:
self.auth = api_settings.UNAUTHENTICATED_TOKEN()
else:
self.auth = None
# -*- coding: utf-8 -*-
import types
from rpc_framework.views import RPCView
def rpc_view(endpoint):
"""
Decorator that converts a function-based view into an RPCView subclass.
"""
def decorator(func):
WrappedAPIView = type(
'WrappedAPIView',
(RPCView,),
{'__doc__': func.__doc__}
)
WrappedAPIView.endpoint = endpoint
def handler(self, context, *args, **kwargs):
return func(context, *args, **kwargs)
setattr(WrappedAPIView, 'handler', handler)
WrappedAPIView.__name__ = func.__name__
WrappedAPIView.__module__ = func.__module__
# WrappedAPIView.renderer_classes = getattr(func, 'renderer_classes',
# RPCView.renderer_classes)
WrappedAPIView.parser_classes = getattr(func, 'parser_classes',
RPCView.parser_classes)
WrappedAPIView.authentication_classes = getattr(func, 'authentication_classes',
RPCView.authentication_classes)
WrappedAPIView.throttle_classes = getattr(func, 'throttle_classes',
RPCView.throttle_classes)
WrappedAPIView.permission_classes = getattr(func, 'permission_classes',
RPCView.permission_classes)
# WrappedAPIView.schema = getattr(func, 'schema', RPCView.schema)
return WrappedAPIView.rpc_bind()
return decorator
# -*- coding: utf-8 -*-
class RPCViewBaseException(Exception):
pass
# -*- coding: utf-8 -*-
import gm_rpcd
from gm_rpcd.internals.dynamic_scopes import Keys, dynamic_scope
class RPCAbstractView(object):
def __init__(self, **kwargs):
for key, value in kwargs.items():
setattr(self, key, value)
@classmethod
def rpc_bind(cls, **initkwargs):
"""
Store the original class on the view function.
This allows us to discover information about the view when we do URL
reverse lookups. Used for breadcrumb generation.
"""
def view(*args, **kwargs):
self = cls(**initkwargs)
# context = gm_rpcd.all.context
context = dynamic_scope.get(Keys.CONTEXT)
self.setup(context, *args, **kwargs)
return self.dispatch(context, *args, **kwargs)
view.view_class = cls
view.view_initkwargs = initkwargs
# avoid exception raise at gm_rpcd/internals/object_resolution_tables.py:62
view.__name__ = cls.__name__
view.__module__ = cls.__module__
gm_rpcd.all.bind(cls.endpoint)(view)
return view
def setup(self, context, *args, **kwargs):
"""Initialize attributes shared by all view methods."""
self.context = context
self.args = args
self.kwargs = kwargs
def dispatch(self, context, *args, **kwargs):
# print(type(context)) # gm_rpcd.internals.proxy_object.ProxyObject
# assert isinstance(context, Context), 'context must be instance of gm_rpcd.internals.context.Context'
return self.handler(context, *args, **kwargs)
"""
Settings for REST framework are all namespaced in the REST_FRAMEWORK setting.
For example your project's `settings.py` file might look like this:
REST_FRAMEWORK = {
'DEFAULT_RENDERER_CLASSES': [
'rest_framework.renderers.JSONRenderer',
'rest_framework.renderers.TemplateHTMLRenderer',
],
'DEFAULT_PARSER_CLASSES': [
'rest_framework.parsers.JSONParser',
'rest_framework.parsers.FormParser',
'rest_framework.parsers.MultiPartParser',
],
}
This module provides the `api_setting` object, that is used to access
REST framework settings, checking for user settings first, then falling
back to the defaults.
"""
from django.conf import settings
from django.test.signals import setting_changed
from django.utils.module_loading import import_string
# from rest_framework import ISO_8601
DEFAULTS = {
# Base API policies
# 'DEFAULT_RENDERER_CLASSES': [
# 'rest_framework.renderers.JSONRenderer',
# 'rest_framework.renderers.BrowsableAPIRenderer',
# ],
# 'DEFAULT_PARSER_CLASSES': [
# 'rest_framework.parsers.JSONParser',
# 'rest_framework.parsers.FormParser',
# 'rest_framework.parsers.MultiPartParser'
# ],
# 'DEFAULT_AUTHENTICATION_CLASSES': [
# 'rest_framework.authentication.SessionAuthentication',
# 'rest_framework.authentication.BasicAuthentication'
# ],
# 'DEFAULT_PERMISSION_CLASSES': [
# 'rest_framework.permissions.AllowAny',
# ],
# 'DEFAULT_THROTTLE_CLASSES': [],
# 'DEFAULT_CONTENT_NEGOTIATION_CLASS': 'rest_framework.negotiation.DefaultContentNegotiation',
# 'DEFAULT_METADATA_CLASS': 'rest_framework.metadata.SimpleMetadata',
# 'DEFAULT_VERSIONING_CLASS': None,
# Generic view behavior
# 'DEFAULT_PAGINATION_CLASS': None,
# 'DEFAULT_FILTER_BACKENDS': [],
# Schema
# 'DEFAULT_SCHEMA_CLASS': 'rest_framework.schemas.openapi.AutoSchema',
# Throttling
# 'DEFAULT_THROTTLE_RATES': {
# 'user': None,
# 'anon': None,
# },
# 'NUM_PROXIES': None,
# Pagination
# 'PAGE_SIZE': None,
# Filtering
# 'SEARCH_PARAM': 'search',
# 'ORDERING_PARAM': 'ordering',
# Versioning
# 'DEFAULT_VERSION': None,
# 'ALLOWED_VERSIONS': None,
# 'VERSION_PARAM': 'version',
#
# Authentication
# 'UNAUTHENTICATED_USER': 'django.contrib.auth.models.AnonymousUser',
# 'UNAUTHENTICATED_TOKEN': None,
# View configuration
# 'VIEW_NAME_FUNCTION': 'rest_framework.views.get_view_name',
# 'VIEW_DESCRIPTION_FUNCTION': 'rest_framework.views.get_view_description',
# Exception handling
# 'EXCEPTION_HANDLER': 'rest_framework.views.exception_handler',
# 'NON_FIELD_ERRORS_KEY': 'non_field_errors',
# Testing
# 'TEST_REQUEST_RENDERER_CLASSES': [
# 'rest_framework.renderers.MultiPartRenderer',
# 'rest_framework.renderers.JSONRenderer'
# ],
# 'TEST_REQUEST_DEFAULT_FORMAT': 'multipart',
# Hyperlink settings
# 'URL_FORMAT_OVERRIDE': 'format',
# 'FORMAT_SUFFIX_KWARG': 'format',
# 'URL_FIELD_NAME': 'url',
# Input and output formats
# 'DATE_FORMAT': ISO_8601,
# 'DATE_INPUT_FORMATS': [ISO_8601],
#
# 'DATETIME_FORMAT': ISO_8601,
# 'DATETIME_INPUT_FORMATS': [ISO_8601],
# 'TIME_FORMAT': ISO_8601,
# 'TIME_INPUT_FORMATS': [ISO_8601],
# Encoding
# 'UNICODE_JSON': True,
# 'COMPACT_JSON': True,
# 'STRICT_JSON': True,
# 'COERCE_DECIMAL_TO_STRING': True,
# 'UPLOADED_FILES_USE_URL': True,
#
# Browseable API
# 'HTML_SELECT_CUTOFF': 1000,
# 'HTML_SELECT_CUTOFF_TEXT': "More than {count} items...",
# Schemas
# 'SCHEMA_COERCE_PATH_PK': True,
# 'SCHEMA_COERCE_METHOD_NAMES': {
# 'retrieve': 'read',
# 'destroy': 'delete'
# },
}
# List of settings that may be in string import notation.
IMPORT_STRINGS = [
# 'DEFAULT_RENDERER_CLASSES',
# 'DEFAULT_PARSER_CLASSES',
# 'DEFAULT_AUTHENTICATION_CLASSES',
# 'DEFAULT_PERMISSION_CLASSES',
# 'DEFAULT_THROTTLE_CLASSES',
# 'DEFAULT_CONTENT_NEGOTIATION_CLASS',
# 'DEFAULT_METADATA_CLASS',
# 'DEFAULT_VERSIONING_CLASS',
# 'DEFAULT_PAGINATION_CLASS',
# 'DEFAULT_FILTER_BACKENDS',
# 'DEFAULT_SCHEMA_CLASS',
# 'EXCEPTION_HANDLER',
# 'TEST_REQUEST_RENDERER_CLASSES',
# 'UNAUTHENTICATED_USER',
# 'UNAUTHENTICATED_TOKEN',
# 'VIEW_NAME_FUNCTION',
# 'VIEW_DESCRIPTION_FUNCTION'
]
# List of settings that have been removed
REMOVED_SETTINGS = [
# 'PAGINATE_BY', 'PAGINATE_BY_PARAM', 'MAX_PAGINATE_BY',
]
def perform_import(val, setting_name):
"""
If the given setting is a string import notation,
then perform the necessary import or imports.
"""
if val is None:
return None
elif isinstance(val, str):
return import_from_string(val, setting_name)
elif isinstance(val, (list, tuple)):
return [import_from_string(item, setting_name) for item in val]
return val
def import_from_string(val, setting_name):
"""
Attempt to import a class from a string representation.
"""
try:
return import_string(val)
except ImportError as e:
msg = "Could not import '%s' for API setting '%s'. %s: %s." % (val, setting_name, e.__class__.__name__, e)
raise ImportError(msg)
class APISettings:
"""
A settings object, that allows API settings to be accessed as properties.
For example:
from rest_framework.settings import api_settings
print(api_settings.DEFAULT_RENDERER_CLASSES)
Any setting with string import paths will be automatically resolved
and return the class, rather than the string literal.
"""
def __init__(self, user_settings=None, defaults=None, import_strings=None):
if user_settings:
self._user_settings = self.__check_user_settings(user_settings)
self.defaults = defaults or DEFAULTS
self.import_strings = import_strings or IMPORT_STRINGS
self._cached_attrs = set()
@property
def user_settings(self):
if not hasattr(self, '_user_settings'):
self._user_settings = getattr(settings, 'REST_FRAMEWORK', {})
return self._user_settings
def __getattr__(self, attr):
if attr not in self.defaults:
raise AttributeError("Invalid API setting: '%s'" % attr)
try:
# Check if present in user settings
val = self.user_settings[attr]
except KeyError:
# Fall back to defaults
val = self.defaults[attr]
# Coerce import strings into classes
if attr in self.import_strings:
val = perform_import(val, attr)
# Cache the result
self._cached_attrs.add(attr)
setattr(self, attr, val)
return val
def __check_user_settings(self, user_settings):
SETTINGS_DOC = "https://www.django-rest-framework.org/api-guide/settings/"
for setting in REMOVED_SETTINGS:
if setting in user_settings:
raise RuntimeError("The '%s' setting has been removed. Please refer to '%s' for available settings." % (setting, SETTINGS_DOC))
return user_settings
def reload(self):
for attr in self._cached_attrs:
delattr(self, attr)
self._cached_attrs.clear()
if hasattr(self, '_user_settings'):
delattr(self, '_user_settings')
api_settings = APISettings(None, DEFAULTS, IMPORT_STRINGS)
def reload_api_settings(*args, **kwargs):
setting = kwargs['setting']
if setting == 'RPC_FRAMEWORK':
api_settings.reload()
setting_changed.connect(reload_api_settings)
# -*- coding: utf-8 -*-
from rpc_framework.context import RPCViewContext
from rpc_framework.generic.base import RPCAbstractView
from rpc_framework.settings import api_settings
class RPCView(RPCAbstractView):
# The following policies may be set at either globally, or per-view.
# renderer_classes = api_settings.DEFAULT_RENDERER_CLASSES
# parser_classes = api_settings.DEFAULT_PARSER_CLASSES
# authentication_classes = api_settings.DEFAULT_AUTHENTICATION_CLASSES
# throttle_classes = api_settings.DEFAULT_THROTTLE_CLASSES
# permission_classes = api_settings.DEFAULT_PERMISSION_CLASSES
parser_classes = []
authentication_classes = []
interceptor_classes = []
throttle_classes = []
permission_classes = []
# content_negotiation_class = api_settings.DEFAULT_CONTENT_NEGOTIATION_CLASS
content_negotiation_class = lambda self: None
# content_negotiation_class = api_settings.DEFAULT_CONTENT_NEGOTIATION_CLASS
# metadata_class = api_settings.DEFAULT_METADATA_CLASS
# versioning_class = api_settings.DEFAULT_VERSIONING_CLASS
# Allow dependency injection of other settings to make testing easier.
settings = api_settings
# schema = DefaultSchema()
@classmethod
def rpc_bind(cls, **initkwargs):
view = super().rpc_bind(**initkwargs)
view.cls = cls
view.initkwargs = initkwargs
return view
def dispatch(self, context, *args, **kwargs):
"""
`.dispatch()` is pretty much the same as Django's regular dispatch,
but with extra hooks for startup, finalize, and exception handling.
"""
self.args = args
self.kwargs = kwargs
context = self.initialize_context(context, *args, **kwargs)
self.context = context
# self.headers = self.default_response_headers # deprecate?
try:
self.initial(context, *args, **kwargs)
# Get the appropriate handler method
handler = self.handler
response = handler(context, *args, **kwargs)
except Exception as exc:
print('+' * 10 , exc)
response = self.handle_exception(exc)
self.response = self.finalize_response(context, response, *args, **kwargs)
return self.response
# @property
# def allowed_methods(self):
# """
# Wrap Django's private `_allowed_methods` interface in a public property.
# """
# return self._allowed_methods()
#
# @property
# def default_response_headers(self):
# headers = {
# 'Allow': ', '.join(self.allowed_methods),
# }
# if len(self.renderer_classes) > 1:
# headers['Vary'] = 'Accept'
# return headers
#
# def http_method_not_allowed(self, request, *args, **kwargs):
# """
# If `request.method` does not correspond to a handler method,
# determine what kind of exception to raise.
# """
# raise exceptions.MethodNotAllowed(request.method)
#
# def permission_denied(self, request, message=None):
# """
# If request is not permitted, determine what kind of exception to raise.
# """
# if request.authenticators and not request.successful_authenticator:
# raise exceptions.NotAuthenticated()
# raise exceptions.PermissionDenied(detail=message)
#
# def throttled(self, request, wait):
# """
# If request is throttled, determine what kind of exception to raise.
# """
# raise exceptions.Throttled(wait)
#
# def get_authenticate_header(self, request):
# """
# If a request is unauthenticated, determine the WWW-Authenticate
# header to use for 401 responses, if any.
# """
# authenticators = self.get_authenticators()
# if authenticators:
# return authenticators[0].authenticate_header(request)
#
# def get_parser_context(self, http_request):
# """
# Returns a dict that is passed through to Parser.parse(),
# as the `parser_context` keyword argument.
# """
# # Note: Additionally `request` and `encoding` will also be added
# # to the context by the Request object.
# return {
# 'view': self,
# 'args': getattr(self, 'args', ()),
# 'kwargs': getattr(self, 'kwargs', {})
# }
#
# def get_renderer_context(self):
# """
# Returns a dict that is passed through to Renderer.render(),
# as the `renderer_context` keyword argument.
# """
# # Note: Additionally 'response' will also be added to the context,
# # by the Response object.
# return {
# 'view': self,
# 'args': getattr(self, 'args', ()),
# 'kwargs': getattr(self, 'kwargs', {}),
# 'request': getattr(self, 'request', None)
# }
#
# def get_exception_handler_context(self):
# """
# Returns a dict that is passed through to EXCEPTION_HANDLER,
# as the `context` argument.
# """
# return {
# 'view': self,
# 'args': getattr(self, 'args', ()),
# 'kwargs': getattr(self, 'kwargs', {}),
# 'request': getattr(self, 'request', None)
# }
#
# def get_view_name(self):
# """
# Return the view name, as used in OPTIONS responses and in the
# browsable API.
# """
# func = self.settings.VIEW_NAME_FUNCTION
# return func(self)
#
# def get_view_description(self, html=False):
# """
# Return some descriptive text for the view, as used in OPTIONS responses
# and in the browsable API.
# """
# func = self.settings.VIEW_DESCRIPTION_FUNCTION
# return func(self, html)
#
# # API policy instantiation methods
#
# def get_format_suffix(self, **kwargs):
# """get_permissions
# Determine if the request includes a '.json' style format suffix
# """
# if self.settings.FORMAT_SUFFIX_KWARG:
# return kwargs.get(self.settings.FORMAT_SUFFIX_KWARG)
#
# def get_renderers(self):
# """
# Instantiates and returns the list of renderers that this view can use.
# """
# return [renderer() for renderer in self.renderer_classes]
#
def get_authenticators(self):
"""
Instantiates and returns the list of authenticators that this view can use.
"""
return [auth() for auth in self.authentication_classes]
def get_interceptors(self):
return [interceptor() for interceptor in self.interceptor_classes]
def get_permissions(self):
"""
Instantiates and returns the list of permissions that this view requires.
"""
return [permission() for permission in self.permission_classes]
def get_throttles(self):
"""
Instantiates and returns the list of throttles that this view uses.
"""
return [throttle() for throttle in self.throttle_classes]
def get_content_negotiator(self):
"""
Instantiate and return the content negotiation class to use.
"""
if not getattr(self, '_negotiator', None):
self._negotiator = self.content_negotiation_class()
return self._negotiator
# def get_exception_handler(self):
# """
# Returns the exception handler that this view uses.
# """
# return self.settings.EXCEPTION_HANDLER
#
# # API policy implementation methods
#
# def perform_content_negotiation(self, request, force=False):
# """
# Determine which renderer and media type to use render the response.
# """
# renderers = self.get_renderers()
# conneg = self.get_content_negotiator()
#
# try:
# return conneg.select_renderer(request, renderers, self.format_kwarg)
# except Exception:
# if force:
# return (renderers[0], renderers[0].media_type)
# raise
#
def perform_authentication(self, context):
"""
Perform authentication on the incoming request.
Note that if you override this and simply 'pass', then authentication
will instead be performed lazily, the first time either
`request.user` or `request.auth` is accessed.
"""
# context.user
return None
def check_permissions(self, context):
"""
Check if the request should be permitted.
Raises an appropriate exception if the request is not permitted.
"""
for permission in self.get_permissions():
if not permission.has_permission(context, self):
self.permission_denied(
context, message=getattr(permission, 'message', None)
)
# def check_object_permissions(self, request, obj):
# """
# Check if the request should be permitted for a given object.
# Raises an appropriate exception if the request is not permitted.
# """
# for permission in self.get_permissions():
# if not permission.has_object_permission(request, self, obj):
# self.permission_denied(
# request, message=getattr(permission, 'message', None)
# )
#
def check_throttles(self, context):
"""
Check if request should be throttled.
Raises an appropriate exception if the request is throttled.
"""
throttle_durations = []
for throttle in self.get_throttles():
if not throttle.allow_request(context, self):
throttle_durations.append(throttle.wait())
if throttle_durations:
# Filter out `None` values which may happen in case of config / rate
# changes, see #1438
durations = [
duration for duration in throttle_durations
if duration is not None
]
duration = max(durations, default=None)
self.throttled(context, duration)
# def determine_version(self, request, *args, **kwargs):
# """
# If versioning is being used, then determine any API version for the
# incoming request. Returns a two-tuple of (version, versioning_scheme)
# """
# if self.versioning_class is None:
# return (None, None)
# scheme = self.versioning_class()
# return (scheme.determine_version(request, *args, **kwargs), scheme)
# Dispatch methods
def initialize_context(self, context, *args, **kwargs):
"""
Returns the initial request object.
"""
# parser_context = self.get_parser_context(context)
return RPCViewContext(
context,
authenticators=self.get_authenticators(),
interceptors=self.get_interceptors(),
negotiator=self.get_content_negotiator()
)
def initial(self, context: RPCViewContext, *args, **kwargs):
"""
Runs anything that needs to occur prior to calling the method handler.
"""
# self.format_kwarg = self.get_format_suffix(**kwargs)
# Perform content negotiation and store the accepted info on the request
# neg = self.perform_content_negotiation(context)
# request.accepted_renderer, request.accepted_media_type = neg
# Determine the API version, if versioning is in use.
# version, scheme = self.determine_version(request, *args, **kwargs)
# request.version, request.versioning_scheme = version, scheme
# Ensure that the incoming request is permitted
self.perform_authentication(context)
self.check_permissions(context)
self.check_throttles(context)
def finalize_response(self, context, response, *args, **kwargs):
return response
# def handle_exception(self, exc):
# """
# Handle any exception that occurs, by returning an appropriate response,
# or re-raising the error.
# """
# if isinstance(exc, (exceptions.NotAuthenticated,
# exceptions.AuthenticationFailed)):
# # WWW-Authenticate header for 401 responses, else coerce to 403
# auth_header = self.get_authenticate_header(self.request)
#
# if auth_header:
# exc.auth_header = auth_header
# else:
# exc.status_code = status.HTTP_403_FORBIDDEN
#
# exception_handler = self.get_exception_handler()
#
# context = self.get_exception_handler_context()
# response = exception_handler(exc, context)
#
# if response is None:
# self.raise_uncaught_exception(exc)
#
# response.exception = True
# return response
#
# def raise_uncaught_exception(self, exc):
# if settings.DEBUG:
# request = self.request
# renderer_format = getattr(request.accepted_renderer, 'format')
# use_plaintext_traceback = renderer_format not in ('html', 'api', 'admin')
# request.force_plaintext_errors(use_plaintext_traceback)
# raise exc
#
# # Note: Views are made CSRF exempt from within `as_view` as to prevent
# # accidental removal of this exemption in cases where `dispatch` needs to
# # be overridden.
# def dispatch(self, request, *args, **kwargs):
# """
# `.dispatch()` is pretty much the same as Django's regular dispatch,
# but with extra hooks for startup, finalize, and exception handling.
# """
# self.args = args
# self.kwargs = kwargs
# request = self.initialize_request(request, *args, **kwargs)
# self.request = request
# self.headers = self.default_response_headers # deprecate?
#
# try:
# self.initial(request, *args, **kwargs)
#
# # Get the appropriate handler method
# if request.method.lower() in self.http_method_names:
# handler = getattr(self, request.method.lower(),
# self.http_method_not_allowed)
# else:
# handler = self.http_method_not_allowed
#
# response = handler(request, *args, **kwargs)
#
# except Exception as exc:
# response = self.handle_exception(exc)
#
# self.response = self.finalize_response(request, response, *args, **kwargs)
# return self.response
#
# def options(self, request, *args, **kwargs):
# """
# Handler method for HTTP 'OPTIONS' request.
# """
# if self.metadata_class is None:
# return self.http_method_not_allowed(request, *args, **kwargs)
# data = self.metadata_class().determine_metadata(request, self)
# return Response(data, status=status.HTTP_200_OK)
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment