-
-
Save studentIvan/a06a1e4b0db9486e1795 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(function () { | |
'use strict'; | |
angular.module('project.rpc', []) | |
.factory('$alert', AlertFactory) | |
.factory('$successCallback', SuccessCallbackFactory) | |
.factory('$errorCallback', ErrorCallbackFactory) | |
.factory('$api', ApiFactory); | |
/** @ngInject */ | |
function AlertFactory(toastr) { | |
return { | |
get: function (title, message) { | |
toastr.error('Ошибка!', message); | |
} | |
}; | |
} | |
/** @ngInject */ | |
function SuccessCallbackFactory() { | |
return { | |
get: function () { | |
} | |
}; | |
} | |
/** @ngInject */ | |
function ErrorCallbackFactory($alert) { | |
return { | |
get: function (failData) { | |
var response = failData.responseJSON; | |
var status = failData.status; | |
response = response || { | |
error: 'Server Error' | |
}; | |
if (!status) { | |
status = 412; | |
response = { | |
error: 'Precondition Failed' | |
} | |
} | |
var errors = { | |
400: ['Bad Request', 'Во время выполнения запроса возникла ошибка, ' + | |
'проверьте данные ещё раз и исправьте при необходимости.'], | |
403: ['Forbidden', 'Данное действие для вас запрещено.'], | |
404: ['Not Found', 'Не удалось найти запрашиваемый элемент.'], | |
409: ['Conflict', 'Во время выполнения запроса возникла ошибка конфликта данных.'], | |
412: ['Precondition Failed', 'Неверный запрос, измените его и попробуйте снова.'], | |
423: ['Locked', 'Ресурс из запроса заблокирован от применения к нему указанного метода.'], | |
429: ['Too Many Requests', 'Очень много запросов, попробуйте позже.'], | |
449: ['Retry With', 'Поступило недостаточно информации.'], | |
500: ['Server Error', 'Ошибка сервера.'] | |
}; | |
$alert.get('Ошибка', (errors[status][0] == response.error ? | |
errors[status][1] : response.error)); | |
} | |
}; | |
} | |
/** @ngInject */ | |
function ApiFactory(backendURI, $successCallback, $errorCallback, $document) { | |
return { | |
/** | |
* POST Api Request | |
* Special for Django | |
* You can pass successCallback only instead kwargs | |
* | |
* @param {string} method | |
* @param {object|function} kwargs | |
* @param {function} [successCallback] | |
* @param {function} [errorCallback] | |
* @export | |
*/ | |
call: function (method, kwargs, successCallback, errorCallback) { | |
if (!method) { | |
throw 'You want to select an method'; | |
} | |
/** | |
* Different kinds of call: | |
* post('example', kwargs, success, error) | |
* post('example', success, error) | |
* post('example', success) | |
*/ | |
if (typeof kwargs == 'function' && typeof successCallback == 'function' && !errorCallback) { | |
errorCallback = successCallback; | |
successCallback = kwargs; | |
kwargs = {}; | |
} else if (typeof kwargs == 'function' && !successCallback) { | |
successCallback = kwargs; | |
kwargs = {}; | |
} | |
successCallback = successCallback || $successCallback.get; | |
errorCallback = errorCallback || $errorCallback.get; | |
kwargs = kwargs || {}; | |
kwargs['function'] = method; | |
var csrftoken = /(?:csrftoken=)(.+?)(?:;|$)/.exec($document[0].cookie); | |
if (csrftoken) { | |
csrftoken = csrftoken[1]; | |
} | |
try { | |
jQuery.ajax({ | |
url: backendURI + '/api/?callable_function=' + method, | |
cache: false, | |
crossDomain: true, | |
contentType: 'application/json', | |
data: angular.toJson(kwargs), | |
dataProcess: false, | |
dataType: 'json', | |
method: 'POST', | |
headers: { | |
"X-CSRFToken": csrftoken | |
}, | |
timeout: 20e3, | |
xhrFields: { | |
withCredentials: true | |
} | |
}) | |
.done(successCallback) | |
.fail(errorCallback); | |
} catch (e) { | |
errorCallback({status: 412, responseJSON: {}}); | |
} | |
} | |
}; | |
} | |
}()); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
try { | |
jQuery.ajax({ | |
url: backendURI + '/api/?callable_function=' + method, // ?callable_function нужно для разбора полетов в отладчике браузера | |
cache: false, | |
crossDomain: true, | |
contentType: 'application/json', | |
data: JSON.stringify(kwargs), // angular.toJson в ангуляре | |
dataProcess: false, | |
dataType: 'json', | |
method: 'POST', | |
headers: { | |
"X-CSRFToken": csrftoken // выцепляйте его из кук | |
}, | |
timeout: 20e3, | |
xhrFields: { | |
withCredentials: true | |
} | |
}) | |
.done(successCallback) | |
.fail(errorCallback); | |
} catch (e) { | |
errorCallback({status: 412, responseJSON: {}}); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# -*- coding: utf-8 -*- | |
from __future__ import unicode_literals, print_function, division | |
from django.core.exceptions import ValidationError | |
from django.views.decorators.csrf import ensure_csrf_cookie | |
from django.conf import settings | |
from django.http import JsonResponse | |
from .exceptions import APIException | |
import simplejson as json | |
import traceback | |
import inspect | |
import sys | |
from .api_users import example_another_function # удобнее разнести методы по файлам | |
# region: api methods | |
def demo(**kwargs): | |
return {'ok': 'test'} | |
# endregion | |
functions = dict( | |
inspect.getmembers( | |
sys.modules[__name__], | |
lambda f: inspect.isfunction(f) and f.__module__ in [__name__, 'rpc.api_users'] | |
) | |
) | |
@ensure_csrf_cookie | |
def api_handler_global(request): | |
response, status = dict(), 200 | |
try: | |
data = json.loads(request.body) | |
data['user'] = request.user | |
except json.JSONDecodeError: | |
response['error'], status = 'Bad Request', 400 | |
else: | |
try: | |
if 'function' not in data: | |
raise APIException.retry_with() | |
data['request'] = request | |
function_result = functions[data['function']](**data) | |
if function_result: | |
response['result'] = function_result | |
except APIException as e: | |
response['error'], status = e.message, e.status | |
except AssertionError: | |
response['error'], status = 'Bad Request', 400 | |
except ValidationError as e: | |
response['error'], status = 'Precondition Failed', 412 | |
response['validation_error'] = e.message | |
except Exception as e: | |
if settings.DEBUG: | |
print(traceback.format_exc(), e) | |
response['error'], status = 'Server Error', 500 | |
try: | |
return JsonResponse(response, status=status) | |
except Exception as e: | |
response = dict() | |
if settings.DEBUG: | |
print(traceback.format_exc(), e) | |
response['error'], status = 'Server Error', 500 | |
return JsonResponse(response, status=status) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# coding=utf-8 | |
class APIException(Exception): | |
def __init__(self, status, message='APIException'): | |
self.status = status | |
self.message = message | |
@staticmethod | |
def not_found(message='Not Found'): | |
""" | |
:type message: str or unicode | |
:param message: Error message. | |
:rtype: APIException | |
:return: APIException | |
""" | |
return APIException(404, message) | |
@staticmethod | |
def forbidden(message='Forbidden'): | |
""" | |
:type message: str or unicode | |
:param message: Error message. | |
:rtype: APIException | |
:return: APIException | |
""" | |
return APIException(403, message) | |
@staticmethod | |
def bad_request(message='Bad Request'): | |
""" | |
:type message: str or unicode | |
:param message: Error message. | |
:rtype: APIException | |
:return: APIException | |
""" | |
return APIException(400, message) | |
@staticmethod | |
def conflict(message='Conflict'): | |
""" | |
:type message: str or unicode | |
:param message: Error message. | |
:rtype: APIException | |
:return: APIException | |
""" | |
return APIException(409, message) | |
@staticmethod | |
def locked(message='Locked'): | |
""" | |
:type message: str or unicode | |
:param message: Error message. | |
:rtype: APIException | |
:return: APIException | |
""" | |
return APIException(423, message) | |
@staticmethod | |
def too_many_requests(message='Too Many Requests'): | |
""" | |
:type message: str or unicode | |
:param message: Error message. | |
:rtype: APIException | |
:return: APIException | |
""" | |
return APIException(429, message) | |
@staticmethod | |
def precondition_failed(message='Precondition Failed'): | |
""" | |
:type message: str or unicode | |
:param message: Error message. | |
:rtype: APIException | |
:return: APIException | |
""" | |
return APIException(412, message) | |
@staticmethod | |
def retry_with(message='Retry With'): | |
""" | |
:type message: str or unicode | |
:param message: Error message. | |
:rtype: APIException | |
:return: APIException | |
""" | |
return APIException(449, message) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# ... | |
urlpatterns = [ | |
url(r'^api/$', 'rpc.api.api_handler_global'), # путь к фронт-контроллеру | |
# ... | |
] | |
# ... |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment