使用Node.js进行Web服务器开发的初学者指南

在我大部分的网络职业中,我只在客户端工作。 设计自适应布局,从大量数据创建可视化文件,创建应用程序仪表板等。但是,我从来不必直接处理路由或HTTP请求。 直到最近。

这篇文章描述了我如何学习使用Node.js进行服务器端Web开发的更多信息,并简要比较了使用Express,Koa.js和Hapi.js这3种不同环境编写简单HTTP服务器的过程。

注意:如果您是经验丰富的Node.js开发人员,您可能会认为这一切都是基本/简单的。 ¯\ _(ツ)_ /¯。

网络的一些基础


几年前,当我开始在Web行业工作时,我遇到了Coursera上的David Veteral教授关于计算机网络的一门课程。 不幸的是,它不再可用,但仍可以在Pearson网站获得讲座。

我真的很喜欢这门课程,因为它以一种可以理解的方式解释了幕后发生的事情,因此,如果您可以阅读《计算机网络》教科书,请阅读有关网络奇观的所有详细信息。

图片

但是,在这里,我仅简要介绍一下上下文。 HTTP(超文本传输​​协议)是计算机网络中使用的通信协议。 Internet上有很多,例如SMTP(简单邮件传输协议)FTP(文件传输协议)POP3(邮局协议3)等等。

这些协议允许具有完全不同的硬件/软件的设备相互通信,因为它们提供了定义良好的消息格式,规则,语法和语义等。 这意味着尽管该设备支持特定协议,但它可以与任何其他设备通信。 在网上。

图片
从TCP / IP与OSI:两种模型之间有什么区别?

操作系统通常开箱即用地支持网络协议,例如HTTP,这解释了为什么我们不需要显式安装任何其他软件来访问Internet。 大多数网络协议支持两个设备之间的开放连接,这使它们可以来回传输数据。

网络运行所在的HTTP是不同的。 之所以称为无连接协议,是因为它基于请求/响应操作模式。 Web浏览器向服务器发送图像,字体,内容等请求,但请求完成后,浏览器与服务器之间的连接断开。

图片

服务器和客户端


服务器一词对于第一次接触该行业的人可能会有些困惑,因为它既可以指硬件(托管网站所需的所有文件和软件的物理计算机)又可以指软件(允许用户在线访问这些文件)。

今天我们将讨论软件方面的问题。 但是首先,一些定义。 该URL代表Universal Resource Locator,它由3部分组成: 协议服务器请求的文件

图片
网址结构

HTTP协议定义了几种方法,浏览器可以使用这些方法来请求服务器执行一系列不同的操作,其中最常见的是GET和POST。 当用户单击链接或在地址栏中输入URL时,浏览器将GET请求发送到服务器以检索URL中指定的资源。

服务器必须知道如何处理此HTTP请求才能获取正确的文件,然后将其发送回请求该文件的浏览器。 处理此问题的最流行的Web服务器软件是ApacheNGINX

图片
Web服务器处理传入的请求并做出相应的响应

两者都是功能齐全的开源软件包,其中包括身份验证方案,URL重写,日志记录和代理等功能,仅举几例。 Apache和NGINX用C编写。从技术上讲,您可以使用任何语言编写Web服务器。 Pythongolang.org/pkg/net/httpRuby ,此列表可以持续很长时间。 只是某些语言在某些方面做得比其他语言要好。

使用Node.js创建HTTP服务器


Node.js是基于Chrome V8 Javascript引擎构建的Javascript运行时。 它带有http模块 ,该模块提供了用于构建HTTP服务器的一组功能和类。

对于此基本的HTTP服务器,我们还将使用文件系统pathURL ,它们是Node.js本机模块。

首先导入所需的模块。

const http = require('http') //   HTTP-  Node.js const fs = require('fs') //      const path = require('path') //        const url = require('url') //     URL 

我们还将创建一个MIME类型字典,以便我们可以根据其扩展名为请求的资源分配适当的MIME类型。 可以在Internet分配号码授权机构中找到MIME类型的完整列表。

 const mimeTypes = { '.html': 'text/html', '.js': 'text/javascript', '.css': 'text/css', '.ico': 'image/x-icon', '.png': 'image/png', '.jpg': 'image/jpeg', '.gif': 'image/gif', '.svg': 'image/svg+xml', '.json': 'application/json', '.woff': 'font/woff', '.woff2': 'font/woff2' } 

