Удивительный модуль сообщества

Фибо-приложение

Основы API-интерфейса приложения fibjs

устанавливать

1
npm install fib-app [--save]

Тест

1
npm test

Установить базовый скрипт

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
const http = require('http'); const util = require('util') const Session = require('fib-session') const App = require('../'); var app = new App('sqlite:test.db', { uuid: true }); app.db.use(require('./defs/person')); var session = new Session(new util.LruCache(20000), { timeout: 60 * 1000 }); var svr = new http.Server(8080, [ session.cookie_filter, { '/1.0': app } ]); svr.run();

Где person является модулем определения модели, содержимое выглядит следующим образом:

1 2 3 4 5 6 7
module.exports = db => { db.define('person', { name: String, sex: ["male", "female"], age: Number }); };

Это стандартное определение orm и может также использовать другие функции orm, такие как проверка типов, события и т. Д.

Формат данных API

Для запросов POST и PUT тело запроса должно быть в формате JSON, а Content-Type заголовка HTTP должен быть установлен в application / json.

1 2 3 4
curl -X PUT \ -H "Content-Type: application/json" \ -d '{"name": "tom","sex":"male","age":23}' \ http://localhost/1.0/person/57fbbdb0a2400000

Для всех запросов формат ответа - это объект JSON.

Успешность запроса указывается кодом состояния HTTP. Код состояния 2XX указывает на успех, а код 4XX указывает на ошибку запроса. При сбое запроса тело ответа остается объектом JSON, но оно всегда содержит два поля: код и сообщение, которые можно использовать для отладки. Например, в случае сбоя запроса на авторизацию будет возвращена следующая информация:

1 2 3 4
{ "code": 4030501, "message": "The operation isn’t allowed for clients due to class-level permissions." }

Кодовый код делится на три части, первые три цифры 403 обозначают тип ошибки, 05 обозначает номер таблицы данных, а 01 обозначает подробный код ошибки.

Для запросов GET обычно возвращаются данные объекта. В зависимости от адреса запроса GET может быть возвращен объект или массив. Такие как:

1 2 3 4 5
{ "name": "tom", "sex": "male", "age": 23 }

или:

1 2 3 4 5 6 7 8 9 10 11 12
[ { "name": "tom", "sex": "male", "age": 23 }, { "name": "lily", "sex": "female", "age": 22 } ]

Специальное поле

В данных объекта есть четыре поля со специальным значением, которые нельзя изменять через API. Они id , updatedAt , createdAt , createdBy , createdBy .

id , updatedAt , createdAt отдельных полях, будет автоматически создан и изменен. createdBy должен указать свой собственный тип.

API доступа к базовым объектам

После завершения определения данных у нас есть набор интерфейсных вызовов, соответствующих спецификации API REST:

URL метод действие
/1.0/:className ПОЧТА Создать новый объект
/1.0/:className/:id ПОЛУЧИТЬ Читать объект
/1.0/:className/:id СТАВИТЬ Изменить объект
/1.0/:className/:id УДАЛИТЬ Удалить объект
/1.0/:className ПОЛУЧИТЬ Список объектов запроса

Создать новый объект

Чтобы создать новый объект, необходимо отправить запрос POST на URL-адрес класса, который должен содержать сам объект. Например, чтобы создать объект, описанный выше:

1 2 3 4
curl -X POST \ -H "Content-Type: application/json" \ -d '{"name": "tom","sex":"male","age":23}' \ http://localhost/1.0/person

После успешного создания HTTP-возврата возвращается 201 Created, а тело ответа - это объект JSON, содержащий метку времени objectId и creationAt нового объекта:

1 2 3 4
{ "createdAt": "2017-11-25T01:39:35.931Z", "id": "57fbbdb0a2400000" }

Читать объект

Когда вы создаете объект, вы можете получить его содержимое, отправив запрос GET в местоположение возвращаемого заголовка. Например, чтобы получить объект, который мы создали выше:

1
curl -X GET http://localhost/1.0/person/57fbbdb0a2400000

Возвращаемое тело - это объект JSON, содержащий все предоставленные пользователем поля, а также поля createdAt , updatedAt и id :

1 2 3 4 5 6 7 8
{ "name": "tom", "sex": "male", "age": 23, "createdAt": "2017-11-25T01:39:35.931Z", "updatedAt": "2017-11-25T01:39:35.931Z", "id": "57fbbdb0a2400000" }

Установив поле возвращает keys , можно вернуть настроенный контент, keys к контенту , строки имени поля сегментации:

