Node.js พร็อกซ์ทำง่าย กำหนดค่าพร็อกซีมิดเดิลแวร์ได้อย่างง่ายดายสำหรับการเชื่อมต่อ, เอ็กซ์เพรส, next.js และอีกมากมาย
ขับเคลื่อนโดย NodeJitsu http-proxy ยอดนิยม
หน้านี้กำลังแสดงเอกสารประกอบสำหรับเวอร์ชัน v3.xx (บันทึกย่อ)
ดู Migration.md สำหรับรายละเอียดเกี่ยวกับวิธีการโยกย้ายจาก v2.xx ไปยัง v3.xx
หากคุณกำลังมองหาเอกสารรุ่นเก่า ไปที่:
คำขอพร็อกซี /api ไปที่ http://www.example.org
เคล็ดลับ: ตั้งค่าตัวเลือก changeOrigin เป็น true สำหรับไซต์โฮสต์เสมือนจริงตามชื่อ
// typescript
import * as express from 'express' ;
import type { Request , Response , NextFunction } from 'express' ;
import { createProxyMiddleware } from 'http-proxy-middleware' ;
import type { Filter , Options , RequestHandler } from 'http-proxy-middleware' ;
const app = express ( ) ;
const proxyMiddleware = createProxyMiddleware < Request , Response > ( {
target : 'http://www.example.org/api' ,
changeOrigin : true ,
} ) ;
app . use ( '/api' , proxyMiddleware ) ;
app . listen ( 3000 ) ;
// proxy and keep the same base path "/api"
// http://127.0.0.1:3000/api/foo/bar -> http://www.example.org/api/foo/bar ตัวเลือก http-proxy ทั้งหมด สามารถใช้งานได้พร้อมกับตัวเลือกพิเศษ http-proxy-middleware
pathFilter (String, [] String, Glob, [] Glob, Function)pathRewrite (วัตถุ/ฟังก์ชั่น)router (วัตถุ/ฟังก์ชั่น)plugins (อาร์เรย์)ejectPlugins (บูลีน) ค่าเริ่มต้น: falselogger (วัตถุ)http-proxyhttp-proxynpm install --save-dev http-proxy-middleware สร้างและกำหนดค่าพร็อกซีมิดเดิลแวร์ด้วย: createProxyMiddleware(config)
const { createProxyMiddleware } = require ( 'http-proxy-middleware' ) ;
const apiProxy = createProxyMiddleware ( {
target : 'http://www.example.org' ,
changeOrigin : true ,
} ) ;
// 'apiProxy' is now ready to be used as middleware in a server.ตัวเลือก Target : เป้าหมายโฮสต์เพื่อพร็อกซีถึง (โปรโตคอล + โฮสต์)
ตัวเลือก changeorigin : สำหรับเว็บไซต์โฮสต์เสมือนจริง
ดูรายการตัวเลือกการกำหนดค่า http-proxy-middleware ทั้งหมด
ตัวอย่างด้วยเซิร์ฟเวอร์ express
// include dependencies
const express = require ( 'express' ) ;
const { createProxyMiddleware } = require ( 'http-proxy-middleware' ) ;
const app = express ( ) ;
// create the proxy
/** @type {import('http-proxy-middleware/dist/types').RequestHandler<express.Request, express.Response>} */
const exampleProxy = createProxyMiddleware ( {
target : 'http://www.example.org/api' , // target host with the same base path
changeOrigin : true , // needed for virtual hosted sites
} ) ;
// mount `exampleProxy` in web server
app . use ( '/api' , exampleProxy ) ;
app . listen ( 3000 ) ; หากคุณต้องการใช้ app.use ของแอพเซิร์ฟเวอร์ใช้พารามิเตอร์ path เพื่อจับคู่คำขอ ใช้ตัวเลือก pathFilter เพื่อเพิ่ม/ยกเว้นคำขอที่คุณต้องการพร็อกซี
app . use (
createProxyMiddleware ( {
target : 'http://www.example.org/api' ,
changeOrigin : true ,
pathFilter : '/api/proxy-only-this-path' ,
} ) ,
) ; app.use Documentation:
ตัวเลือก http-proxy-middleware:
pathFilter (String, [] String, Glob, [] Glob, Function) แคบลงซึ่งควรมีการร้องขอ path ที่ใช้สำหรับการกรองเป็นชื่อพา ธ request.url ใน Express นี่คือ path ที่สัมพันธ์กับจุดเมาท์ของพร็อกซี
การจับคู่เส้นทาง
createProxyMiddleware({...}) - ตรงกับเส้นทางใด ๆ คำขอทั้งหมดจะถูกพร็อกซีเมื่อไม่ได้กำหนดค่า pathFiltercreateProxyMiddleware({ pathFilter: '/api', ...}) - จับคู่พา ธ เริ่มต้นด้วย /apiการจับคู่เส้นทางหลายเส้นทาง
createProxyMiddleware({ pathFilter: ['/api', '/ajax', '/someotherpath'], ...})การจับคู่เส้นทางไวด์การ์ด
สำหรับการควบคุมอย่างละเอียดคุณสามารถใช้การจับคู่ไวด์การ์ด การจับคู่รูปแบบลูกโลกทำได้โดย Micromatch เยี่ยมชม Micromatch หรือ Glob สำหรับตัวอย่างที่มีรอบมากขึ้น
createProxyMiddleware({ pathFilter: '**', ...}) ตรงกับเส้นทางใด ๆ คำขอทั้งหมดจะถูกพร็อกซีcreateProxyMiddleware({ pathFilter: '**/*.html', ...}) ตรงกับเส้นทางใด ๆ ที่ลงท้ายด้วย .htmlcreateProxyMiddleware({ pathFilter: '/*.html', ...}) จับคู่พา ธ โดยตรงภายใต้ Path-AbsolutecreateProxyMiddleware({ pathFilter: '/api/**/*.html', ...}) จับคู่คำขอที่ลงท้ายด้วย .html ในเส้นทางของ /apicreateProxyMiddleware({ pathFilter: ['/api/**', '/ajax/**'], ...}) รวมหลายรูปแบบcreateProxyMiddleware({ pathFilter: ['/api/**', '!**/bad.json'], ...}) การยกเว้นหมายเหตุ : ในการจับคู่เส้นทางหลายเส้นทางคุณไม่สามารถใช้เส้นทางสตริงและเส้นทางไวด์การ์ดร่วมกันได้
การจับคู่แบบกำหนดเอง
สำหรับการควบคุมเต็มรูปแบบคุณสามารถจัดเตรียมฟังก์ชั่นที่กำหนดเองเพื่อพิจารณาว่าคำขอใดควรเป็นพร็อกซีหรือไม่
/**
* @return {Boolean}
*/
const pathFilter = function ( path , req ) {
return path . match ( '^/api' ) && req . method === 'GET' ;
} ;
const apiProxy = createProxyMiddleware ( {
target : 'http://www.example.org' ,
pathFilter : pathFilter ,
} ) ;pathRewrite (วัตถุ/ฟังก์ชั่น)เขียนเส้นทาง URL ของเป้าหมายใหม่ Object-keys จะถูกใช้เป็น regexp เพื่อจับคู่เส้นทาง
// rewrite path
pathRewrite: { '^/old/api' : '/new/api' }
// remove path
pathRewrite: { '^/remove/api' : '' }
// add base path
pathRewrite: { '^/' : '/basepath/' }
// custom rewriting
pathRewrite: function ( path , req ) { return path . replace ( '/api' , '/base/api' ) }
// custom rewriting, returning Promise
pathRewrite: async function ( path , req ) {
const should_add_something = await httpRequestToDecideSomething ( path ) ;
if ( should_add_something ) path += "something" ;
return path ;
}router (วัตถุ/ฟังก์ชั่น) option.target เป้าหมายอีกครั้งกำหนดเป้าหมายสำหรับคำขอเฉพาะ
// Use `host` and/or `path` to match requests. First match will be used.
// The order of the configuration matters.
router: {
'integration.localhost:3000' : 'http://127.0.0.1:8001' , // host only
'staging.localhost:3000' : 'http://127.0.0.1:8002' , // host only
'localhost:3000/api' : 'http://127.0.0.1:8003' , // host + path
'/rest' : 'http://127.0.0.1:8004' // path only
}
// Custom router function (string target)
router: function ( req ) {
return 'http://127.0.0.1:8004' ;
}
// Custom router function (target object)
router: function ( req ) {
return {
protocol : 'https:' , // The : is required
host : '127.0.0.1' ,
port : 8004
} ;
}
// Asynchronous router function which returns promise
router: async function ( req ) {
const url = await doSomeIO ( ) ;
return url ;
}plugins (อาร์เรย์) const simpleRequestLogger = ( proxyServer , options ) => {
proxyServer . on ( 'proxyReq' , ( proxyReq , req , res ) => {
console . log ( `[HPM] [ ${ req . method } ] ${ req . url } ` ) ; // outputs: [HPM] GET /users
} ) ;
} ,
const config = {
target : `http://example.org` ,
changeOrigin : true ,
plugins : [ simpleRequestLogger ] ,
} ;ejectPlugins (บูลีน) ค่าเริ่มต้น: false หากคุณไม่พอใจกับปลั๊กอินที่กำหนดค่าไว้ล่วงหน้าคุณสามารถนำออกได้โดยการกำหนดค่า ejectPlugins: true
หมายเหตุ: ลงทะเบียนตัวจัดการข้อผิดพลาดของคุณเองเพื่อป้องกันไม่ให้เซิร์ฟเวอร์ล่ม
// eject default plugins and manually add them back
const {
debugProxyErrorsPlugin , // subscribe to proxy errors to prevent server from crashing
loggerPlugin , // log proxy events to a logger (ie. console)
errorResponsePlugin , // return 5xx response on proxy error
proxyEventsPlugin , // implements the "on:" option
} = require ( 'http-proxy-middleware' ) ;
createProxyMiddleware ( {
target : `http://example.org` ,
changeOrigin : true ,
ejectPlugins : true ,
plugins : [ debugProxyErrorsPlugin , loggerPlugin , errorResponsePlugin , proxyEventsPlugin ] ,
} ) ;logger (วัตถุ) กำหนดค่าตัวบันทึกเป็นข้อมูลเอาต์พุตจาก HTTP-Proxy-Middleware: IE console , winston , pino , bunyan , log4js , ฯลฯ ...
เฉพาะ info warn error จะถูกใช้ภายในเพื่อความเข้ากันได้กับตัวบันทึกที่แตกต่างกัน
หากคุณใช้ winston ตรวจสอบให้แน่ใจว่าได้เปิดใช้งานการแก้ไข: https://github.com/winstonjs/winston#string-interpolation
ดูเพิ่มเติมสูตร Logger (สูตร/logger.md) สำหรับรายละเอียดเพิ่มเติม
createProxyMiddleware ( {
logger : console ,
} ) ; http-proxy สมัครสมาชิก HTTP-Proxy พร้อมตัวเลือก on :
createProxyMiddleware ( {
target : 'http://www.example.org' ,
on : {
proxyReq : ( proxyReq , req , res ) => {
/* handle proxyReq */
} ,
proxyRes : ( proxyRes , req , res ) => {
/* handle proxyRes */
} ,
error : ( err , req , res ) => {
/* handle error */
} ,
} ,
} ) ; Option.on.error : ฟังก์ชั่นสมัครสมาชิกเหตุการณ์ error ของ HTTP-Proxy สำหรับการจัดการข้อผิดพลาดที่กำหนดเอง
function onError ( err , req , res , target ) {
res . writeHead ( 500 , {
'Content-Type' : 'text/plain' ,
} ) ;
res . end ( 'Something went wrong. And we are reporting a custom error message.' ) ;
} Option.on.proxyres : ฟังก์ชั่นสมัครสมาชิกกิจกรรม proxyRes ของ HTTP-Proxy
function onProxyRes ( proxyRes , req , res ) {
proxyRes . headers [ 'x-added' ] = 'foobar' ; // add new header to response
delete proxyRes . headers [ 'x-removed' ] ; // remove header from response
} Option.on.proxyreq : ฟังก์ชั่นสมัครสมาชิกเหตุการณ์ proxyReq ของ HTTP-Proxy
function onProxyReq ( proxyReq , req , res ) {
// add custom header to request
proxyReq . setHeader ( 'x-added' , 'foobar' ) ;
// or log the req
} Option.on.proxyreqws : ฟังก์ชั่นสมัครสมาชิกเหตุการณ์ proxyReqWs ของ HTTP-Proxy
function onProxyReqWs ( proxyReq , req , socket , options , head ) {
// add custom header
proxyReq . setHeader ( 'X-Special-Proxy-Header' , 'foobar' ) ;
} Option.on.open : ฟังก์ชั่นสมัครสมาชิกกิจกรรม open ของ HTTP-Proxy
function onOpen ( proxySocket ) {
// listen for messages coming FROM the target here
proxySocket . on ( 'data' , hybridParseAndLogMessage ) ;
} Option.on.close : ฟังก์ชั่นสมัครสมาชิกเหตุการณ์ close ของ HTTP-Proxy
function onClose ( res , socket , head ) {
// view disconnected websocket connections
console . log ( 'Client disconnected' ) ;
} http-proxyตัวเลือกต่อไปนี้จัดทำโดยไลบรารี HTTP-Proxy พื้นฐาน
Option.target : url string ที่จะแยกวิเคราะห์ด้วยโมดูล URL
ตัวเลือกไปข้างหน้า : สตริง URL ที่จะแยกวิเคราะห์ด้วยโมดูล URL
ตัวเลือก. ตัวแทน : วัตถุที่จะส่งผ่านไปยัง HTTP (S). Request (ดูออบเจ็กต์ HTTPS ของ Node และ HTTP Agent)
Option.ssl : วัตถุที่จะส่งผ่านไปยัง https.createserver ()
ตัวเลือก. ws : true/false: หากคุณต้องการพร็อกซี websockets
ตัวเลือก xfwd : จริง/เท็จเพิ่มส่วนหัว X-Forward
ตัวเลือก. ความปลอดภัย : จริง/เท็จหากคุณต้องการตรวจสอบใบรับรอง SSL
ตัวเลือก Toproxy : จริง/เท็จผ่าน URL สัมบูรณ์เป็น path (มีประโยชน์สำหรับการส่งมอบพร็อกซี)
ตัวเลือกการขึ้นอยู่กับ : จริง/เท็จ, ค่าเริ่มต้น: จริง - ระบุว่าคุณต้องการเตรียมเส้นทางของเป้าหมายไปยังเส้นทางพร็อกซี
Option.ignorePath : จริง / เท็จ, ค่าเริ่มต้น: เท็จ - ระบุว่าคุณต้องการเพิกเฉยต่อเส้นทางพร็อกซีของคำขอเข้ามา (หมายเหตุ: คุณจะต้องต่อท้าย / ด้วยตนเองหากจำเป็น)
ตัวเลือก. localaddress: สตริงอินเตอร์เฟสท้องถิ่นเพื่อผูกสำหรับการเชื่อมต่อขาออก
ตัวเลือก changeorigin : true/false, ค่าเริ่มต้น: false - เปลี่ยนต้นกำเนิดของส่วนหัวโฮสต์เป็น URL เป้าหมาย
ตัวเลือก PRESERVETERHEADESCASE : จริง/เท็จ, ค่าเริ่มต้น: เท็จ - ระบุว่าคุณต้องการเก็บคีย์ตัวอักษรของการตอบกลับไว้
ตัวเลือก Auth : การตรวจสอบขั้นพื้นฐานเช่น 'ผู้ใช้: รหัสผ่าน' เพื่อคำนวณส่วนหัวการอนุญาต
ตัวเลือก. hostrewrite : เขียนชื่อโฮสต์ตำแหน่งบน (301/302/307/308) การเปลี่ยนเส้นทาง
ตัวเลือก AUTOREWRITE : เขียนตำแหน่งโฮสต์/พอร์ตบน (301/302/307/308) การเปลี่ยนเส้นทางตามโฮสต์/พอร์ตที่ร้องขอ ค่าเริ่มต้น: เท็จ
ตัวเลือก ProtocolrewRite : เขียนโปรโตคอลตำแหน่งใหม่บน (301/302/307/308) เปลี่ยนเส้นทางไปยัง 'http' หรือ 'https' ค่าเริ่มต้น: NULL
ตัวเลือก CookiedOmainRewrite : เขียนโดเมนของส่วนหัวของ set-cookie ค่าที่เป็นไปได้:
false (ค่าเริ่มต้น): ปิดใช้งานการเขียนคุกกี้ใหม่
สตริง: โดเมนใหม่เช่น cookieDomainRewrite: "new.domain" ในการลบโดเมนให้ใช้ cookieDomainRewrite: ""
วัตถุ: การแมปของโดเมนกับโดเมนใหม่ใช้ "*" เพื่อให้ตรงกับโดเมนทั้งหมด
ตัวอย่างเช่นให้หนึ่งโดเมนไม่เปลี่ยนแปลงเขียนหนึ่งโดเมนใหม่และลบโดเมนอื่น ๆ :
cookieDomainRewrite: {
"unchanged.domain" : " unchanged.domain " ,
"old.domain" : " new.domain " ,
"*" : " "
} ตัวเลือก CookiePathrewRite : เขียนเส้นทางของส่วนหัวของ set-cookie ค่าที่เป็นไปได้:
false (ค่าเริ่มต้น): ปิดใช้งานการเขียนคุกกี้ใหม่
สตริง: เส้นทางใหม่เช่น cookiePathRewrite: "/newPath/" ในการลบเส้นทางให้ใช้ cookiePathRewrite: "" ในการตั้งค่าเส้นทางการใช้รูทใช้ cookiePathRewrite: "/"
วัตถุ: การทำแผนที่เส้นทางไปยังเส้นทางใหม่ให้ใช้ "*" เพื่อให้ตรงกับเส้นทางทั้งหมด ตัวอย่างเช่นเพื่อให้เส้นทางหนึ่งไม่เปลี่ยนแปลงให้เขียนเส้นทางหนึ่งเส้นทางใหม่และลบเส้นทางอื่น ๆ :
cookiePathRewrite: {
"/unchanged.path/" : " /unchanged.path/ " ,
"/old.path/" : " /new.path/ " ,
"*" : " "
} ตัวเลือกหัว : วัตถุเพิ่มส่วนหัวคำขอ (ตัวอย่าง: {host:'www.example.org'} )
ตัวเลือก. proxytimeout : หมดเวลา (เป็นมิลลิส) เมื่อพร็อกซีไม่ได้รับการตอบกลับจากเป้าหมาย
Option.timeout : หมดเวลา (เป็นมิลลิส) สำหรับคำขอที่เข้ามา
ตัวเลือก. followredirects : true/false, ค่าเริ่มต้น: false - ระบุว่าคุณต้องการติดตามการเปลี่ยนเส้นทาง
Option.selfhandleresponse จริง/เท็จหากตั้งค่าเป็นจริงไม่มีการเรียกผ่านเว็บออกไปและเป็นความรับผิดชอบของคุณที่จะส่งคืนการตอบกลับอย่างเหมาะสมโดยการฟังและการดำเนินการในเหตุการณ์ proxyRes
Option.buffer : สตรีมข้อมูลที่จะส่งเป็นตัวคำขอ บางทีคุณอาจมีมิดเดิลแวร์ที่ใช้สตรีมคำขอก่อนที่จะพร็อกซ์ในเช่นถ้าคุณอ่านเนื้อหาของคำขอลงในฟิลด์ที่เรียกว่า 'req.rawbody' คุณสามารถยับยั้งฟิลด์นี้ในตัวเลือกบัฟเฟอร์:
'use strict' ;
const streamify = require ( 'stream-array' ) ;
const HttpProxy = require ( 'http-proxy' ) ;
const proxy = new HttpProxy ( ) ;
module . exports = ( req , res , next ) => {
proxy . web (
req ,
res ,
{
target : 'http://127.0.0.1:4003/' ,
buffer : streamify ( req . rawBody ) ,
} ,
next ,
) ;
} ; // verbose api
createProxyMiddleware ( { pathFilter : '/' , target : 'http://echo.websocket.org' , ws : true } ) ; ในตัวอย่าง WebSocket ก่อนหน้า HTTP-Proxy-Middleware อาศัยคำขอ HTTP เริ่มต้นเพื่อฟังเหตุการณ์ upgrade HTTP หากคุณต้องการพร็อกซี WebSockets โดยไม่ต้องมีคำขอ HTTP เริ่มต้นคุณสามารถสมัครรับเหตุการณ์ upgrade HTTP ของเซิร์ฟเวอร์ด้วยตนเอง
const wsProxy = createProxyMiddleware ( { target : 'ws://echo.websocket.org' , changeOrigin : true } ) ;
const app = express ( ) ;
app . use ( wsProxy ) ;
const server = app . listen ( 3000 ) ;
server . on ( 'upgrade' , wsProxy . upgrade ) ; // <-- subscribe to http 'upgrade' การสกัดกั้นคำขอจากดาวน์สตรีมโดยการกำหนด onProxyReq ใน createProxyMiddleware
ปัจจุบันการสกัดกั้นการร้องขอล่วงหน้าเพียงอย่างเดียวคือ fixRequestBody ซึ่งใช้เพื่อแก้ไขคำขอโพสต์พร็อกซีเมื่อใช้ bodyParser ก่อนมิดเดิลแวร์นี้
ตัวอย่าง:
const { createProxyMiddleware , fixRequestBody } = require ( 'http-proxy-middleware' ) ;
const proxy = createProxyMiddleware ( {
/**
* Fix bodyParser
**/
on : {
proxyReq : fixRequestBody ,
} ,
} ) ; การตอบสนองการสกัดกั้นจากต้นน้ำด้วย responseInterceptor (ตรวจสอบให้แน่ใจว่าได้ตั้งค่า selfHandleResponse: true )
การตอบสนองที่ถูกบีบอัดด้วย brotli , gzip และ deflate จะถูกบีบอัดโดยอัตโนมัติ การตอบกลับจะถูกส่งคืนเป็น buffer (เอกสาร) ซึ่งคุณสามารถจัดการได้
ด้วย buffer การจัดการการตอบสนองไม่ จำกัด เฉพาะการตอบสนองข้อความ (HTML/CSS/JS ฯลฯ ... ); การจัดการภาพก็เป็นไปได้เช่นกัน (ตัวอย่าง)
หมายเหตุ: responseInterceptor ปิดใช้งานการสตรีมการตอบสนองของเป้าหมาย
ตัวอย่าง:
const { createProxyMiddleware , responseInterceptor } = require ( 'http-proxy-middleware' ) ;
const proxy = createProxyMiddleware ( {
/**
* IMPORTANT: avoid res.end being called automatically
**/
selfHandleResponse : true , // res.end() will be called internally by responseInterceptor()
/**
* Intercept response and replace 'Hello' with 'Goodbye'
**/
on : {
proxyRes : responseInterceptor ( async ( responseBuffer , proxyRes , req , res ) => {
const response = responseBuffer . toString ( 'utf8' ) ; // convert buffer to string
return response . replace ( 'Hello' , 'Goodbye' ) ; // manipulate response and return the result
} ) ,
} ,
} ) ;ตรวจสอบสูตรการสกัดกั้นสำหรับตัวอย่างเพิ่มเติม
node.js 17+ ไม่ชอบ IPv4 มากกว่า IPv6 สำหรับการค้นหา DNS อีกต่อไป เช่น ไม่ รับประกันว่า localhost จะได้รับการแก้ไขเป็น 127.0.0.1 - มันอาจจะเป็นเช่นนั้น ::1 (หรือที่อยู่ IP อื่น ๆ )
หากเซิร์ฟเวอร์เป้าหมายของคุณยอมรับการเชื่อมต่อ IPv4 เท่านั้นการพยายามพร็อกซีไปยัง localhost จะล้มเหลวหากแก้ไขเป็น ::1 (IPv6)
วิธีแก้ปัญหา:
target: "http://localhost" เป็น target: "http://127.0.0.1" (IPv4)node : node index.js --dns-result-order=ipv4first (ไม่แนะนำ)หมายเหตุ: มีสิ่งที่เรียกว่าลูกตาที่มีความสุขซึ่งหมายถึงการเชื่อมต่อกับทั้ง IPv4 และ IPv6 ในแบบขนานซึ่ง Node.js ไม่มี แต่อธิบายว่าทำไม
curlสามารถเชื่อมต่อได้
กำหนดค่าตัวแปรสภาพแวดล้อม DEBUG เปิดใช้งานการบันทึกการดีบัก
ดูโครงการ debug สำหรับตัวเลือกเพิ่มเติม
DEBUG=http-proxy-middleware * node server.js
$ http-proxy-middleware proxy created +0ms
$ http-proxy-middleware proxying request to target: ' http://www.example.org ' +359msดูและเล่นกับตัวอย่างการทำงาน
ดูสูตรอาหารสำหรับกรณีการใช้งานทั่วไป
http-proxy-middleware เข้ากันได้กับเซิร์ฟเวอร์ต่อไปนี้:
การใช้งานตัวอย่างสามารถพบได้ในสูตรเซิร์ฟเวอร์
เรียกใช้ชุดทดสอบ:
# install dependencies
$ yarn
# linting
$ yarn lint
$ yarn lint:fix
# building (compile typescript to js)
$ yarn build
# unit tests
$ yarn test
# code coverage
$ yarn cover
# check spelling mistakes
$ yarn spellcheckใบอนุญาต MIT (MIT)
ลิขสิทธิ์ (c) 2015-2024 Steven Chim