Site icon Blog ARC Optimizer

Comment créer une API RESTful avec Deno


Dans cet article, nous allons créer une API de contact à part entière avec Deno – un runtime simple, moderne et sécurisé pour JavaScript et TypeScript qui utilise V8 et est construit avec Rust.

Dans la première partie de cette série nous avons abordé les principes fondamentaux de Deno, et également couvert des choses comme les fonctionnalités, la bibliothèque standard, l'installation et bien plus encore. Dans cet article, nous allons créer une API RESTful. Si vous êtes un novice total de la programmation côté serveur, cet article vous mettra à l'aise avec le runtime.

Voici une liste de quelques microframeworks REST pour Deno:

Nous allons utiliser le framework abc pour construire le contact API.

L'API que nous allons construire pourra:

  • Créer un contact et le stocker dans une base de données MongoDB
  • Récupérer un ou plusieurs contacts de la base de données en fonction de la demande
  • Mettre à jour un contact existant dans la base de données
  • Supprimez tout contact de la base de données sur demande

Nous le ferons dans TypeScript, mais rien ne vous empêche de créer l'API en JavaScript – vous pouvez supprimer les types, et vous êtes prêt à

PS: Dans le post précédent j'ai déjà expliqué comment installer Deno, alors n'hésitez pas à vérifier cela, ou suivez l'installation officielle de denoland sur githhub .

Configurer MongoDB Atlas

Pour pouvoir utiliser MongoDB services cloud, vous aurez besoin d'un compte MongoDB Atlas. Pour en créer un, accédez à sa page d'accueil et inscrivez-vous ou connectez-vous si vous avez un compte.

docs . Maintenant, nous devons créer un cluster pour notre projet, donc cliquez sur Build a Cluster .

Configurer le serveur

Créez un répertoire de projet:

 mkdir contactAPI

Créez un fichier .env :

 touch .env

Dans le fichier .env créez un nom de base de données et collez la chaîne de connexion que nous avons copiée précédemment à partir de MongoDB:

 DB_NAME = 
DB_HOST_URL = 

Ensuite, créez un dossier appelé utils et à l'intérieur, créez un fichier middleware.ts :

 mkdir utils
toucher middlewares.ts

Ci-dessous, nous avons deux middlewares mis en place, pour la journalisation de chaque requête et pour gérer les erreurs détectées dans les contrôleurs:


 import   { MiddlewareFunc  Context } [19659060] de   "https://deno.land/x/abc@v1.0.0-rc2/mod.ts" ; 
 export   class   ErrorHandler   s'étend   ] Erreur   {
status :   numéro ; 
 constructeur  ( message :   string  status :   numéro [19659062])   {
 super  ( message ) ; 
 this .  status  =  status  ; 
} 
} 

 export   const  LogMiddleware :   MiddlewareFunc   =   ( next )   => 
 async   ( c )   =>   {
 const  start  =  Date .  now [19659062] () 
 const   { method  url  proto }   =  c  .  demande
 attendre   suivant  ( c ) ; 
console .  log  ( JSON .  stringify  ( {
heure :   Date  () 
méthode 
url 
proto 
response_time :  Date .  now  ()   -  start  +   "millisecond" 
response_status :  c .  response .  status
}   null   " t" ) ) 
} 


 export   const  ErrorMiddleware  :   MiddlewareFunc   =   ( next )   => 
 async   ( c )   =>   [19659062])   {
 const  error  =  err  as  ErrorHandler ; 
c .  response .  status  =  error .  status  ||   500 ; 
c .  response .  body  =  error .  message ; 
} 
} ; 

Il est maintenant temps d'écrire le code de notre serveur. Commençons par créer un fichier main.ts dans le répertoire du projet:

 touch main.ts

 import   { Application }   de   "https://deno.land/x/abc@v1.0.0-rc2/mod.ts" ; 
 import   "https://deno.land/x/dotenv/load.ts" ; 
 import   {
getAllContact 
createContact 
getOneContact 
updateContact 
deleteContact 
}   from   "./ controllers / contacts.ts" ; 
 import   {
ErrorMiddleware 
LogMiddleware
}   de   "./ utils / middlewares.ts" ; 
 const  app  =   new   Application  ( ]) ; 
