fib-app
fibjs applicatie basis API-framework
Installeren
1npm install fib-app [--save]
Test
1npm test
Maak een basisscript
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21const 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();
Waar person
is de module Modeldefinitie, de inhoud is als volgt:
1
2
3
4
5
6
7module.exports = db => {
db.define('person', {
name: String,
sex: ["male", "female"],
age: Number
});
};
Dit is een standaard ORM-definitie en u kunt ook andere ORM-functies gebruiken, zoals typecontrole, gebeurtenissen, enz.
API-gegevensformaat
Voor POST- en PUT-aanvragen moet de hoofdtekst van het verzoek de JSON-indeling hebben en moet het Content-Type van de HTTP-header worden ingesteld op application/json.
1
2
3
4curl -X PUT \
-H "Content-Type: application/json" \
-d '{"name": "tom","sex":"male","age":23}' \
http://localhost/1.0/person/57fbbdb0a2400000
Voor alle verzoeken is het antwoordformaat een JSON-object.
Of een verzoek succesvol was of niet, wordt aangegeven door de HTTP-statuscode. Een statuscode 2XX geeft succes aan, terwijl een statuscode 4XX aangeeft dat het verzoek is mislukt. Wanneer een verzoek mislukt, is de hoofdtekst van het antwoord nog steeds een JSON-object, maar bevat het altijd de code- en berichtvelden, die u kunt gebruiken voor foutopsporing. Als een verzoek om verificatie van toestemming bijvoorbeeld mislukt, wordt de volgende informatie geretourneerd:
1
2
3
4{
"code": 4030501,
"message": "The operation isn’t allowed for clients due to class-level permissions."
}
De codecode bestaat uit drie delen: de eerste drie cijfers 403 vertegenwoordigen het fouttype, 05 vertegenwoordigt het gegevensbladnummer en 01 vertegenwoordigt de gedetailleerde foutcode.
Bij GET-verzoeken worden doorgaans objectgegevens geretourneerd, afhankelijk van het adres van het GET-verzoek kan een object of een array worden geretourneerd. Bijvoorbeeld:
1
2
3
4
5{
"name": "tom",
"sex": "male",
"age": 23
}
of:
1
2
3
4
5
6
7
8
9
10
11
12[
{
"name": "tom",
"sex": "male",
"age": 23
},
{
"name": "lily",
"sex": "female",
"age": 22
}
]
speciale velden
In de objectgegevens bevinden zich vier velden met een speciale betekenis die niet via de API mogen worden gewijzigd. Het zijn respectievelijk id
, updatedAt
, createdAt
.createdBy
id
Onder hen worden automatisch afzonderlijke velden aangemaakt en gewijzigd updatedAt
. Het type dient u zelf op te geven.createdAt
createdBy
Basis-API voor objecttoegang
Na het voltooien van een dergelijke gegevensdefinitie beschikt u direct over een reeks interface-aanroepen die voldoen aan de REST API-specificatie:
URL | methode | actie |
---|---|---|
/1.0/:klassenaam | NA | Nieuw object maken |
/1.0/:klassenaam/:id | KRIJGEN | Voorwerp lezen |
/1.0/:klassenaam/:id | NEERZETTEN | Object wijzigen |
/1.0/:klassenaam/:id | VERWIJDEREN | Object verwijderen |
/1.0/:klassenaam | KRIJGEN | Objectlijst opvragen |
Nieuw object maken
Om een nieuw object te maken, moet een POST-verzoek naar de URL van de klasse worden verzonden, die het object zelf moet bevatten. Om bijvoorbeeld het hierboven weergegeven object te maken:
1
2
3
4curl -X POST \
-H "Content-Type: application/json" \
-d '{"name": "tom","sex":"male","age":23}' \
http://localhost/1.0/person
Wanneer het maken is gelukt, is de HTTP-retour 201 Created en is de hoofdtekst van het antwoord een JSON-object dat de objectId bevat en de tijdstempel createAt van het nieuwe object:
1
2
3
4{
"createdAt": "2017-11-25T01:39:35.931Z",
"id": "57fbbdb0a2400000"
}
Voorwerp lezen
Wanneer u een object maakt, kunt u de inhoud ervan ophalen door een GET-verzoek naar de locatie in de geretourneerde header te sturen. Om bijvoorbeeld het object te krijgen dat we hierboven hebben gemaakt:
1curl -X GET http://localhost/1.0/person/57fbbdb0a2400000
De geretourneerde hoofdtekst is een JSON-object dat alle door de gebruiker opgegeven velden bevat, plus de velden createdAt
, updatedAt
en :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"
}
Door het retourveld in te stellen keys
, kunt u de geretourneerde inhoud aanpassen. keys
Dit is een ,
reeks veldnamen, gescheiden door:
1curl -X GET http://localhost/1.0/person/57fbbdb0a2400000?keys=name%2Csex
zal terugkeren:
1
2
3
4{
"name": "tom",
"sex": "male"
}
Object wijzigen
Om de bestaande gegevens van een object te wijzigen, kunt u een PUT-verzoek sturen naar de corresponderende URL van het object. Sleutels die u niet opgeeft, worden niet gewijzigd, dus u kunt alleen een subset van de objectgegevens bijwerken. Laten we bijvoorbeeld een leeftijdsveld van ons object wijzigen:
1
2
3
4curl -X PUT \
-H "Content-Type: application/json" \
-d '{"age": 25}' \
http://localhost/1.0/person/57fbbdb0a2400000
Het geretourneerde JSON-object bevat updatedAt
en id
velden die aangeven wanneer de update heeft plaatsgevonden:
1
2
3
4{
"updatedAt": "2017-11-25T01:39:35.931Z",
"id": "57fbbdb0a2400000"
}
Object verwijderen
Om een object te verwijderen, kunt u een DELETE-verzoek sturen naar de URL van het opgegeven object, bijvoorbeeld:
1curl -X DELETE http://localhost/1.0/person/57fbbdb0a2400000
Objectlijst opvragen
U kunt meerdere objecten tegelijk verkrijgen door een GET-verzoek naar de URL van de klasse te sturen, zonder enige URL-parameters. Zo krijgt u eenvoudig alle gebruikers:
1curl -X GET http://localhost/1.0/person
De geretourneerde waarde is een JSON-object dat het resultatenveld bevat, waarvan de waarde een lijst met objecten is:
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"
}
]
aanpassing van het sleutelveld
Net als bij objectquery's kunt u keys
de velden in de geretourneerde resultaten aanpassen door deze in te stellen bij het opvragen van de lijst. keys
De inhoud is een ,
reeks veldnamen, gescheiden door bijvoorbeeld:
1curl -X GET http://localhost/1.0/person?keys=name%2Cage
Geeft aan dat alleen de velden name
en age
worden geretourneerd.
waar filterconditie
where
Het queryobject kan worden beperkt in de vorm van parameters.
where
De parameterwaarde moet JSON-gecodeerd zijn. Dat wil zeggen, als u kijkt naar het daadwerkelijke URL-verzoek dat wordt gedaan, moet dit eerst JSON-gecodeerd zijn en vervolgens URL-gecodeerd. De eenvoudigste where
manier om parameters te gebruiken is door de juiste sleutel en waarde op te nemen. Als we bijvoorbeeld willen zoeken naar gebruikers met de naam tom, zouden we de zoekopdracht als volgt opbouwen:
1curl -X GET http://localhost/1.0/person?where=%7B%22name%22%3A%22tom%22%7D
where
De waarde is een urlencoded JSON-tekenreeks, de inhoud is:{"name":"tom"}
Naast het exact matchen van een bepaalde waarde, where
worden ook vergelijkingsmethoden zoals opname ondersteund. where
Parameters ondersteunen de volgende opties:
sleutel | operatie | steekproef |
---|---|---|
gelijk | gelijkwaardig | {"name":{"eq":tom"}} of {"name":tom"} |
ne | niet gelijk aan | {"name":{"ne:tom"}} |
gt | meer dan de | {"leeftijd":{"gt":24"}} |
gte | groter of gelijk aan | {"leeftijd":{"gte":24"}} |
Het | minder dan | {"leeftijd":{"lt":24"}} |
lte | minder dan of gelijk aan | {"leeftijd":{"lte":24"}} |
leuk vinden | vage vraag | {"name":{"like":%m"}} |
niet zoals | vage vraag | {"name":{"not_like":%m"}} |
tussen | Intervalvergelijking | {"leeftijd":{"tussen":[22,25]}} |
niet tussen | Intervalvergelijking | {"leeftijd":{"niet_tussen":[22,25]}} |
in | opsommen | {"naam":{"in":["tom","lelie"]}} |
niet in | opsommen | {"name":{"not_in":["tom","lelie"]}} |
of | OF operatie | {"of":[{"name"tom"},{"age":24}]} |
records overslaan
Via skip
deze optie kunt u het opgegeven aantal records overslaan om het effect van het omslaan van pagina's te bereiken.
1curl -X GET http://localhost/1.0/person?skip=100
limiet retourneert recordlimiet
Via limit
deze optie kunt u het aantal geretourneerde records beperken. limit
De geldige getallen zijn 1-1000 en de standaardwaarde is 100.
1curl -X GET http://localhost/1.0/person?limit=100
order specificeert de sorteermethode
Gebruik order
de optie om de sorteermethode van de geretourneerde resultatenset in te stellen. Wanneer de veldnaam ervoor staat, -
is deze in omgekeerde volgorde.
1curl -X GET http://localhost/1.0/person?order=-id
count retourneert het totale aantal resultaten
Op verzoek verhoogd count
Het totale aantal resultatenets dat kan worden geretourneerd terwijl de opgegeven inhoud wordt geretourneerd.
1curl -X GET http://localhost/1.0/person?count=1&limit=1
Op dit moment bevat het geretourneerde resultaat twee velden: count
en results
, die respectievelijk het totale aantal en het resultaat bevatten:
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"
}
]
}
Maak een uitbreidingsobject
Door hasOne en hasMany te definiëren via ORM, kunt u de associatie tussen objecten definiëren en deze weergeven in de API, bijvoorbeeld:
1
2
3
4
5
6
7
8
9module.exports = db => {
var Person = db.models.person;
var Pet = db.define('pet', {
name: String
});
Person.hasMany('pets', Pet);
};
Uitgebreide API voor objecttoegang
Hieronder volgt de API-definitie van het uitbreidingsobject:
URL | methode | actie |
---|---|---|
/1.0/:className/:id/:extendName | NEERZETTEN | Extensieobject instellen |
/1.0/:className/:id/:extendName | NA | Extensieobject maken |
/1.0/:className/:id/:extendName/:rid | KRIJGEN | Extensieobject lezen |
/1.0/:className/:id/:extendName/:rid | NEERZETTEN | Wijzig extensieobject |
/1.0/:className/:id/:extendName/:rid | VERWIJDEREN | Uitgebreid object verwijderen |
/1.0/:className/:id/:extendName | KRIJGEN | Uitgebreide objectlijst opvragen |
Extensieobject instellen
Het instellen van een uitbreidingsobject is het tot stand brengen van een relatie tussen twee onafhankelijke objecten. Als Tom bijvoorbeeld een huisdier met de naam kat adopteert, kan hij de volgende handelingen gebruiken om dit te bereiken:
1
2
3
4curl -X PUT \
-H "Content-Type: application/json" \
-d '{"id": "57fbbdb0a2400007"}' \
http://localhost/1.0/person/57fbbdb0a2400000/pets
Bij de oproep moet de ID van de kat in de hoofdtekst worden opgegeven.
Extensieobject maken
Door rechtstreeks uitgebreide objecten te maken, kunnen verbindingen tussen objecten tot stand worden gebracht terwijl objecten worden gemaakt. Bijvoorbeeld:
1
2
3
4curl -X POST \
-H "Content-Type: application/json" \
-d '{"name": "cat"}' \
http://localhost/1.0/person/57fbbdb0a2400000/pets
Er wordt een huisdier met de naam kat gemaakt en aan Tom gekoppeld.
Extensieobject lezen
Het lezen van uitgebreide objecten lijkt sterk op het lezen van basisobjecten, en ondersteunt ook de sleuteloptie:
1curl -X GET http://localhost/1.0/person/57fbbdb0a2400000/pets/57fbbdb0a2400007
Wijzig extensieobject
Het lezen van uitgebreide objecten lijkt sterk op het lezen van basisobjecten:
1
2
3
4curl -X PUT \
-H "Content-Type: application/json" \
-d '{"name": "cat 1"}' \
http://localhost/1.0/person/57fbbdb0a2400000/pets/57fbbdb0a2400007
Uitgebreid object verwijderen
Als u een uitgebreid object verwijdert, wordt het object zelf niet verwijderd, maar wordt alleen de relatie tussen de objecten opgeheven:
1curl -X DETELE http://localhost/1.0/person/57fbbdb0a2400000/pets/57fbbdb0a2400007
Uitgebreide objectlijst opvragen
Het opvragen van de uitgebreide objectlijst lijkt sterk op het opvragen van de basisobjectlijst, en ondersteunt ook opties zoals sleutels en voorwaardelijke filtering:
1curl -X GET http://localhost/1.0/person/57fbbdb0a2400000/pets
ACL
Gegevensmachtigingen kunnen worden beheerd door de ACL van het model te definiëren. Bijvoorbeeld:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25const 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
}
}
};
}
});
};
Als er geen ACL is opgegeven bij het definiëren van het model, komt dit overeen met het instellen van de standaardmachtigingen:
1
2
3
4
5{
"*": {
"*": true
}
}
centrale gedeelte
Er zijn drie soorten ACL-onderwerpbeschrijvingen: user id
, user role
en *
, id
die een specifieke gebruiker vertegenwoordigen, role
gebruikers met een bepaalde rol vertegenwoordigen en *
alle gebruikers vertegenwoordigen:
centrale gedeelte | beschrijven | prioriteit |
---|---|---|
ID kaart | specifieke gebruikers-ID | 1 |
rol | Naam van gebruikersgroep | 2 |
* | Alle | 3 |
Bij het controleren van de machtigingen worden eerst id
de bijbehorende machtigingen vergeleken. Als deze niet zijn opgegeven, komen deze overeen met role
de overeenkomstige machtigingen van de gebruiker. Als deze nog steeds zijn opgegeven, controleert u of *
de machtigingen zijn opgegeven. Als deze *
niet zijn opgegeven, is er geen machtiging.
In de bovenstaande machtigingsconfiguratie user
is de gebruikersgroep bijvoorbeeld gespecificeerd om te kunnen lezen. De gebruiker 57fbbdb0a2400000
heeft alle machtigingen, maar andere gebruikers hebben geen machtigingen.
Rechten
ACL classificeert machtigingen in vijf categorieën op basis van API-gedrag:
Rechten | beschrijven | toegestane soorten |
---|---|---|
creëren | Object maken | waar/onwaar/matrix |
lezen | Voorwerp lezen | waar/onwaar/matrix |
schrijven | Object wijzigen | waar/onwaar/matrix |
verwijderen | Object verwijderen | waar onwaar |
vinden | Objectlijst opvragen | waar onwaar |
* | Match alle rechten | waar/onwaar/matrix |
Er zijn machtigingen ingesteld true
om toegang toe te staan, false
toegang te weigeren en array
alleen toegang tot bepaalde velden toe te staan. delete
en find
worden niet geaccepteerd en worden op dezelfde manier behandeld array
als ze zijn ingesteld . Als de opgegeven toestemming niet bestaat, worden de rechten onder hetzelfde onderwerp gematcht. Als geen van beide bestaat, vraag dan opnieuw naar het onderwerp van het volgende prioriteitsniveau.array
true
*
Als u in het bovenstaande voorbeeld bijvoorbeeld user
alleen lezen wilt instellen title
en detail
anderen wilt laten lezen title
, kunt u dit als volgt instellen:
1
2
3
4
5
6
7
8
9
10
11
12
13
14{
"*": {
"*": false,
"read": ['title']
},
"57fbbdb0a2400000": {
"*": true
},
"roles": {
"user": {
"read": ['title', 'detail']
}
}
}
Objectmachtigingen
De machtigingen die voor het model zijn ingesteld, zijn de machtigingen van de hele klasse. Als u machtigingen voor specifieke objecten wilt instellen, kunt u dit doen door OACL in te stellen:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24module.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;
}
});
};
In dit voorbeeld, wanneer de bezoeker zelf het object is, zijn alle handelingen toegestaan, anders is alle toegang verboden. Machtigingen worden als volgt gecontroleerd:
person[57fbbdb0a2400000]
=>OACL
person
=>ACL
Uitgebreide objectmachtigingen
Het beheer van de toegangsrechten van uitgebreide objecten is vergelijkbaar met de rechten van basisobjecten. Het enige verschil is dat de ACL afzonderlijk moet worden opgegeven:
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
41module.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);
};
In deze definitie kan iedereen de name
som van persoonlijke informatie controleren sex
en vrijelijk controleren en doorzoeken pets
. De gebruiker kan zelf al zijn eigen gegevens beheren en heeft volledige rechten voor zijn eigen huisdierinformatie.
Bij het controleren van toegangsrechten voor uitgebreide objecten worden objectrechten en uitgebreide objectrechten afzonderlijk gecontroleerd. Bijvoorbeeld het volgende verzoek:
1curl -X GET http://localhost/1.0/person/57fbbdb0a2400000/pets/57fbbdb0a2400007
Machtigingen worden als volgt gecontroleerd:
pets[57fbbdb0a2400007]
=>OACL
person[57fbbdb0a2400000]
=>OACL
=>extends
=>pets
person
=>ACL
=>extends
=>pets
pets
=>ACL
Functie
API's kunnen voor het model worden gedefinieerd en complexe gegevensbewerkingen kunnen worden voltooid via aangepaste functies.
De meeste machtigingen kunnen worden beheerd via ACL, en objectgebaseerde machtigingen hoeven niet via Function te worden geïmplementeerd. De functie kan worden gebruikt om op gegevens gebaseerde machtigingen te voltooien, zoals het verlenen van machtigingen aan verschillende gebruikersgroepen op basis van de goedkeuringsstatus. En meerdere wijzigingen, zoals de noodzaak om meerdere databaserecords te wijzigen.
Gegevensmodel tekenen
Nadat u de gegevensdefinitie heeft voltooid, kunt u app.diagram()
het indelingsklassediagram van het gegevensmodel tekenen svg
. Wanneer u het opslaat in een bestand, krijgt u een afbeelding die er ongeveer als volgt uitziet: