如何使用HTTP模块在Node.js中创建Web服务器(下)
2020-09-11 11:18:00 Author: www.4hou.com(查看原文) 阅读量:381 收藏

上一篇文章中,我们已经讲了步骤1和步骤2,本文继续讲解步骤3和步骤4。

提供HTML

当我们希望用户通过web浏览器与服务器交互时,超文本标记语言HTML是最常用的格式。创建它是为了构造web内容。网页浏览器是用来显示HTML内容的,以及我们通过CSS添加的任何样式,CSS是另一种允许我们改变网站美观的前端网络技术。

让我们使用文本编辑器重新打开html.js:

31.png

修改requestListener()函数以为HTML响应返回适当的Content-Type标头:

32.png

现在,让我们将HTML内容返回给用户。将突出显示的行添加到html.js中,如下所示:

33.png

我们首先添加HTTP状态码,然后使用包含有效HTML的字符串参数调用response.end()。当我们在浏览器中访问我们的服务器时,我们将看到一个带有一个标头标签的HTML页面,其中包含“This is HTML”。

让我们保存并退出按CTRL+X,现在,让我们用node命令运行服务器:

34.png

当我们的程序启动时,我们将看到服务器在http://localhost:8000上运行。现在进入浏览器并访问http://localhost:8000,我们的页面看起来是这样的:

35.png

让我们使用CTRL + C退出正在运行的服务器,然后返回到标准终端提示符。

通常将HTML写入文件中,与服务器端代码(例如我们的Node.js程序)分开。接下来,让我们看看如何从文件返回HTML响应。

步骤3 :通过文件提供HTML页面

我们可以将HTML作为Node.js中的字符串提供给用户,但是最好加载HTML文件并提供其内容。这样,随着HTML文件的增长,我们不必在Node.js代码中保留长字符串,从而使其更加简洁,并允许我们独立处理网站的各个方面。这种方法在许多web开发设置中都很常见,所以最好知道如何在Node.js中加载HTML文件来支持它。

为了提供HTML文件,我们使用fs模块加载HTML文件,并在编写HTTP响应时使用其数据。

首先,我们将创建web服务器将返回的HTML文件,创建一个新的HTML文件:

36.png

现在,在文本编辑器中打开index.html:

37.png

我们的网页将很小,它将具有橙色背景,并在中间显示一些问候语。将此代码添加到文件中:

first-servers / index.html

     My Website                 Hello Again!        This is served from a file

此网页显示两行文字:Hello Again!并且这是通过文件提供的。这些线条出现在页面的中心,一个在另一个之上。第一行文本显示在标题中,这意味着它会很大。第二行文本看起来会稍微小一些。所有的文字都是白色的,网页的背景是橙色的。

这就是HTML所需的全部内容,因此请使用CTRL + X保存并退出文件。现在,我们可以继续讨论服务器代码了。

在本练习中,我们将使用htmlFile.js。用文本编辑器打开它:

39.png

由于必须读取文件,因此首先导入fs模块:

first-servers / htmlFile.js

40.png

此模块包含一个readFile()函数,我们将使用该函数将HTML文件加载到位。我们导入了promise变量,以符合现代JavaScript最佳实践。我们将promise作为其语法比回调更简洁,如果将fs分配给require('fs'),则必须使用promise。

我们希望在用户请求我们的系统时读取HTML文件,首先,修改requestListener()以读取文件:

first-servers / htmlFile.js

41.png

我们使用fs.readFile()方法加载文件,它的参数有剩余的dirname + "/index.html"。特殊变量__dirname具有运行Node.js代码的绝对路径。然后我们添加/index.html,这样就可以加载之前创建的HTML文件。

现在,让我们在加载HTML页面后返回它:

first-servers / htmlFile.js

42.png

如果fs.readFile()承诺成功解析,它将返回其数据。我们使用then()方法处理这种情况。 contents参数包含HTML文件的数据。

我们首先将Content-Type标头设置为text / html,以告诉客户端我们正在返回HTML数据。然后,我们编写状态代码以指示请求成功。最后,我们向客户端发送我们加载的HTML页面,其中包含content变量中的数据。

