Skip to content

Instantly share code, notes, and snippets.

@studentIvan
Last active December 13, 2015 21:27
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save studentIvan/a06a1e4b0db9486e1795 to your computer and use it in GitHub Desktop.
Save studentIvan/a06a1e4b0db9486e1795 to your computer and use it in GitHub Desktop.
(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: {}});
}
}
};
}
}());
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: {}});
}
# -*- 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)
# 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)
# ...
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