1
curl -X GET http://localhost/1.0/person/57fbbdb0a2400000?keys=name%2Csex

Вернется:

1 2 3 4
{ "name": "tom", "sex": "male" }

Изменить объект

Чтобы изменить данные, которые уже есть у объекта, вы можете отправить запрос PUT на соответствующий URL-адрес объекта. Любой ключ, который вы не укажете, не изменится, поэтому вы можете обновить только подмножество данных объекта. Например, давайте изменим поле возраста нашего объекта:

1 2 3 4
curl -X PUT \ -H "Content-Type: application/json" \ -d '{"age": 25}' \ http://localhost/1.0/person/57fbbdb0a2400000

updatedAt объект JSON будет содержать updatedAt и id , указывающие, когда произошло обновление:

1 2 3 4
{ "updatedAt": "2017-11-25T01:39:35.931Z", "id": "57fbbdb0a2400000" }

Удалить объект

Чтобы удалить объект, вы можете отправить запрос DELETE на URL указанного объекта, например:

1
curl -X DELETE http://localhost/1.0/person/57fbbdb0a2400000

Список объектов запроса

Вы можете получить несколько объектов одновременно, отправив запрос GET на URL класса без каких-либо параметров URL. Вот простой способ получить всех пользователей:

1
curl -X GET http://localhost/1.0/person

Возвращаемое значение представляет собой объект JSON, содержащий поле результатов, а его значение представляет собой список объектов:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
[ { "name": "tom", "sex": "male", "age": 23, "createdAt": "2017-11-25T01:39:35.931Z", "updatedAt": "2017-11-25T01:39:35.931Z", "id": "57fbbdb0a2400000" }, { "name": "lily", "sex": "female", "age": 22, "createdAt": "2017-11-25T01:39:35.931Z", "updatedAt": "2017-11-25T01:39:35.931Z", "id": "57fbbdb0a2400001" } ]

Настройка ключевых полей

Как и в случае с объектным запросом, вы можете настроить поля, включенные в возвращаемый результат, установив keys при запросе списка. keys содержимого , строки имени поля сегментации, например:

1
curl -X GET http://localhost/1.0/person?keys=name%2Cage

Будет указано, что будут возвращены только два поля name и age .

где фильтр

Объект запроса может быть ограничен через форму, where параметры.

Значение параметра where должно быть закодировано в JSON. То есть, если вы посмотрите на запрос URL, который был фактически выполнен, он должен быть сначала закодирован в JSON, а затем закодирован в URL. Самый простой способ использовать параметр where - включить требуемый ключ и значение. Например, если мы хотим найти пользователя с именем tom, мы должны построить запрос следующим образом:

1
curl -X GET http://localhost/1.0/person?where=%7B%22name%22%3A%22tom%22%7D

where значение - это строка JSON после urlencode, содержимое: {"name":"tom"}

В дополнение к точному соответствию заданному значению, where также поддерживаются методы сравнения, такие как включение. where поддерживает следующие параметры:

ключ операция образец
уравнение равный {"name": {"eq": "tom"}} или {"name": "tom"}
Небраска не равно { "Имя": { "п": "Томь"}}
GT больше чем { "Возраст": { "GT": "24"}}
GTE больше или равно { "Возраст": { "GTE": "24"}}
л Меньше, чем { "Возраст": { "л": "24"}}
Ге Меньше или равно { "Возраст": { "Г": "24"}}
лайк Нечеткий запрос { "Имя": { "как": "% м"}}
не как Нечеткий запрос { "Имя": { "not_like": "% м"}}
между Интервал сравнения { "Возраст": { "между": [22,25]}}
not_between Интервал сравнения { "Возраст": { "not_between": [22,25]}}
в перечисление { "Имя": { "в": [ "Том", "лилии"]}}
не в перечисление { "Имя": { "NOT_IN": [ "Томь", "лилии"]}}
или ИЛИ операция { "Или": [{ "Имя": "Том"}, { "возраст": 24}]}

пропустить пропустить записи

С помощью опции skip вы можете пропустить указанное количество записей, чтобы добиться эффекта перелистывания страниц.

1
curl -X GET http://localhost/1.0/person?skip=100

limit возвращает лимит записи

Через limit вариант, вы можете ограничить количество записей , возвращаемых, эффективное число limit составляет 1-1000, по умолчанию 100.

1
curl -X GET http://localhost/1.0/person?limit=100

