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.
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
.
Source link