Halo semuanya. Kali ini saya memutuskan untuk melakukan sesuatu yang lebih menarik daripada bot lain, jadi selanjutnya saya akan menunjukkan kepada Anda cara mengimplementasikan REST API dengan Deno, menghubungkan dan menggunakan MongoDB sebagai database, dan menjalankan semuanya dari bawah Linux.
Versi video dari posting ini tersedia di bawah ini:
Deskripsi tugas
Sebagai contoh, saya memilih Github Gists API dan metode berikut:
[POST] Buat inti;
[GET] Buat daftar inti publik;
[GET] Dapatkan intinya;
[PATCH] Perbarui intinya;
[DELETE] Delete a gist.
api/mod.ts
:
console.log('hello world');
, deno run mod.ts
:
api/deps.ts
:
/* 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
, :
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);
}
});
...
-
-
API;
-
-
.
, , , , -.