def service(func):
"""
Make sure this is the first/closest @wrapper on your service function
Note that this decorator tags the original function with meta and new arguments.
The real url-->fn() registeration happens in __init__.py autodiscover() because of @url.
"""
@csrf_exempt # setting wrapper.csrf_exempt = True, consulted by CsrfViewMiddleware
def wrapper(req, *args, **kwargs):
response = ExpressResponse()
request = ExpressRequest(req)
func(request, response, *args, **kwargs) # all service functions should have this signature.
return response._res
wrapper.__name__ = func.__name__
wrapper.__doc__ = func.__doc__
wrapper.__module__ = func.__module__
# base entrypoint
wrapper._path = func.__name__
return wrapper
# use only on a Django ORM Model cls
python类csrf_exempt()的实例源码
def as_view(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.
"""
if isinstance(getattr(cls, 'queryset', None), models.query.QuerySet):
def force_evaluation():
raise RuntimeError(
'Do not evaluate the `.queryset` attribute directly, '
'as the result will be cached and reused between requests. '
'Use `.all()` or call `.get_queryset()` instead.'
)
cls.queryset._fetch_all = force_evaluation
view = super(APIView, cls).as_view(**initkwargs)
view.cls = cls
view.initkwargs = initkwargs
# Note: session based authentication is explicitly CSRF validated,
# all other authentication is CSRF exempt.
return csrf_exempt(view)
def as_view(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.
"""
if isinstance(getattr(cls, 'queryset', None), models.query.QuerySet):
def force_evaluation():
raise RuntimeError(
'Do not evaluate the `.queryset` attribute directly, '
'as the result will be cached and reused between requests. '
'Use `.all()` or call `.get_queryset()` instead.'
)
cls.queryset._fetch_all = force_evaluation
cls.queryset._result_iter = force_evaluation # Django <= 1.5
view = super(APIView, cls).as_view(**initkwargs)
view.cls = cls
# Note: session based authentication is explicitly CSRF validated,
# all other authentication is CSRF exempt.
return csrf_exempt(view)
def csrf(func):
"""
Ensures csrf token cookie or checkes it based on request method type.
"""
@wraps(func)
def wrapper(req, *args, **kwargs):
if req.method in ('GET', 'HEAD', 'OPTIONS', 'TRACE'):
return (ensure_csrf_cookie(func))(req, *args, **kwargs)
# Default cookie by CSRF_COOKIE_NAME in settings is 'csrftoken'
# submit back in either req.form['csrfmiddlewaretoken'] or req['X-CSRFToken']
# the latter often used by Ajax and can be configured by CSRF_HEADER_NAME in settings
else:
func.csrf_exempt = False # reset csrf_exempt set by @csrf_exempt during @service
return (csrf_protect(func))(req, *args, **kwargs)
# Note that we don't use requires_csrf_token() here since it was for making the 'csrf_token' tag work in django templates.
return wrapper
def _generateMountURLs(self, path, mapping, app=None):
p = path
@csrf_exempt # dispatcher (view) needs to be csrf exempted
def dispatcher(req, *args, **kwargs):
service = mapping.get(req.method, None) or mapping.get('*', None)
if service:
return service['src'](req, *args, **kwargs)
else:
return HttpResponseNotAllowed(mapping.keys())
# relative path
if not p.startswith('/'):
if app:
p = '/'.join([app, p]) # add app name prefix in addition to 'path'
# absolute path
else:
p = p[1:] # remove leading '/'
# support reverse() in template for <a href=...> and <form action=...>
reversable = mapping.get('*', None) or mapping.get('GET', None) or mapping.get('POST', None)
return url(r'^{}$'.format(p), dispatcher, name='.'.join([reversable['src'].__module__, reversable['name']]) if reversable else None)
def as_view(cls, **initkwargs):
view_mapping_kwargs = initkwargs.pop("view_mapping_kwargs", {})
view = super(EndpointSet, cls).as_view(**initkwargs)
def view(request, *args, **kwargs):
self = cls(**initkwargs)
mapping = cls.view_mapping(**view_mapping_kwargs)
for verb, method in mapping.items():
if hasattr(self, method):
setattr(self, verb, getattr(self, method))
self.requested_method = mapping.get(request.method.lower())
self.args = args
self.kwargs = kwargs
self.request = request
return self.dispatch(request, *args, **kwargs)
functools.update_wrapper(view, cls, updated=())
functools.update_wrapper(view, cls.dispatch, assigned=())
return csrf_exempt(view)
def webhook(f):
@csrf_exempt
def new_f(request, *args, **kwargs):
data = json.loads(request.body) or {}
with Context.for_request(request, data) as context:
return f(request, context, data, *args, **kwargs)
return update_wrapper(new_f, f)
def dispatch(self, request, *args, **kwargs):
return super(Sms, self).dispatch(request, *args, **kwargs)
# @method_decorator(csrf_exempt) # here it doesn't work
def service_rpc(request, username, repository):
"""
Responds to 'git-receive-pack' or 'git-upload-pack' requests
for the given username and repository.
Decorator 'csrf_exempt' is used because git POST requests does not provide csrf cookies and
therefore validation cannot be done.
"""
requested_repo = Repo(Repo.get_repository_location(username, repository))
response = GitResponse(service=request.path_info.split('/')[-1], action=GIT_ACTION_RESULT,
repository=requested_repo, data=request.body)
return response.get_http_service_rpc()
def as_view(cls, **init_kwargs):
"""
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.
"""
view = super(View, cls).as_view(**init_kwargs)
view.cls = cls
# Note: session based authentication is explicitly CSRF validated,
# all other authentication is CSRF exempt.
return csrf_exempt(view)
def lock_tokens_csrf_exempt(view):
return csrf_exempt(view) if API_CSRF_EXEMPT else view
def csrf_exempt(view_func):
return view_func
def csrf_exempt(func):
return func
# Django 1.5 has moved this constant up one level.
def get_urls(self):
cs_reply = csrf_exempt(CyberSourceReplyView.as_view())
review_notification = csrf_exempt(DecisionManagerNotificationView.as_view())
fingerprint = FingerprintRedirectView.as_view()
urlpatterns = [
url(r'^cybersource-reply/$', cs_reply, name='cybersource-reply'),
url(r'^decision-manager-review-notification/$', review_notification, name='cybersource-review-notification'),
url(r'^fingerprint/(?P<url_type>.*)/$', fingerprint, name='cybersource-fingerprint-redirect'),
]
return self.post_process_urls(urlpatterns)
def api_view(method):
"""Decorator that forces the view to require a valid
API key in order to be processed.
Calls to the view that do not have an appropriate key
will return a 403 response.
"""
def f(request, *args, **kwargs):
# Ensure that there is an appropriate key attached
# to this request, and return a 401 otherwise.
try:
APIAuth.verify_request(request)
except AuthenticationError as ex:
return HttpResponse(
content=json.dumps({
'code': 403,
'error': unicode(ex).strip("'"),
}),
content_type='application/json',
status=403,
)
# Run the decorated method.
try:
response = method(request, *args, **kwargs)
code = 200
# Sanity check: Did we get a tuple back?
# This shorthand provides me an easy way to send back
# a success response that is not a 200.
if isinstance(response, tuple) and len(response) == 2:
response, code = response
return HttpResponse(
json.dumps({
'code': code,
'data': response,
}, cls=JSONDatetimeEncoder),
content_type='application/json',
status=code,
)
except Http404 as ex:
msg = unicode(ex).strip("'")
return HttpResponse(
content=json.dumps({
'code': 404,
'error': msg if msg else 'not found',
}),
content_type='application/json',
status=404,
)
f = csrf_exempt(f)
return update_wrapper(f, method)
def as_view(cls, actions=None, **initkwargs):
"""
Because of the way class based views create a closure around the
instantiated view, we need to totally reimplement `.as_view`,
and slightly modify the view function that is created and returned.
"""
# The suffix initkwarg is reserved for identifying the viewset type
# eg. 'List' or 'Instance'.
cls.suffix = None
# actions must not be empty
if not actions:
raise TypeError("The `actions` argument must be provided when "
"calling `.as_view()` on a ViewSet. For example "
"`.as_view({'get': 'list'})`")
# sanitize keyword arguments
for key in initkwargs:
if key in cls.http_method_names:
raise TypeError("You tried to pass in the %s method name as a "
"keyword argument to %s(). Don't do that."
% (key, cls.__name__))
if not hasattr(cls, key):
raise TypeError("%s() received an invalid keyword %r" % (
cls.__name__, key))
def view(request, *args, **kwargs):
self = cls(**initkwargs)
# We also store the mapping of request methods to actions,
# so that we can later set the action attribute.
# eg. `self.action = 'list'` on an incoming GET request.
self.action_map = actions
# Bind methods to actions
# This is the bit that's different to a standard view
for method, action in actions.items():
handler = getattr(self, action)
setattr(self, method, handler)
if hasattr(self, 'get') and not hasattr(self, 'head'):
self.head = self.get
# And continue as usual
return self.dispatch(request, *args, **kwargs)
# take name and docstring from class
update_wrapper(view, cls, updated=())
# and possible attributes set by decorators
# like csrf_exempt from dispatch
update_wrapper(view, cls.dispatch, assigned=())
# We need to set these on the view function, so that breadcrumb
# generation can pick out these bits of information from a
# resolved URL.
view.cls = cls
view.initkwargs = initkwargs
view.suffix = initkwargs.get('suffix', None)
view.actions = actions
return csrf_exempt(view)
def as_view(cls, actions=None, **initkwargs):
"""
Because of the way class based views create a closure around the
instantiated view, we need to totally reimplement `.as_view`,
and slightly modify the view function that is created and returned.
"""
# The suffix initkwarg is reserved for identifying the viewset type
# eg. 'List' or 'Instance'.
cls.suffix = None
# actions must not be empty
if not actions:
raise TypeError("The `actions` argument must be provided when "
"calling `.as_view()` on a ViewSet. For example "
"`.as_view({'get': 'list'})`")
# sanitize keyword arguments
for key in initkwargs:
if key in cls.http_method_names:
raise TypeError("You tried to pass in the %s method name as a "
"keyword argument to %s(). Don't do that."
% (key, cls.__name__))
if not hasattr(cls, key):
raise TypeError("%s() received an invalid keyword %r" % (
cls.__name__, key))
def view(request, *args, **kwargs):
self = cls(**initkwargs)
# We also store the mapping of request methods to actions,
# so that we can later set the action attribute.
# eg. `self.action = 'list'` on an incoming GET request.
self.action_map = actions
# Bind methods to actions
# This is the bit that's different to a standard view
for method, action in actions.items():
handler = getattr(self, action)
setattr(self, method, handler)
# Patch this in as it's otherwise only present from 1.5 onwards
if hasattr(self, 'get') and not hasattr(self, 'head'):
self.head = self.get
# And continue as usual
return self.dispatch(request, *args, **kwargs)
# take name and docstring from class
update_wrapper(view, cls, updated=())
# and possible attributes set by decorators
# like csrf_exempt from dispatch
update_wrapper(view, cls.dispatch, assigned=())
# We need to set these on the view function, so that breadcrumb
# generation can pick out these bits of information from a
# resolved URL.
view.cls = cls
view.suffix = initkwargs.get('suffix', None)
return csrf_exempt(view)