Pratique avec Deno: développement de l'API REST + MongoDB + Linux

Bonjour à tous. Cette fois, j'ai décidé de faire quelque chose de plus intéressant qu'un autre bot, alors je vais ensuite vous montrer comment implémenter l'API REST avec Deno, connecter et utiliser MongoDB comme base de données et tout exécuter sous Linux.





Une version vidéo de cet article est disponible ci-dessous:





Description de la tâche

A titre d'exemple, j'ai choisi l' API Github Gists et les méthodes suivantes:





  • [POST] Créez un résumé;





  • [GET] Liste publique gists;





  • [GET] Obtenez un aperçu;





  • [PATCH] Mettre à jour un élément essentiel;





  • [DELETE] Delete a gist.





api/mod.ts



:





console.log('hello world');
      
      



, deno run mod.ts



:





mod.ts
mod.ts

api/deps.ts



:





  • oak API;





  • mongo MongoDB;





/* REST API */
export { Application, Router } from "<https://deno.land/x/oak/mod.ts>";
export type { RouterContext } from "<https://deno.land/x/oak/mod.ts>";
export { getQuery } from "<https://deno.land/x/oak/helpers.ts>";

/* MongoDB driver */
export { MongoClient, Bson } from "<https://deno.land/x/mongo@v0.21.0/mod.ts>";
      
      



: NodeJS, Deno npm node_modules



, url . Third Party Modules http://deno.land.





API Boilerplate

, API mod.ts



:





import { Application, Router } from "./deps.ts";

const router = new Router();

router
  .get("/", (context) => {
    context.response.body = "Hello world!";
  });

const app = new Application();

app.use(router.routes());
app.use(router.allowedMethods());

await app.listen({ port: 8000 });
      
      



Application



Router



deps.ts



.





, :





  • deno run --allow-net mod.ts



    ;





  • http://localhost:8000



    ;





  • 'Hello world!';