fs.readFile()方法有时可能会失败,因此当遇到错误时,我们应该处理这种情况。将此添加到requestListener()函数中:

first-servers / htmlFile.js

43.png

保存文件并使用CTRL + X退出nano。

当一个承诺遇到错误时,它将被拒绝。我们用catch()方法处理这种情况。它接受fs.readFile()返回的错误,将状态代码设置为500,表示遇到内部错误,然后将错误返回给用户。

使用node命令运行我们的服务器:

44.png

在web浏览器中,访问http://localhost:8000,你将看到此页面:

45.png

现在,你已经从服务器返回了一个HTML页面给用户。你可以使用CTRL + C退出正在运行的服务器,这样将看到终端提示符返回。

在生产环境中编写此类代码时,你可能不想每次收到HTTP请求时都加载HTML页面。尽管此HTML页面的大小约为800字节,但更复杂的网站可能有兆字节大小。大文件可能需要一段时间才能加载,如果你的网站流量很大,最好在启动时加载HTML文件并保存其内容。加载后,你可以设置服务器并使其监听地址上的请求。

为了演示此方法,让我们看看如何重新设计服务器,使其更高效、更具可扩展性。

有效地提供HTML

在此步骤中,我们不会在每个步骤中都加载HTML,而是在开始时加载一次。该请求将返回我们在启动时加载的数据。

在终端,用文本编辑器重新打开Node.js脚本:

46.png

在创建requestListener()函数之前,我们先添加一个新变量:

first-servers / htmlFile.js

47.png

当我们运行该程序时,此变量将保存HTML文件的内容。

现在,让我们重新调整requestListener()函数。现在,它不再返回文件,而是返回indexFile的内容:

first-servers / htmlFile.js

48.png

接下来,我们将文件读取逻辑从requestListener()函数转移到服务器启动过程,在创建服务器时进行以下更改:

first-servers / htmlFile.js

49.png

保存文件并按CTRL+X退出nano。

读取文件的代码类似于我们第一次尝试编写的代码,但是,成功读取文件后,现在将内容保存到全局indexFile变量中。然后,我们使用listen()方法启动服务器。关键是在运行服务器之前已加载文件。这样,requestListener()函数将确保返回一个HTML页面,因为indexFile不再是一个空变量。

我们的错误处理程序也已更改,如果无法加载文件,我们将捕获错误并将其打印到控制台。然后,我们使用exit()函数退出Node.js程序,而无需启动服务器。这样,我们可以了解文件读取失败的原因,解决该问题,然后再次启动服务器。

现在,我们创建了不同的web服务器,这些服务器将各种类型的数据返回给用户。到目前为止,我们尚未使用任何请求数据来确定应返回的内容。在Node.js服务器中设置不同的路由或路径时,我们将需要使用请求数据,因此接下来让我们看看它们是如何协同工作的。

步骤4 :使用HTTP请求对象管理路由

我们访问的大多数网站或我们使用的API通常都具有多个终端,因此我们可以访问各种资源。图书管理系统就是一个很好的例子,可以在图书馆中使用。它不仅需要管理图书数据,还需要管理作者数据,以便进行分类和搜索。

即使书籍和作者的数据相关,它们也是两个不同的对象。在这种情况下,软件开发人员通常在不同的终端上为每个对象编写代码,以指示API用户与之交互的是什么类型的数据。

让我们为一个小型图书馆创建一个新服务器,该服务器将返回两种不同类型的数据。如果用户转到我们服务器的地址/books,他们将收到JSON格式的图书列表。如果转到/authors,则会收到JSON格式的作者信息列表。

到目前为止,我们对得到的每个请求都返回相同的响应,让我们快速演示一下。

重新运行我们的JSON响应示例:

50.png

在另一个终端中,让我们像之前一样发出一个cURL请求:

51..png

你会看见:

52.png

现在让我们尝试另一个curl命令:

53.png

按Enter键后,你将看到相同的结果:

54.png

我们没有在requestListener()函数中构建任何特殊的逻辑来处理URL包含/ todos的请求,因此Node.js默认情况下会返回相同的JSON消息。

