Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

How to use native API to build a Web server in Node.js

2025-01-14 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Servers >

Share

Shulou(Shulou.com)06/01 Report--

In this issue, the editor will bring you about how to use native API to build a Web server in Node.js. The article is rich in content and analyzes and describes for you from a professional point of view. I hope you can get something after reading this article.

1. Static web server

'use strict' const http = require (' http') const url = require ('url') const fs = require (' fs') const path = require ('path') const cp = require (' child_process') const port = 8080 const hostname = 'localhost' / / create http service let httpServer = http.createServer (processStatic) / / set listening port httpServer.listen (port, hostname) () = > {console.log (`explorer {port} `) console.log (`url: http://${hostname}:${port}`) cp.exec (`explorer http://${hostname}:${port}`, () = > {})}) / / process static resource function processStatic (req, res) {const mime = {css: 'text/css', gif:' image/gif' Html: 'text/html', ico:' image/x-icon', jpeg: 'image/jpeg', jpg:' image/jpeg', js: 'text/javascript', json:' application/json', pdf: 'application/pdf', png:' image/png', svg: 'image/svg+xml', woff:' application/x-font-woff', woff2: application/x-font-woff' Swf: 'application/x-shockwave-flash', tiff:' image/tiff', txt: 'text/plain', wav:' audio/x-wav', wma: 'audio/x-ms-wma', wmv:' video/x-ms-wmv' Xml: 'text/xml'} const requestUrl = req.url let pathName = url.parse (requestUrl). Pathname / / Chinese garbled handling pathName = decodeURI (pathName) let ext = path.extname (pathName) / / Special url handling if (! pathName.endsWith (' /') & & ext ='& &! requestUrl.includes ('?)) {pathName + ='/ 'const redirect = `http://${req.headers.host}${pathName}` redirectUrl (redirect) Res)} / / explain the resource file path let filePath = path.resolve (_ _ dirname + pathName) / / set mime ext = ext? Ext.slice (1): 'unknown' const contentType = mime [ext] | |' text/plain' / / processing resource files fs.stat (filePath, (err, stats) = > {if (err) {res.writeHead (404, {'content-type':' text/html) Charset=utf-8'}) res.end ('404 Not Found') return} / / processing file if (stats.isFile ()) {readFile (filePath, contentType, res)} / / processing directory if (stats.isDirectory ()) {let html = "" / / traversing the file directory, returning as a hyperlink It is convenient for users to select fs.readdir (filePath, (err, files) = > {if (err) {res.writeHead (500) {'content-type': contentType}) res.end (' 500 Server Error') return} else {for (let file of files) {if (file = 'index.html') {const redirect = `http://${req.headers.host}${pathName}index.html` redirectUrl (redirect) Res)} html + = `$ {file} `} html + =''res.writeHead (200,{' content-type': 'text/html'}) res.end (html)} / / redirect processing function redirectUrl (url, res) {url = encodeURI (url) res.writeHead {location: url}) res.end ()} / / File read function readFile (filePath, contentType, res) {res.writeHead (200,{ 'content-type': contentType}) const stream = fs.createReadStream (filePath) stream.on (' error', function () {res.writeHead (500,{ 'content-type': contentType}) res.end (' 500 Server Error')}) stream.pipe (res)}

2. Agent function

/ / Agent list const proxyTable = {'/ api': {target: 'http://127.0.0.1:8090/api', changeOrigin: true}} / / processing agent list function processProxy (req, res) {const requestUrl = req.url const proxy = Object.keys (proxyTable) let not_found = true for (let index = 0; index

< proxy.length; index++) { const k = proxy[index] const i = requestUrl.indexOf(k) if (i >

= 0) {not_found = false const element = proxyTable [k] const newUrl = element.target + requestUrl.slice (I + k.length) if (requestUrl! = = newUrl) {const u = url.parse (newUrl, true) const options = {hostname: u.hostname, port: u.port | | 80 Path: u.path, method: req.method, headers: req.headers Timeout: 6000} if (element.changeOrigin) {options.headers ['host'] = u.hostname +':'+ (u.port | | 80)} const request = http .request (options) Response = > {/ / cookie processes if (element.changeOrigin & & response.headers ['set-cookie']) {response.headers [' set-cookie'] = getHeaderOverride (response.headers ['set-cookie'])} res.writeHead (response.statusCode) Response.headers) response.pipe (res)}) .on ('error' Err = > {res.statusCode = 503 res.end ()} req.pipe (request)} break}} return not_found} function getHeaderOverride (value) {if (Array.isArray (value)) {for (var I = 0 I

< value.length; i++ ) { value[i] = replaceDomain(value[i]) } } else { value = replaceDomain(value) } return value } function replaceDomain(value) { return value.replace(/domain=[a-z.]*;/,'domain=.localhost;').replace(/secure/, '') } 3、完整版 服务器接收到 http 请求,首先处理代理列表 proxyTable,然后再处理静态资源。虽然这里面只有二个步骤,但如果按照先后顺序编码,这种方式显然不够灵活,不利于以后功能的扩展。koa 框架的中间件就是一个很好的解决方案。完整代码如下: 'use strict' const http = require('http') const url = require('url') const fs = require('fs') const path = require('path') const cp = require('child_process') // 处理静态资源 function processStatic(req, res) { const mime = { css: 'text/css', gif: 'image/gif', html: 'text/html', ico: 'image/x-icon', jpeg: 'image/jpeg', jpg: 'image/jpeg', js: 'text/javascript', json: 'application/json', pdf: 'application/pdf', png: 'image/png', svg: 'image/svg+xml', woff: 'application/x-font-woff', woff2: 'application/x-font-woff', swf: 'application/x-shockwave-flash', tiff: 'image/tiff', txt: 'text/plain', wav: 'audio/x-wav', wma: 'audio/x-ms-wma', wmv: 'video/x-ms-wmv', xml: 'text/xml' } const requestUrl = req.url let pathName = url.parse(requestUrl).pathname // 中文乱码处理 pathName = decodeURI(pathName) let ext = path.extname(pathName) // 特殊 url 处理 if (!pathName.endsWith('/') && ext === '' && !requestUrl.includes('?')) { pathName += '/' const redirect = `http://${req.headers.host}${pathName}` redirectUrl(redirect, res) } // 解释 url 对应的资源文件路径 let filePath = path.resolve(__dirname + pathName) // 设置 mime ext = ext ? ext.slice(1) : 'unknown' const contentType = mime[ext] || 'text/plain' // 处理资源文件 fs.stat(filePath, (err, stats) =>

{if (err) {res.writeHead (404, {'content-type':' text/html Charset=utf-8'}) res.end ('404 Not Found') return} / / processing file if (stats.isFile ()) {readFile (filePath, contentType, res)} / / processing directory if (stats.isDirectory ()) {let html = "" / / traversing the file directory, returning as a hyperlink It is convenient for users to select fs.readdir (filePath, (err, files) = > {if (err) {res.writeHead (500) {'content-type': contentType}) res.end (' 500 Server Error') return} else {for (let file of files) {if (file = 'index.html') {const redirect = `http://${req.headers.host}${pathName}index.html` redirectUrl (redirect) Res)} html + = `$ {file} `} html + =''res.writeHead (200,{' content-type': 'text/html'}) res.end (html)} / / redirect processing function redirectUrl (url, res) {url = encodeURI (url) res.writeHead {location: url}) res.end ()} / / File read function readFile (filePath, contentType, res) {res.writeHead (200,{ 'content-type': contentType}) const stream = fs.createReadStream (filePath) stream.on (' error', function () {res.writeHead (500) {'content-type': contentType}) res.end (' 500 Server Error')}) stream.pipe (res)} / / processing agent list function processProxy (req, res) {const requestUrl = req.url const proxy = Object.keys (proxyTable) let not_found = true for (let index = 0 Index

< proxy.length; index++) { const k = proxy[index] const i = requestUrl.indexOf(k) if (i >

= 0) {not_found = false const element = proxyTable [k] const newUrl = element.target + requestUrl.slice (I + k.length) if (requestUrl! = = newUrl) {const u = url.parse (newUrl, true) const options = {hostname: u.hostname, port: u.port | 80, path: u.path Method: req.method, headers: req.headers, timeout: 6000} If (element.changeOrigin) {options.headers ['host'] = u.hostname +':'+ (u.port | | 80)} const request = http.request (options Response = > {/ / cookie processes if (element.changeOrigin & & response.headers ['set-cookie']) {response.headers [' set-cookie'] = getHeaderOverride (response.headers ['set-cookie'])} res.writeHead (response.statusCode) Response.headers) response.pipe (res)}) .on ('error', err = > {res.statusCode = 503 res.end ()}) req.pipe (request)} break}} return not_found} function getHeaderOverride (value) {if (Array.isArray (value)) {for (var I = 0 I

< value.length; i++ ) { value[i] = replaceDomain(value[i]) } } else { value = replaceDomain(value) } return value} function replaceDomain(value) { return value.replace(/domain=[a-z.]*;/,'domain=.localhost;').replace(/secure/, '') } function compose (middleware) { if (!Array.isArray(middleware)) throw new TypeError('Middleware stack must be an array!') for (const fn of middleware) { if (typeof fn !== 'function') throw new TypeError('Middleware must be composed of functions!') } return function (context, next) { // 记录上一次执行中间件的位置 let index = -1 return dispatch(0) function dispatch (i) { // 理论上 i 会大于 index,因为每次执行一次都会把 i递增, // 如果相等或者小于,则说明next()执行了多次 if (i { const ctx = {req, res} return this.handleRequest(ctx, fn) } return handleRequest } Router.prototype.handleRequest= function(ctx, fn) { fn(ctx) } // 代理列表 const proxyTable = { '/api': { target: 'http://127.0.0.1:8090/api', changeOrigin: true } } const port = 8080 const hostname = 'localhost' const appRouter = new Router() // 使用中间件 appRouter.use(async(ctx,next)=>

{if (processProxy (ctx.req, ctx.res)) {next ()}) .use (async (ctx) = > {processStatic (ctx.req, ctx.res)}) / / create http service let httpServer = http.createServer (appRouter.callback ()) / / set listening port httpServer.listen (port, hostname) () = > {console.log (`app is running at port:$ {port} `) console.log (`url: http://${hostname}:${port}`) cp.exec (`explorer http://${hostname}:${port}`, () = > {})}) the above is how to use native API to build a Web server in the Node.js shared by the editor. If you happen to have similar doubts, you might as well refer to the above analysis to understand. If you want to know more about it, you are welcome to follow the industry information channel.

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Servers

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report