app .  use  ( LogMiddleware ) 
.  use  ( ErrorMiddleware ) 
app .  get  ( "/ contacts"  getAllContact ) 
.  post  ( "/ contact " createContact ) 
.  get  (" / contact /: id " getOneContact ) 
 .  put  ( "/ contact /: id"  updateContact ) 
.  delete  ( "/ contact / : id " deleteContact ) 
.  start  ( { port :   5000  }  ) ; 
console .  log  ( `serveur écoutant sur http: // localhost: 5000`  ) ; 

Dans la première ligne, remarquez comment nous importons des modules d'Internet directement en utilisant l'URL.

La deuxième ligne importe le module dotenv pour charger les variables d'environnement à partir du fichier .env. Le reste du code est similaire à express, rien de spécial.

Maintenant, nous devons configurer notre base de données pour interagir avec le serveur. Nous allons utiliser deno_mongo un pilote de base de données MongoDB développé pour Deno. Il est en cours de développement actif et ne contient pas pour l'instant les différentes méthodes d'un pilote MongoDB complet.

 mkdir models
touchez db.ts

 import   { init  MongoClient }   de   "https://deno.land/x/mongo@v0.8.0/mod. ts "; 
 class   DB   {
 public  client :  MongoClient ; 
 constructor  ( public  dbName :   string   public  url :   string )   {
 this .  ] dbName  =  dbName ; 
 this .  url  =  url ; 
 this .  client  =   {}   as  MongoClient ; 
} 
 connect  ()   {
 const  client  =   nouveau   MongoClient  () ; 
client .  connectWithUri  ( this .  url ) ; 
 this .  client  =  client ; 
} 
 get   getDatabase  ()   {
 return   this .  client  .  base de données  ( this .  dbName ) ; 
} 
} 
 const  dbName  =  Deno .  env .  get  ( "DB_NAME" )   ||   "contactdb" ; [19659063] const  dbHostUrl  =  Deno .  env .  get  ( "DB_HOST_URL" )   || [19659061] "mongodb: // localhost: 27017" ; 
console .  log  ( dbName  dbHostUrl ) 
 const  db  =   new   DB [19659062] ( dbName  dbHostUrl ) ; 
db .  connect  () ; 
 export   default  db ; 

Ici, j'ai créé une classe DB ; puis, j'ai instancié la classe avec le paramètre DB_NAME et DB_HOST_URL récupéré à partir de la variable d'environnement.

REMARQUE: Deno.env.get () est utilisé pour récupérer la variable d'environnement we défini plus tôt.

Maintenant, il est temps de configurer nos contrôleurs.

 contrôleurs mkdir
touch contracts.ts

 import   { HandlerFunc  Context }   from   "https://deno.land/x/abc@v1.0.0-rc2/ mod.ts "; 
 import  db  from   '../ models / db.ts' ; 
 import   { ErrorHandler }   de   "../ utils / middlewares.ts" 
 const  database  =  db .  getDatabase ; [19659063] const  contacts  =  base de données .  collection  ( 'contacts' ) ; 
 interface   Contact [19659059] {
_id :   {
  $ oid :   chaîne ; 
} ; 
nom :   chaîne ; 
âge :   numéro ; 
email :   chaîne ; 
adresse :   chaîne ; 
} 
 ... 

Tout d'abord, nous avons importé le type HandlerFunc du module abc. Ce sera le type attribué à toutes nos fonctions de gestionnaire. Ensuite, nous avons utilisé la méthode getDatabase que nous avons créée précédemment pour récupérer notre classe Database . Ensuite, nous avons utilisé la méthode de collecte pour configurer notre collection. L'interface Contact est utilisée lorsque nous voulons récupérer tous les contacts de notre collection.

createContact : Ajoute le contact à la base de données.


 export   const  createContact :  HandlerFunc  =   async   ( c :  Context )   =>   {
 ] essayez   {
 if   ( c .  request .  headers .  get  ( " content-type ")  ! ==  " application / json ")   {
 throw   new   ErrorHandler  (" Corps non valide "  422 ) ; 
} 
 const  body  =   wait   ( c  .  corps  () ) ; 
 if   (!  Object .  keys [1 9659062] ( body ) .  length )   {
 throw   new   ErrorHandler  ( "Request body can ne soyez pas vide! "  400 ) ; 
} 
 const   { name  age  courriel  adresse }   =  corps ; 
 const  inséréContact  =   attendre  contacts  .  insertOne  ( {
nom 
âge 
courriel 
adresse
} ) ; 
 return  c .  json  ( inséréContact   201 ) [19659062]; 
}   catch   ( error )   {
 throw   new   ErrorHandler  ( error .  message  error .  status  ||   500 ) ; 
} 
} ; [19659358] ... 