: Deno secure by default. , () (--allow-net



, (--allow-read



--allow-write



, (--allow-env



) .





POST /gists

, .





:





  • [POST] /gists





  • :





    • content: string | body;





  • :





    • 201 Created;





    • 400 Bad Request;





handlers



create.ts



, handler () :





import { RouterContext } from "../deps.ts";

import { createGist } from "../service.ts";

export async function create(context: RouterContext) {
  if (!context.request.hasBody) {
    context.throw(400, "Bad Request: body is missing");
  }

  const body = context.request.body();
  const { content } = await body.value;
  if (!content) {
    context.throw(400, "Bad Request: content is missing");
  }

  const gist = await createGist(content);

  context.response.body = gist;
  context.response.status = 201;
}
      
      



:





  • (request.hasBody



    !content



    );





  • createGist



    ( );





  • 201 Created.





, ( service.ts



):





import { insertGist } from "./db.ts";

export async function createGist(content: string): Promise<IGist> {
  const values = {
    content,
    created_at: new Date(),
  };

  const _id = await insertGist(values);

  return {
    _id,
    ...values,
  };
}

interface IGist {
  _id: string;
  content: string;
  created_at: Date;
}
      
      



content: string



, IGist



.





MongoDB. db.ts



:





import { Collection } from "<https://deno.land/x/mongo@v0.21.0/src/collection/collection.ts>";
import { Bson, MongoClient } from "./deps.ts";

async function connect(): Promise<Collection<IGistSchema>> {
  const client = new MongoClient();
  await client.connect("mongodb://localhost:27017");
  return client.database("gist_api").collection<IGistSchema>("gists");
}

export async function insertGist(gist: any): Promise<string> {
  const collection = await connect();
  return (await collection.insertOne(gist)).toString();
}

interface IGistSchema {
  _id: { $oid: string };
  content: string;
  created_at: Date;
}
      
      



:





  • MongoDB;





  • gist_api



    connect



    ;





  • , gist_api



    IGistSchema



    ;





  • insertOne



    (inserted id);





MongoDB

, :





sudo systemctl start mongod
sudo systemctl status mongod
      
      



, :





: MongoDB Ubuntu





  • deno run --allow-net mod.ts



    ;





  • Postman API:





, 201 Created



_id



:





: , TypeScript . - Deno TypeScript .





GET /gists

, .





:





  • [GET] /gists





  • :





    • skip: string | query;





    • limit: string | query;





  • :





    • 200 OK;





handlers/list.ts



, handler () :





import { getQuery, RouterContext } from "../deps.ts";

import { getGists } from "../service.ts";

export async function list(context: RouterContext) {
  const { skip, limit } = getQuery(context);

  const gists = await getGists(+skip || 0, +limit || 0);

  context.response.body = gists;
  context.response.status = 200;
}
      
      



:





  • query string getQuery



    ;





  • getGists



    ( );





  • 200 OK;





: number



, string



. +skip || 0



( , NaN



0



).





, :





export function getGists(skip: number, limit: number): Promise<IGist[]> {
  return fetchGists(skip, limit);
}
      
      



skip: number



limit: number



, , IGist



.





MongoDB. fetchGists



db.ts



:





export async function fetchGists(skip: number, limit: number): Promise<any> {
  const collection = await connect();
  return await collection.find().skip(skip).limit(limit).toArray();
}
      
      



:





  • gist_api



    connect



    ;





  • , skip



    - limit



    ;





  • deno run --allow-net mod.ts



    ;





  • Postman API:





, 200 OK



:





GET /gists/:id

.





:





  • [GET] /gists/:id





  • :





    • id: string | path





  • :





    • 200 OK;





    • 400 Bad Request;





    • 404 Not Found.





handlers/get.ts



, handler () :





import { RouterContext } from "../deps.ts"
import { getGist } from "../service.ts";

export async function get(context: RouterContext) {
    const { id } = context.params;
    if(!id) {
        context.throw(400, "Bad Request: id is missing");
    }

    const gist = await getGist(id);
    if(!gist) {
        context.throw(404, "Not Found: the gist is missing");
    }

    context.response.body = gist;
    context.response.status = 200;
}
      
      



:





  • id



    400 ;





  • getGist



    404 ( );





  • 200 OK;





, :





export function getGist(id: string): Promise<IGist> {
    return fetchGist(id);
}

interface IGist {
  _id: string;
  content: string;
  created_at: Date;
}
      
      



id: string



, IGist



.





MongoDB. fetchGist



db.ts



:





export async function fetchGist(id: string): Promise<any> {
  const collection = await connect();
  return await collection.findOne({ _id: new Bson.ObjectId(id) });
}
      
      



:





  • gist_api



    connect



    ;





  • findOne



    _id



    ;





  • deno run --allow-net mod.ts



    ;





  • Postman API:





, 200 OK



:





PATCH /gists/:id

.





, :





  • [PATCH] /gists/:id





  • :





    • id: string | path





    • content: string | body





  • :





    • 200 OK;





    • 400 Bad Request;





    • 404 Not Found.





handlers/update.ts



, handler () :





import { RouterContext } from "../deps.ts";

import { getGist, patchGist } from "../service.ts";

export async function update(context: RouterContext) {
  const { id } = context.params;
  if (!id) {
    context.throw(400, "Bad Request: id is missing");
  }

  const body = context.request.body();
  const { content } = await body.value;
  if (!content) {
    context.throw(400, "Bad Request: content is missing");
  }

  const gist = await getGist(id);
  if (!gist) {
    context.throw(404, "Not Found: the gist is missing");
  }

  await patchGist(id, content);

  context.response.status = 200;
}
      
      



:





  • id



    400 ;





  • !content



    ;





  • getGist



    404 ;





  • patchGist



    ( );





  • 200 OK.





, :





export async function patchGist(id: string, content: string): Promise<any> {
  return updateGist({ id, content });
}

interface IGist {
  _id: string;
  content: string;
  created_at: Date;
}
      
      



id: string



content: string



, any



.





MongoDB. updateGist



db.ts



:





export async function updateGist(gist: any): Promise<any> {
  const collection = await connect();
  const filter = { _id: new Bson.ObjectId(gist.id) };
  const update = { $set: { content: gist.content } };
  return await collection.updateOne(filter, update);
}
      
      



:





  • gist_api



    connect



    ;





  • filter



    , ;





  • update



    , ;





  • updateOne



    ;





  • deno run --allow-net mod.ts



    ;





  • Postman API:





, 200 OK



:





DELETE /gists/:id

, , .





, :





  • [DELETE] /gists/:id





  • :





    • id: string | path





  • :





    • 204 No Content;





    • 404 Not Found.





handlers/remove.ts



, handler () :





import { RouterContext } from "../deps.ts";

import { getGist, removeGist } from "../service.ts";

export async function remove(context: RouterContext) {
  const { id } = context.params;
  if (!id) {
    context.throw(400, "Bad Request: id is missing");
  }

  const gist = await getGist(id);
  if (!gist) {
    context.throw(404, "Not Found: the gist is missing");
  }

  await removeGist(id);

  context.response.status = 204;
}
      
      



:





  • id



    400 ;





  • getGist



    404 ;





  • removeGist



    ( );





  • 204 No Content.





, :





export function removeGist(id: string): Promise<number> {
  return deleteGist(id);
}
      
      



id: string



number



.





MongoDB. deleteGist



db.ts



:





export async function deleteGist(id: string): Promise<any> {
  const collection = await connect();
  return await collection.deleteOne({ _id: new Bson.ObjectId(id) });
}
      
      



:





  • gist_api



    connect



    ;





  • deleteOne



    _id



    ;





  • deno run --allow-net mod.ts



    ;





  • Postman API:





, 204 No Content



:





: . isDeleted: boolean



.





FAQ

API 404 Not Found

router



mod.ts



:





import { Application, Router } from "./deps.ts";
import { list } from "./handlers/list.ts";
import { create } from "./handlers/create.ts";
import { remove } from "./handlers/remove.ts";
import { get } from "./handlers/get.ts";
import { update } from "./handlers/update.ts";

const app = new Application();

const router = new Router();

router
  .post("/gists", create)
  .get("/gists", list)
  .get("/gists/:id", get)
  .delete("/gists/:id", remove)
  .patch("/gists/:id", update);

app.use(router.routes());
app.use(router.allowedMethods());

await app.listen({ port: 8000 });

      
      



API 500 Internal Server Error

:





const app = new Application();

app.use(async (ctx, next) => {
  try {
    await next();
  } catch (err) {
    console.log(err);
  }
});

...
      
      



  • ;





  • GitHub Gist API ;





  • API;





  • MongoDB;





  • MongoDB Ubuntu.





.





, , , , -.












All Articles