当我们要构建小型图书馆管理服务器时,我们现在将根据用户访问的终端来区分返回的数据类型。

首先,使用CTRL + C退出正在运行的服务器。

现在,在文本编辑器中打开routes.js:

55.png

首先,将JSON数据存储在requestListener()函数之前的变量中:

first-servers / routes.js

56.png

books变量是一个字符串,其中包含book对象数组的JSON。每本书都有书名、作者和出版年份。

authors变量是一个字符串,其中包含author对象数组的JSON,每个作者都有姓名、出生地和出生年份。

现在我们有了响应将返回的数据,让我们开始修改requestListener()函数以将它们返回到正确的路由。

首先,我们将确保来自服务器的每个响应都具有正确的Content-Type标头:

first-servers / routes.js

57.png

现在,我们希望根据用户访问的URL路径返回正确的JSON。让我们在请求的URL上创建一个switch语句:

first-servers / routes.js

58.png

要从请求对象获得URL路径,我们需要访问它的URL属性。我们现在可以向switch语句添加case来返回适当的JSON。

JavaScript的switch语句提供了一种方法,可以根据对象或JavaScript表达式的值(例如,数学操作的结果)控制运行哪些代码。如果你需要一个关于如何使用它们的教训或提示,请看我们关于如何在JavaScript中使用Switch语句的指南

让我们继续添加一个案例,说明用户何时想要获取我们的图书清单:

first-servers / routes.js

59.png

我们将状态代码设置为200,以表明请求正常,并返回包含图书清单的JSON。现在让我们为作者添加另一个案例:

first-servers / routes.js

60.png

与之前一样,请求的状态码为200。这次,我们返回包含作者列表的JSON。

如果用户尝试转到任何其他路径,我们想返回一个错误,让我们添加默认案例来执行此操作:

routes.js

61.png

我们在switch语句中使用default关键字来捕获以前案例未捕获的所有其他方案。我们将状态代码设置为404,以表示没有找到他们正在寻找的URL。然后,我们设置一个包含错误消息的JSON对象。

让我们测试一下服务器,看看它是否像我们预期的那样运行。在另一个终端,让我们先运行一个命令,看看我们是否得到了我们的图书清单:

62.png

按确认键以查看以下输出:

Output
[{"title":"The Alchemist","author":"Paulo Coelho","year":1988},{"title":"The Prophet","author":"Kahlil Gibran","year":1923}]

到目前为止一切顺利,让我们对/authors进行同样的尝试。在终端中输入以下命令:

64.png

当命令完成时,你将看到以下输出:

Output
[{"name":"Paulo Coelho","countryOfBirth":"Brazil","yearOfBirth":1947},{"name":"Kahlil Gibran","countryOfBirth":"Lebanon","yearOfBirth":1883}]

最后,让我们尝试一个错误的URL,以确保requestListener()返回错误响应:

66.png

输入该命令将显示以下消息:

67.png

你可以使用CTRL + C退出正在运行的服务器。

现在我们已经为用户创建了获取不同数据的不同途径,还添加了一个默认响应,如果用户输入一个我们不支持的URL,它将返回一个HTTP错误。

总结

在这两篇文章中,我们已经制作了一系列Node.js HTTP服务器。首先返回了一个基本的文本响应,然后,继续从服务器返回各种类型的数据:JSON,CSV和HTML。在此基础上,你可以将文件加载与HTTP响应结合起来,从服务器向用户返回HTML页面,并创建一个API,该API使用有关用户请求的信息来确定应在响应中发送哪些数据。

现在,你已经可以创建可以处理各种请求和响应的web服务器。有了这些知识,你就可以创建一个在不同终端向用户返回许多HTML页面的服务器,另外还可以创建自己的API。

要了解Node.js中更多的HTTP Web服务器,你可以阅读http模块上的Node.js文档

本文我翻译自:https://www.digitalocean.com/community/tutorials/how-to-create-a-web-server-in-node-js-with-the-http-module如若转载,请注明原文地址:


文章来源: https://www.4hou.com/posts/VlZX
如有侵权请联系:admin#unsafe.sh