Test sur le facteur : Faire une demande POST sur / contact . Démarrez le serveur et assurez-vous d'utiliser les indicateurs appropriés bien sûr:

 deno run --allow-write --allow-read --allow-plugin --allow-net --allow-env --unstable ./ main.ts

La première fois que vous exécutez le serveur, Deno télécharge et met en cache les dépendances. La prochaine fois devrait ressembler à quelque chose de similaire dans votre terminal.

 INFO charger le plugin deno "deno_mongo" à partir du local "~ / .deno_plugins / deno_mongo_40ee79e739a57022e3984775fe5fd0ff.dll"
serveur écoutant sur http: // localhost: 5000

export const getOneContact : HandlerFunc = async ( c : Context ) => { essayez { const { id } = c . params as { id : string } ; const getContact = wait contacts . findOne ( { _id : { "$ oid" : id } } ) ; if ( getContact ) { const { _id : { $ oid } [19659062] nom âge email adresse } = getContact ; return c . json ( { id : $ oid name age email address } 200 ) ; } throw new [19659065] ErrorHandler ( "Contact not found" 404 ) ; } catch ( error ) { throw new ErrorHandler ( error . message error . status ] || 500 ) ; } } ; ...

Test sur Postman : Faire une requête GET sur / contacts .

export const getOneContact : HandlerFunc = async ( c : Context ) => { try { const { id } = c . params as { id : string } ; const getContact = wait contacts . findOne ( { _id : {[19659061] "$ oid" : id } } ) ; if ( getContact ) { const { _id : { $ oid } name age em ail adresse } = getContact ; return c . json ( { id : $ oid nom age email address } [19659062] 200 ) ; } throw new ErrorHandler ( "Contact not found" 404 ) ; } catch ( error ) { throw new ErrorHandler ( ] error . message error . status || 500 ) ; } } ; ...

Test sur le facteur : Faire une requête GET sur / contact /: id .

export const updateContact : HandlerFunc = asynchrone ( c : Contexte ) => { try { const ] { id } = c . params as { id : string } ; if ( c . request . headers . get ( "content- type ") ! == " application / json ") { throw new ErrorHandler [196590] 62] ( "Invalid body" 422 ) ; } const body = wait ( c . corps () ) comme { name ? : string ; âge ? : numéro ; email ? : string ; adresse ? : string ; } ; if (! Object . keys [19659062] ( body ) . length ) { throw new ErrorHandler ( "Request body can ne soyez pas vide! " 400 ) ; } const getContact = wait contacts . [19659096] findOne ( { _id : { "$ oid" : id } } ) ; if ( getContact ) { const { matchedCount } = wait contacts . updateOne ( { _id : { "$ oid" : id } [19659059]} { $ set : body } ) ; if ( matchedCount ) { return c . string ( "Contact mis à jour avec succès!" 204 ) ; } return c . string ( "Unable to update contact" ) ; } throw new [19659065] ErrorHandler ( "Contact not found" 404 ) ; } catch ( error ) { throw new ErrorHandler ( error . message error . status || 500 ) ; } } ; ...

Test sur le facteur : Faire une requête PUT sur / contact /: id .

export const deleteContact: HandlerFunc = async (c: Context) => { essayez { const {id} = c.params as {id: string}; const getContact = attendre contacts.findOne ({_id: {"$ oid": id}}); if (getContact) { const deleteCount = attendre contacts.deleteOne ({_id: {"$ oid": id}}); if (deleteCount) { return c.string ("Contact supprimé avec succès!", 204); } throw new ErrorHandler ("Impossible de supprimer l'employé", 400); } throw new ErrorHandler ("Contact not found", 404); } catch (erreur) { lancer un nouveau ErrorHandler (error.message, error.status || 500); } };

Test sur le facteur : Faire une demande DELETE sur / contact /: id .

Github .





Source link
Quitter la version mobile