порядок определяет метод сортировки

С помощью параметра order вы можете установить метод сортировки возвращенного результирующего набора. Когда имя поля содержит - , оно находится в обратном порядке.

1
curl -X GET http://localhost/1.0/person?order=-id

count возвращает общее количество результатов

Увеличение count при запросе может вернуть общее количество наборов результатов при возврате указанного содержимого.

1
curl -X GET http://localhost/1.0/person?count=1&limit=1

В это время возвращаемый результат будет содержать два поля count и results , которые содержат общее число и результат соответственно:

1 2 3 4 5 6 7 8 9 10 11 12 13
{ "count": 2, "results": [ { "name": "tom", "sex": "male", "age": 23, "createdAt": "2017-11-25T01:39:35.931Z", "updatedAt": "2017-11-25T01:39:35.931Z", "id": "57fbbdb0a2400000" } ] }

Создавайте расширенные объекты

Определяя hasOne и hasMany через orm, отношения между объектами могут быть определены и отражены в API, например:

1 2 3 4 5 6 7 8 9
module.exports = db => { var Person = db.models.person; var Pet = db.define('pet', { name: String }); Person.hasMany('pets', Pet); };

API расширенного доступа к объектам

Ниже приведено определение API для объекта расширения:

URL метод действие
/1.0/:className/:id/:extendName СТАВИТЬ Установить расширенный объект
/1.0/:className/:id/:extendName ПОЧТА Создать объект расширения
/1.0/:className/:id/:extendName/:rid ПОЛУЧИТЬ Читать расширенные объекты
/1.0/:className/:id/:extendName/:rid СТАВИТЬ Изменить расширенные объекты
/1.0/:className/:id/:extendName/:rid УДАЛИТЬ Удалить расширенный объект
/1.0/:className/:id/:extendName ПОЛУЧИТЬ Запрос расширенного списка объектов

Установить расширенный объект

Установка расширенного объекта заключается в установлении связи между двумя независимыми объектами. Например, Том принял домашнее животное по имени кошка, что может быть достигнуто с помощью следующих операций:

1 2 3 4
curl -X PUT \ -H "Content-Type: application/json" \ -d '{"id": "57fbbdb0a2400007"}' \ http://localhost/1.0/person/57fbbdb0a2400000/pets

В вызове, идентификатор кошки должен быть указан в теле.

Создать объект расширения

Непосредственное создание расширенных объектов позволяет устанавливать связи между объектами при их создании. Такие как:

1 2 3 4
curl -X POST \ -H "Content-Type: application/json" \ -d '{"name": "cat"}' \ http://localhost/1.0/person/57fbbdb0a2400000/pets

Создадим питомца по имени кошка и создадим ассоциацию с Томом.

Читать расширенные объекты

Чтение расширенных объектов аналогично чтению базовых объектов, а также поддерживает параметр keys:

1
curl -X GET http://localhost/1.0/person/57fbbdb0a2400000/pets/57fbbdb0a2400007

Изменить расширенные объекты

Чтение расширенных объектов очень похоже на чтение базовых объектов:

1 2 3 4
curl -X PUT \ -H "Content-Type: application/json" \ -d '{"name": "cat 1"}' \ http://localhost/1.0/person/57fbbdb0a2400000/pets/57fbbdb0a2400007

Удалить расширенный объект

Удаление расширенного объекта не удаляет сам объект, а только освобождает связь между объектами:

1
curl -X DETELE http://localhost/1.0/person/57fbbdb0a2400000/pets/57fbbdb0a2400007

Запрос расширенного списка объектов

Список расширенных объектов запроса очень похож на список базовых объектов запроса, а также поддерживает такие параметры, как ключи и условная фильтрация:

1
curl -X GET http://localhost/1.0/person/57fbbdb0a2400000/pets

ACL

Вы можете управлять разрешениями на данные, определяя ACL модели. Такие как:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
const orm = require('fib-orm'); module.exports = db => { db.define('blog', { title: String, detail: String, note: String }, { ACL: function(session) { return { "*": { "*": false }, "57fbbdb0a2400000": { "*": true }, "roles": { "user": { "read": true } } }; } }); };

Если ACL не указан при определении модели, это эквивалентно установке разрешений по умолчанию:

1 2 3 4 5
{ "*": { "*": true } }

основной корпус

Существует три типа описаний тела ACL: id пользователя, role пользователя и * , id представляет конкретного пользователя, role представляет пользователя с определенной ролью, а * представляет всех пользователей:

основной корпус описание приоритет
мне бы Конкретный идентификатор пользователя 1
роль Имя группы пользователей 2
* Все 3

При проверке разрешений сначала будут сопоставляться разрешения, соответствующие id . Если не указано, будут сопоставлены разрешения, соответствующие role пользователя. Если оно все еще указано, проверьте, указано ли разрешение * . Если * не указано, разрешения не будет.

Например, вышеуказанные настройки разрешения указывает , что user группа пользователей может быть прочитан. Пользователь 57fbbdb0a2400000 имеет все разрешения, в то время как другие пользователи не имеют каких - либо разрешений.

Власть

ACL классифицирует разрешения на пять категорий на основе поведения API:

Власть описание Разрешенные типы
Создайте Создать объект истина / ложь / массив
читать Читать объект истина / ложь / массив
записывать Изменить объект истина / ложь / массив
Удалить Удалить объект правда / ложь
найти Список объектов запроса правда / ложь
* Соответствовать всем разрешениям истина / ложь / массив

Разрешения имеют значение true чтобы разрешить доступ, false чтобы запретить доступ, и array чтобы разрешить доступ только к указанным полям. delete и find не принимать array , если array установлен, он считается true . Если указанное разрешение не существует, оно совпадает с разрешением * той же темы. Если ничего не существует, запросите предмет следующего приоритета снова.

Например, в приведенном выше примере, если вам нужно настроить user разрешение только чтения title и detail , а другие могут читать title , вы можете установить его следующим образом:

1 2 3 4 5 6 7 8 9 10 11 12 13 14
{ "*": { "*": false, "read": ['title'] }, "57fbbdb0a2400000": { "*": true }, "roles": { "user": { "read": ['title', 'detail'] } } }

Разрешения на объекты

Полномочия всего класса устанавливаются в модели. Если вам нужно установить разрешения для определенных объектов, вы можете установить OACL для достижения:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
module.exports = db => { db.define('person', { name: String, sex: ["male", "female"], age: Number }, { ACL: function(session) { return { "*": { "*": false } } }, OACL: function(session) { var _acl = {}; if(this.id === session.id) _acl[session.id] = { "*": true }; return _acl; } }); };

В этом примере, когда посетителем является объект, все операции будут разрешены, в противном случае весь доступ запрещен. Разрешения будут проверены в соответствии со следующими шагами:

  • person[57fbbdb0a2400000] => OACL
  • person => ACL

Расширенные права доступа к объекту

Контроль прав доступа к расширенным объектам аналогичен базовым правам объектов, за исключением того, что ACL необходимо указывать отдельно:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41
module.exports = db => { var Person = db.define('person', { name: String, sex: ["male", "female"], age: Number },{ ACL: function(session) { return { "*": { "read": ['name', 'sex'], "extends": { "pets": { "read": true, "find": true } } } } }, OACL: function(session) { var _acl = {}; if(this.id === session.id) _acl[session.id] = { "*": true, "extends": { "pets": { "*": true } } }; return _acl; } }); var Pet = db.define('pet', { name: String }); Person.hasMany('pets', Pet); };

В этом определении каждый может проверить name и sex личной информации, а также свободно искать и искать своих pets . Пользователь сам может использовать все свои собственные данные и иметь все разрешения для своей собственной информации о домашних животных.

При проверке прав доступа к расширенным объектам права на объекты и права на расширенные объекты проверяются отдельно. Например, следующий запрос:

1
curl -X GET http://localhost/1.0/person/57fbbdb0a2400000/pets/57fbbdb0a2400007

Разрешения будут проверены в соответствии со следующими шагами:

  • pets[57fbbdb0a2400007] => OACL
  • person[57fbbdb0a2400000] => OACL => extends => pets
  • person => ACL => extends => pets
  • pets => ACL

функция

API может быть определен для модели, для сложных операций с данными, может быть завершен с помощью пользовательской функции.

Подавляющее большинство разрешений может быть выполнено с помощью управления ACL, без необходимости выполнять основанные на объектах разрешения через Function. Функцию можно использовать для заполнения разрешений на основе данных, таких как предоставление разрешений различным группам пользователей в зависимости от статуса утверждения. И несколько модификаций, таких как необходимость изменения нескольких записей базы данных.

Построить модель данных

После завершения определения данных вы можете использовать app.diagram() нарисовать диаграмму классов формата svg модели данных, и сохранить ее в файл, чтобы получить изображение, похожее на следующее: диаграмма