De RESTful API bestaat uit twee hoofdconcepten: hulpbron, en Vertegenwoordiging. Resource kan elk object zijn dat is gekoppeld aan gegevens, of kan worden geïdentificeerd met een URI (meer dan één URI kan verwijzen naar dezelfde bron) en kan worden uitgevoerd met behulp van HTTP-methoden. Vertegenwoordiging is de manier waarop u de bron weergeeft. In deze tutorial behandelen we enkele theoretische informatie over RESTful API-ontwerp en implementeren we een voorbeeld van een API voor het bloggen met NodeJS.
Het kiezen van de juiste bronnen voor een RESTful API is een belangrijk onderdeel van het ontwerpen. Allereerst moet u uw bedrijfsdomein analyseren en vervolgens beslissen hoeveel en welke hulpbronnen worden gebruikt die relevant zijn voor uw bedrijfsbehoeften. Als u een blog-API ontwerpt, zult u deze waarschijnlijk gebruiken Artikel, Gebruiker, en Commentaar. Dat zijn de resourcenamen, en de bijbehorende gegevens zijn de bron zelf:
"title": "RESTful API ontwerpen", "content": "RESTful API-ontwerp is een zeer belangrijk geval in de wereld van softwareontwikkeling.", "author": "huseyinbabal", "tags": ["technology" , "nodejs", "node-restify"] "category": "NodeJS"
U kunt doorgaan met een bewerking van de resource nadat u de benodigde resources hebt gekozen. Bewerking verwijst hier naar HTTP-methoden. Als u bijvoorbeeld een artikel wilt maken, kunt u het volgende verzoek doen:
POST / artikelen HTTP / 1.1 Host: localhost: 3000 Inhoudstype: application / json "title": "RESTful API Design with Restify", "slug": "restful-api-design-with-restify", "content" : "Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas.", "Auteur": "huseyinbabal"
Op dezelfde manier kunt u een bestaand artikel bekijken door de volgende aanvraag in te dienen:
GET / articles / 123456789012 HTTP / 1.1 Host: localhost: 3000 Inhoudstype: toepassing / json
Hoe zit het met het bijwerken van een bestaand artikel? Ik kan horen dat je zegt:
Ik kan een ander POST-verzoek doen naar / articles / update / 123456789012 met de payload.
Misschien beter, maar de URI wordt steeds complexer. Zoals we eerder al zeiden, kunnen bewerkingen verwijzen naar HTTP-methoden. Dit betekent, vermeld de bijwerken operatie in de HTTP-methode in plaats van dat in de URI. Bijvoorbeeld:
PUT / articles / 123456789012 HTTP / 1.1 Host: localhost: 3000 Inhoudstype: application / json "title": "Bijgewerkt hoe RESTful API te ontwerpen", "inhoud": "Bijgewerkt RESTful API-ontwerp is een zeer belangrijk geval in de software development world. "," author ":" huseyinbabal "," tags ": [" technology "," nodejs "," restify "," one more tag "]" category ":" NodeJS "
Trouwens, in dit voorbeeld zie je tags en categorievelden. Dit hoeven geen verplichte velden te zijn. Je kunt ze leeg laten en ze in de toekomst instellen.
Soms moet je een artikel verwijderen als het verouderd is. In dat geval kunt u een DELETE HTTP-aanvraag voor / Artikelen / 123456789012.
HTTP-methoden zijn standaardconcepten. Als u ze als bewerking gebruikt, heeft u eenvoudige URI's en een dergelijke eenvoudige API helpt u gelukkige consumenten te werven.
Wat als u een opmerking wilt toevoegen aan een artikel? U kunt het artikel selecteren en een nieuwe opmerking toevoegen aan het geselecteerde artikel. Door deze verklaring te gebruiken, kunt u de volgende aanvraag gebruiken:
POST / articles / 123456789012 / comments HTTP / 1.1 Host: localhost: 3000 Content-Type: application / json "text": "Wow! Dit is een goede tutorial", "auteur": "john doe"
De bovenstaande vorm van resource wordt genoemd als een sub-resource. Commentaar is een subresource van Artikel. De Commentaar bovenstaande payload wordt als een kind van. in de database ingevoegd Artikel. Soms verwijst een andere URI naar dezelfde bron. Als u bijvoorbeeld een specifieke opmerking wilt bekijken, kunt u een van de volgende gebruiken:
GET / articles / 123456789012 / Reacties / 123 HTTP / 1.1 Host: localhost: 3000 Inhoudstype: toepassing / json
of:
GET / comments / 123456789012 HTTP / 1.1 Host: localhost: 3000 Inhoudstype: toepassing / json
Over het algemeen veranderen API-functies regelmatig om nieuwe functies aan consumenten te bieden. In dat geval kunnen er tegelijkertijd twee versies van dezelfde API bestaan. Als u deze twee functies wilt scheiden, kunt u versiebeheer gebruiken. Er zijn twee vormen van versiebeheer
/v1.1/articles/123456789012
. GET / articles / 123456789012 HTTP / 1.1 Host: localhost: 3000 Accepteer-versie: 1.0
In feite verandert de versie alleen de weergave van de bron, niet het concept van de bron. U hoeft dus de URI-structuur niet te wijzigen. In v1.1 is misschien een nieuw veld toegevoegd aan Artikel. Het geeft echter nog steeds een artikel terug. In de tweede optie is de URI nog steeds eenvoudig en hoeven consumenten hun URI niet te wijzigen in client-side implementaties.
Het is belangrijk om een strategie te ontwerpen voor situaties waarin de consument geen versienummer verstrekt. U kunt een foutmelding geven als de versie niet beschikbaar is, of u kunt een antwoord retourneren door de eerste versie te gebruiken. Als u de nieuwste stabiele versie als standaard gebruikt, kunnen consumenten veel fouten maken voor implementaties aan de clientzijde.
Representatie is de manier waarop een API de resource weergeeft. Wanneer u een API-eindpunt belt, krijgt u een resource terug. Deze bron kan in elk formaat zijn zoals XML, JSON, etc. JSON heeft de voorkeur als u een nieuwe API ontwerpt. Als u echter een bestaande API bijwerkt die een XML-antwoord heeft geretourneerd, kunt u een andere versie van een JSON-antwoord opgeven.
Dat is genoeg theoretische informatie over RESTful API-ontwerp. Laten we eens kijken naar het dagelijks gebruik door een Blogging-API te ontwerpen en implementeren met Restify.
Om een RESTful API te ontwerpen, moeten we het bedrijfsdomein analyseren. Dan kunnen we onze middelen definiëren. In een blog-API moeten we:
In deze API ga ik niet in op het verifiëren van een gebruiker om een artikel of opmerking te maken. Voor het authenticatiedeel kunt u verwijzen naar de Token-Based Authentication met de instructie AngularJS & NodeJS.
Onze resourcenamen zijn klaar. Resource-bewerkingen zijn eenvoudig CRUD. U kunt de volgende tabel raadplegen voor een algemene showcase van API.
Naam van de bron | HTTP-werkwoorden | HTTP-methoden |
---|---|---|
Artikel | maak een artikel update artikel verwijder artikel bekijk artikel | POST / artikelen met Payload PUT / artikelen / 123 met payload VERWIJDEREN / artikelen / 123 GET / artikel / 123 |
Commentaar | maak een reactie update Coment verwijder commentaar bekijk de opmerking | POST / artikelen / 123 / opmerkingen met Payload PUT / opmerkingen / 123 met payload VERWIJDEREN / opmerkingen / 123 GET / opmerkingen / 123 |
Gebruiker | maak Gebruiker aan update Gebruiker Verwijder gebruiker bekijk Gebruiker | POST / gebruikers met Payload PUT / gebruikers / 123 met payload DELETE / gebruikers / 123 GET / gebruikers / 123 |
In dit project zullen we gebruiken NodeJS met Restify. De bronnen worden opgeslagen in de MongoDB database. Allereerst kunnen we resources definiëren als modellen in Restify.
var mongoose = vereisen ("mangoest"); var Schema = mongoose.Schema; var ArticleSchema = new Schema (title: String, slug: String, content: String, author: type: String, ref: "User"); mongoose.model ('Article', ArticleSchema);
var mongoose = vereisen ("mangoest"); var Schema = mongoose.Schema; var CommentSchema = new Schema (text: String, article: type: String, ref: "Article", auteur: type: String, ref: "User"); mongoose.model ('Reactie', CommentSchema);
Er vindt geen bewerking plaats voor de gebruikersresource. We gaan ervan uit dat we de huidige gebruiker al kennen die in staat is om op artikelen of opmerkingen te reageren.
Je kunt je afvragen waar deze mongoesmodule vandaan komt. Het is het meest populaire ORM-framework voor MongoDB geschreven als een NodeJS-module. Deze module is opgenomen in het project binnen een ander configuratiebestand.
Nu kunnen we onze HTTP-werkwoorden definiëren voor de bovenstaande bronnen. Je kunt het volgende zien:
var restify = require ('restify'), fs = require ('fs') var controllers = , controllers_path = process.cwd () + '/ app / controllers' fs.readdirSync (controllers_path) .forEach (functie (bestand ) if (file.indexOf ('. js')! = -1) controllers [file.split ('.') [0]] = vereisen (controllers_path + '/' + file)) var server = restify.createServer (); server .use (restify.fullResponse ()) .use (restify.bodyParser ()) // Artikel Start server.post ("/ articles", controllers.article.createArticle) server.put ("/ articles /: id", controllers.article.updateArticle) server.del ("/ articles /: id", controllers.article.deleteArticle) server.get (path: "/ articles /: id", version: "1.0.0", controllers. article.viewArticle) server.get (path: "/ articles /: id", version: "2.0.0", controllers.article.viewArticle_v2) // Article End // Comment Start server.post ("/ comments" , controllers.comment.createComment) server.put ("/ comments /: id", controllers.comment.viewComment) server.del ("/ comments /: id", controllers.comment.deleteComment) server.get ("/ opmerkingen /: id ", controllers.comment.viewComment) // Commentaar End var port = process.en VAARTPORT || 3000; server.listen (poort, functie (err) if (err) console.error (err) else console.log ('App is klaar om:' + poort)) if (process.env.environment == 'production' ) process.on ('uncaughtException', function (err) console.error (JSON.parse (JSON.stringify (err, ['stack', 'message', 'inner'], 2))))
In dit codefragment worden in de eerste plaats de controllerbestanden met controllermethoden herhaald en worden alle controllers geïnitialiseerd om een specifiek verzoek voor de URI uit te voeren. Hierna worden URI's voor specifieke bewerkingen gedefinieerd voor standaard CRUD-bewerkingen. Er is ook versiebeheer voor een van de bewerkingen op Artikel.
Als u bijvoorbeeld de versie opgeeft als 2
in de header Accept-Version, viewArticle_v2
zal worden uitgevoerd. viewArticle
en viewArticle_v2
beide doen hetzelfde werk, tonen de resource, maar ze tonen Article Resource in een ander formaat, zoals je kunt zien in de titel
onderstaande veld. Ten slotte wordt de server gestart op een specifieke poort en worden enkele foutenrapportcontroles toegepast. We kunnen doorgaan met controlemechanismemethoden voor HTTP-bewerkingen op bronnen.
var mongoose = require ('mongoose'), Article = mongoose.model ("Article"), ObjectId = mongoose.Types.ObjectId exportss.createArticle = function (req, res, next) var articleModel = new Article (req.body ); articleModel.save (functie (err, artikel) if (err) res.status (500); res.json (type: false, data: "Fout opgetreden:" + err) else res.json ( type: true, data: article)) exports.viewArticle = function (req, res, next) Article.findById (new ObjectId (req.params.id), function (err, article) if ( err) res.status (500); res.json (type: false, data: "Fout opgetreden:" + err) else if (article) res.json (type: true, data: article ) else res.json (type: false, data: "Article:" + req.params.id + "not found")) exports.viewArticle_v2 = function (req, res, next) Article.findById (nieuwe ObjectId (req.params.id), functie (err, artikel) if (err) res.status (500); res.json (type: false, data: "Fout opgetreden:" + err) else if (article) article.title = article.title + "v2" res.json (type: true, data: article) else res.json (type: false, data : "Artikel:" + req.params.id + "not found")) exports.updateArticle = function (req, res, next) var updatedArticleModel = nieuw artikel (req.body); Article.findByIdAndUpdate (nieuwe ObjectId (req.params.id), updatedArticleModel, function (err, article) if (err) res.status (500); res.json (type: false, data: "Fout opgetreden: "+ err) else if (article) res.json (type: true, data: article) else res.json (type: false, data:" Article: "+ req.params. id + "niet gevonden")) exports.deleteArticle = function (req, res, next) Article.findByIdAndRemove (new Object (req.params.id), function (err, article) if (err ) res.status (500); res.json (type: false, data: "Fout opgetreden:" + err) else res.json (type: true, data: "Article:" + req. params.id + "succesvol verwijderd"))
Je kunt een uitleg vinden van de basis CRUD-bewerkingen aan de kant van de Mongoose hieronder:
articleModel
verzonden van de verzoekende instantie. Er kan een nieuw model worden gemaakt door de hoofdtekst van het verzoek door te geven als een constructor naar een model zoals var articleModel = nieuw artikel (req.body)
. vind een
met een ID-parameter is genoeg om artikeldetails te retourneren.opslaan
commando.findByIdAndRemove
is de beste manier om een artikel te verwijderen door het artikel-ID op te geven.De Mongoose-commando's die hierboven zijn genoemd, zijn gewoon statisch als methode door middel van het voorwerp van het Artikel dat ook een verwijzing is naar het Mongoose-schema.
var mongoose = require ('mongoose'), Comment = mongoose.model ("Reactie"), Article = mongoose.model ("Article"), ObjectId = mongoose.Types.ObjectId exports.viewComment = function (req, res) Article.findOne ("comments._id": nieuwe ObjectId (req.params.id), "comments. $": 1, function (err, comment) if (err) res.status (500) ; res.json (type: false, data: "Fout opgetreden:" + err) else if (comment) res.json (type: true, data: new Comment (comment.comments [0]) ) else res.json (type: false, data: "Commentaar:" + req.params.id + "not found")) exports.updateComment = function (req, res, next) var updatedCommentModel = nieuwe opmerking (req.body); console.log (updatedCommentModel) Article.update ("comments._id": nieuwe ObjectId (req.params.id), "$ set": "comments. $. text": updatedCommentModel.text, "comments. $ .author ": updatedCommentModel.author, function (err) if (err) res.status (500); res.json (type: false, data:" Fout opgetreden: "+ err) else res.json (type: true, data: "Commentaar:" + req.params.id + "updated")) exports.deleteComment = function (req, res, next) Article.findOneAndUpdate ( "comments._id": nieuw ObjectId (req.params.id), "$ pull": "comments": "_id": nieuw ObjectId (req.params.id), function (err, artikel) if (err) res.status (500); res.json (type: false, data: "Fout opgetreden:" + err) else if (article) res.json (type: waar, data: artikel) else res.json (type: false, data: "Reactie:" + req.params.id + "not found"))
Wanneer u een verzoek indient bij een van de resource-URI's, wordt de gerelateerde functie die in de controller wordt vermeld, uitgevoerd. Elke functie binnen de controllerbestanden kan de req en res voorwerpen. De commentaar bron hier is een subresource van Artikel. Alle querybewerkingen worden uitgevoerd via het artikelmodel om een subdocument te vinden en de benodigde update uit te voeren. Wanneer u echter een Commentaarbron probeert te bekijken, zult u er een zien, zelfs als er geen verzameling is in MongoDB.
/ Artikelen / 123
(Goed), / Artikelen? Id = 123
(Slecht).Als u ten slotte een RESTful API ontwerpt door deze fundamentele regels te volgen, heeft u altijd een flexibel, onderhoudbaar en gemakkelijk te begrijpen systeem.