现在,我们可以使用函数http.createServer()创建一个HTTP服务器,该服务器将返回http.Server的新实例。

 const server = http.createServer() 

我们将把请求处理程序函数与请求和响应对象一起传递给createServer() 。 每当HTTP请求到达服务器时,都会调用此函数一次。

 server.on('request', (req, res) => { //     }) 

通过使用我们希望服务器监听的端口号调用server对象的listen方法来启动server ,例如5000

 server.listen(5000) 

request对象是IncomingMessage的实例,它使我们能够访问有关请求的所有信息,例如响应状态,标头和数据。

response对象是ServerResponse的实例,该实例是可写的流,并提供了许多用于将数据发送回客户端的方法。

在查询处理程序中,我们要执行以下操作:

  • 解析传入的请求并对其进行处理而无需扩展

     const parsedUrl = new URL(req.url, 'https://node-http.glitch.me/') let pathName = parsedUrl.pathname let ext = path.extname(pathName) //   URL    '/',   '/' //      URL    'Location' if (pathName !== '/' && pathName[pathName.length - 1] === '/') { res.writeHead(302, {'Location': pathName.slice(0, -1)}) res.end() return } //     ,  index.html //     «.html»       if (pathName === '/') { ext = '.html' pathName = '/index.html' } else if (!ext) { ext = '.html' pathName += ext } 

  • 执行一些基本检查以确定所请求的资源是否存在,并做出相应的响应

     //     ,       const filePath = path.join(process.cwd(), '/public', pathName) // ,       fs.exists(filePath, function (exists, err) { //     ,  404 Not Found if (!exists || !mimeTypes[ext]) { console.log('  : ' + pathName) res.writeHead(404, {'Content-Type': 'text/plain'}) res.write('404 Not Found') res.end() return } //        200 OK, //       res.writeHead(200, {'Content-Type': mimeTypes[ext]}) //        const fileStream = fs.createReadStream(filePath) fileStream.pipe(res) }) 


所有代码都托管在Glitch上,并且您可以根据需要重新混合项目。

https://glitch.com/edit/#!/node-http

使用Node.js框架创建HTTP服务器


ExpressKoa.jsHapi.js等Node.js框架具有各种有用的中间件功能,此外还有许多其他方便的功能,这些功能使开发人员不必自己编写。

就个人而言,我觉得最好先学习没有框架的基础知识,而只是了解幕后发生的事情,然后疯狂使用任何您喜欢的框架。

Express具有自己的内置插件来提供静态文件,因此执行与自己的Node.js中相同的操作所需的代码要短得多。

 const express = require('express') const app = express() //         app.use(express.static('public')) //  index.html,      //     res.sendFile() app.get('/', (req, res) => { res.sendFile(__dirname + '/public/index.html') }) app.listen(5000) 

Koa.js的内核内部没有类似的插件,因此任何必需的插件都必须单独安装。 Koa.js的最新版本使用异步函数来支持回调。 您可以使用koa-static插件提供静态文件。

 const serve = require('koa-static') const koa = require('koa') const app = new koa() //         //   koa-static    index.html    app.use(serve(__dirname + '/public')) app.listen(5000) 

Hapi.js支持自定义,并围绕自定义server对象。 它使用插件来扩展路由,身份验证等功能。 要提供静态文件,我们需要一个名为inert的插件。

 const path = require('path') const hapi = require('hapi') const inert = require('inert') //        const server = new hapi.Server({ port: 5000, routes: { files: { relativeTo: path.join(__dirname, 'public') } } }) const init = async () => { // server.register()      await server.register(inert) // inert     //       server.route({ method: 'GET', path: '/{param*}', handler: { directory: { path: '.', redirectToSlash: true, index: true } } }) await server.start() } init() 

这些平台中的每一个都有其优点和缺点,对于较大的应用程序,而不仅仅是为单个HTML页面提供服务,它们将更加明显。 结构的选择将在很大程度上取决于您正在处理的项目的实际需求。

完成时间


如果网络方面一直是您的黑匣子,我希望本文可以对提供网络的协议提供有用的介绍。 我也强烈建议您阅读Node.js API文档 ,该文档写得很好,并且对于任何Node.js新手来说都是非常有用的。

Source: https://habr.com/ru/post/zh-CN435970/


All Articles