Node中的HTTP

2023-05-16

来自对《了不起的Node.js》一书的学习

HTTP协议

  1. 超文本传输协议,又称为HTTP,是一种Web协议。
  2. HTTP协议构建在请求和响应的概念上,对应在Node.js中就是由http.ClientRequest和http.ServerResponse这个两个构造器构造出来的对象(Node.js v6.2.0)。
  3. HTTP协议在请求和响应消息前使用头信息(header)来描述不同的消息内容。
  4. 发送内容的类型(type)由头信息中的Content-Type头信息来标注,Web页面会分发许多不同类型的内容:文本(text)、HTML、XML、JSON、PNG以及JPEG图片,等等。
  5. 在Node.js中,Node会默认在响应消息的头信息中加入Transfer-Encoding和Connection。
  6. Transfer-Encoding头信息的默认值为chunked,主要的原因是Node天生的异步机制,这样响应就可以逐步产生。
      一般情况下,HTTP的Header包含Content-length域来指明报文体的长度。有时服务生成HTTP回应是无法确定消息大小的,比如大文件的下载,或者后台需要复杂的逻辑才能全部处理页面的请求,这时就需要实时生成消息长度,服务一般使用chunked编码。
  7. 在Node.js中TCP服务器和HTTP服务器的实现,都调用了createServer方法,并且当客户端连入时都会执行一个回调函数。不同的是,回调函数中的对象的类型。在net服务器中(TCP服务器),是个连接(connection)对象,而在HTTP服务器中,则是请求和响应对象。
      之所以会这样,原因有两个。
      1)HTTP服务器是更高层的API,提供了控制和HTTP协议相关的一些功能。实际上Node.js为我们封装了请求消息和响应消息对象。
      2)同时也是一个更为重要的原因是,浏览器在访问站点时不会就只用一个连接。
      默认情况下,Node会告诉浏览器始终保持连接,通过它发送更多的请求。这是通过此前我们看到的Connection头信息中的keep-alive值来通知浏览器的。为了提高性能(因为浏览器不想浪费时间去重新建立和关闭TCP连接),这样做通常是对的。不过,我们也可以调用writeHead方法,传递一个不同的值,如Close,来将其重写掉。

一个简单的Web服务器

  1. 创建模块:npm init。
{
  "name": "http-form",
  "version": "0.0.1",
  "description": "An HTTP server that process forms",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "",
  "license": "ISC"
}

初始化项目。
2. 创建server.js,向客户端输出一个表单:

var http = require('http');

http.createServer(function(req, res) {
    // console.log(req.url);

    res.writeHead(200, {'Content-Type': 'text/html'});
    res.end([
        '<form method="POST" action="/url">',
        '<h1>My form</h1>',
        '<fieldset>',
        '<label>Personal information</label>',
        '<p>What is your name?</p>',
        '<input type="text" name="name">',
        '<p><button>Submit</button></p>',
        '</form>'
        ].join(''));
}).listen(3000);

其中,表单提交的地址为/url,同时采用POST方法。
3. 使用 node server.js 来运行服务器。
4. 在浏览器中访问:127.0.0.1:3000,我们会在浏览器中看到输出来的表单。
页面-表单
页面显示的结果。
5. 为了实现接收表单提交的数据,我们来将上述server.js代码中的console.log这一行代码注释掉,在重新运行服务器,看看在命令行中会出现什么。
输出结果
  我们在浏览器中修改url地址呢?在127.0.0.1:300后面加上 /url ,我们想访问这样的地址,会出现什么样的结果呢?
请求结果
  看,我们请求的 /url 地址被输出显示出来了(有点莫名其妙,我们先不管——居然这样访问,不会404报错,而是被服务器正确接收,在server.js的回调方法中打印出用户访问的相对地址),同时在浏览器中显示的结果还是同刚才访问的页面一样。
  那么我们就可以在server.js中的回调方法中判断当前请求的地址,来对应是否在form表单请求的地址,如果是,则对该请求进行相应的处理。
6. 在server.js中需要对请求对象上的url属性进行检测。server.js的代码如下所示:

var http = require('http');

http.createServer(function(req, res) {
    // console.log(req.url);
    if('/' == req.url) {
        res.writeHead(200, {'Content-Type': 'text/html'});
        res.end([
            '<form method="POST" action="/url">',
            '<h1>My form</h1>',
            '<fieldset>',
            '<label>Personal information</label>',
            '<p>What is your name?</p>',
            '<input type="text" name="name">',
            '<p><button>Submit</button></p>',
            '</form>'
            ].join(''));    
    } else if('/url' == req.url) {
        res.writeHead(200, {'Content-Type': 'text/html'});
        res.end('You sent a <em>' + req.method + '</em> request.');
    }

}).listen(3000);

  再次运行node server.js,刷新页面看看,这次提交表单会有什么变化吧。
7. 这会能猜到结果了吧,当我们直接提交表单后会跳转 /url 链接,此时服务器接收到发现请求是 /url 地址,就进行了相应的处理,返回相应的内容被浏览器接收,最后给浏览器显示出来。
8. 那么我们现在在浏览器访问其他地址呢,会发现浏览器会请求很久很久,最后提示我们:
请求结果
  这是因为我们在服务器中没有对其他地址进行响应的操作。
  注:Node.js会将主机名后所有的内容都放在(req.)url属性中。
9. 接下来我们需要接收form表单提交过来的数据。需要注意的是:请求消息也可以包含Content-Type头信息。就像响应消息有Content-Type头信息来告诉浏览器它返回了什么数据一样,浏览器发送请求是也可以告诉服务器我发送了什么类型数据给你(服务器)了。server.js代码如下:

var http = require('http');

http.createServer(function(req, res) {
    // console.log(req.url);
    if('/' == req.url) {
        res.writeHead(200, {'Content-Type': 'text/html'});
        res.end([
            '<form method="POST" action="/url">',
            '<h1>My form</h1>',
            '<fieldset>',
            '<label>Personal information</label>',
            '<p>What is your name?</p>',
            '<input type="text" name="name">',
            '<p><button>Submit</button></p>',
            '</form>'
            ].join(''));    
    } else if('/url' == req.url && 'POST' == req.method) {
        var body = '';
        req.on('data', function(chunk) {
            body += chunk;
        });
        req.on('end', function() {
            res.writeHead(200, {'Content-Type': 'text/html'});
            // res.end('You sent a <em>' + req.method + '</em> request.');
            res.end('<p>Content-Type: ' + req.headers['content-type'] + '</p>'
                + '<p>Data:</p><pre>' + body + '</pre>');
        });
    }

}).listen(3000);

  运行结果如下:
运行结果
  结果显示:提交的数据Content-Type,即数据格式为键值对字符串的形式,或者说是一个查询字符串(key1=value1&key2=value2&…)。我们需要对该字符串进行解析,生成我们想要的对象,便于操作。好在Node.js为我们提供了一个称为querystring的模块,方便地对这类字符串进行解析。
  querystring模块将一个字符串解析成一个对象。这个解析处理方法和Node解析headers消息的方式类似,Node将HTTP请求数据中的headers信息从字符串解析成一个方便处理的headers对象。
10. 使用querystring的parse方法对请求内容进行解析,然后从解析生成的对象中获取name值,并将其展示给用户。server.js部分代码修改如下:
  引入querystring模块:

var qs = require('querystring');

  修改req.end中的回调:

req.on('end', function() {
            res.writeHead(200, {'Content-Type': 'text/html'});
            // res.end('You sent a <em>' + req.method + '</em> request.');
            /*res.end('<p>Content-Type: ' + req.headers['content-type'] + '</p>'
                + '<p>Data:</p><pre>' + body + '</pre>');*/
            res.end('<p>Your name is <b>' + qs.parse(body).name + '</b></p>');
        });

  重新运行后正确显示结果。
11. 如果URL没有匹配到任何判断条件,那么服务器将会一直没有响应,浏览器一直都处在挂起的状态。要解决这样的问题,我们可以在服务器不知道如何处理请求时,发送404(Not Found)状态码给客户端。server.js部分代码修改如下:

} else {
    res.writeHead(404);
    res.end('Not Found');
}

  这个时候,我们才真正完成了第一个HTTP Web服务器!!!

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Node中的HTTP 的相关文章

  • 从开放的 HTTP 流中读取数据

    我正在尝试使用 NET WebRequest WebResponse 类来访问 Twitter 流 API 此处 http stream twitter com spritzer json 我需要能够打开连接并从打开的连接中增量读取数据 目
  • AWS ALB 截断 HTTP 响应

    我有一个带有目标组的 ALB 和运行 PHP API 的 ECS 集群 我正在尝试查询 API 以获得 CSV 响应 但如果请求通过 ALB 我会得到被截断的结果 当我通过 SSH 连接到运行集群的 EC2 实例并尝试手动运行curl 通过
  • 是否可以在ajax get请求中获取页面的一部分?

    我知道我们可以在向服务器发出 GET 请求时获取整个页面 但是如果我只对该页面上的一个特定 div 感兴趣 或者更准确地说对其内容感兴趣 该怎么办 这里唯一的选择是获取整个页面 例如使用 jquery find 从中获取 div 内容吗 或
  • Spring webflow 应用程序:HTTP 302 暂时移动

    我的 java 应用程序中的每个请求都会生成另外 2 个带有 HTTP 302 错误的请求 例如 如果请求查看名为板 html 这个请求是从首页 html 我收到按以下顺序生成的 3 个请求 POST home html 302 Moved
  • 如何使用 http 将 Android 中的文件从移动设备发送到服务器?

    在android中 如何使用http将文件 数据 从移动设备发送到服务器 很简单 您可以使用 Post 请求并将文件作为二进制 字节数组 提交 String url http yourserver File file new File En
  • 将 HttpApi 与 I/O 完成端口结合使用

    我刚刚偶然发现了微软的HTTP 服务器 API http msdn microsoft com en us library aa364510 28v vs 85 29 aspx 简介中写道 HTTP 服务器 API 使应用程序能够通过 HT
  • 如何解析 Content-Disposition 标头以检索文件名属性?

    使用 go 如何解析从 http HEAD 请求检索到的 Content Disposition 标头以获取文件的文件名 此外 如何从 http HEAD 响应中检索标头本身 这样的事情正确吗 resp err http Head http
  • 如何使用 Emacs 通过 HTTP 打开远程文件?

    大多数开源软件都通过某些 HTTP 服务公开其代码 我想从 Emacs 打开并浏览此类代码 但 AFAICS trapmp 只允许ssh and ftp 因此 我的第一个问题是如何打开 HTTP URL 以便在 Emacs 中进行读取 然后
  • 使用特定 HTTP 方法链接到页面 (DELETE)

    如何像 Rails 那样链接到页面并让浏览器使用 DELETE 方法调用它 我试过 a href DELETE ME a 但不起作用 我使用 Node js 所以我可以用它来处理 DELETE 方法 你不能 链接只会触发 GET 请求 您可
  • 防止 ASP.Net 中的表单重新提交(不重定向到我自己)

    我有一个带有表单元素的母版页
  • ASP.NET 中 HTTP 缓存相关标头的有效含义

    我正在 ASP NET 2 0 中开发一个 Web 应用程序 其中涉及通过资源处理程序 ashx 提供图像 我刚刚实现了处理缓存标头和条件 GET 请求 这样我就不必为每个请求提供所有图像 但我不确定我是否完全理解浏览器缓存发生了什么 图像
  • Android - API 请求

    我开发了一个应用程序 它也在 iPhone 上 问题出在 api 请求上 我为所有请求设置了超时 有时会出现 30 60 秒的中断 看起来这个应用程序执行了几个请求 然后就中断了 一直超时 大约 45 秒后一切正常 不知道是服务器问题还是安
  • 在java中轮询Http服务器(重复发送http get请求)

    当对其进行 REST 调用时 我的 Web 服务器会发送一些信息 我想不断轮询该服务器 间隔5秒后重复发送HTTP GET请求 以检查返回的信息是否有任何变化 做到这一点最有效的方法是什么 您能提供一些代码示例吗 请注意 我只想开发客户端代
  • 如何在flutter项目中使用http拦截器?

    我必须向我的所有 Api 添加标头 有人告诉我为此使用 http 拦截器 但我无法理解如何做到这一点 因为我是颤振的新手 谁能帮我举个例子吗 您可以使用http 拦截器 https pub dev packages http interce
  • JS 库请求的常见 HTTP 标头是什么?

    使用JavaScript 框架原型 http www prototypejs org 我注意到 Ajax 请求通过一个名为X Requested With 其他 JavaScript 库 如 jQuery dojo 和 YUI 是否会向其
  • UNIX/MacOS 上静态文件的“临时 Web 服务器”?

    是否有一个像小型网络服务器这样的东西 我可以从命令行调用它 只从本地文件系统获取文件并通过特定端口上的 HTTP 为它们提供服务 我希望能够做这样的事情 cd Sites mysite serve 10 0 1 1 8080 这应该会启动一
  • WCF WebHttp 混合身份验证(基本和匿名)

    所有这些都与 WebHttp 绑定有关 托管在自定义服务主机中 IIS 目前不是一个选项 我已经实现了自定义 UserNamePasswordValidator 和自定义 IAuthorizationPolicy 当我将端点的绑定配置为使用
  • 使用 flash 或 java servlet 将麦克风数据从浏览器上传到服务器的教程? [关闭]

    Closed 这个问题不符合堆栈溢出指南 help closed questions 目前不接受答案 There was a question on how to get data from a microphone on a client
  • 使用 WCF 支持“application/x-www-form-urlencoded”发布数据的最佳方式?

    我正在基于 W3C 规范构建 WCF 服务 该规范定义了接受 application x www form urlencoded 发布数据的 RESTful Web 服务端点 默认情况下 WCF 不支持这种类型的消息编码 我发现了许多创建如
  • 如何将文件透明地传输到浏览器?

    受控环境 IE8 IIS 7 ColdFusion 当从 IE 发出指向媒体文件 例如 mp3 mpeg 等 的 GET 请求时 浏览器将启动关联的应用程序 Window Media Player 我猜测 IIS 提供文件的方式允许应用程序

随机推荐

  • Android 系统禁止应用的某个弹框

    需求 xff1a 谷歌拼音输入法首次使用会弹出以下提示 xff0c 为了提高用户体验 xff0c 在系统层屏蔽此弹窗 这里以谷歌输入法首次使用为例 分析 xff1a 系统dialog的弹出都是集成Dialog java 所以我们先找到dia
  • mysql中的null值和空值区别

    转载自 xff1a 点击打开链接 标签 xff1a 笔记 mysql null 发表时间 xff1a 2014 06 06 23 46 作者 xff1a 出处 xff1a http jackyrong iteye com mysql中的nu
  • bootstrap-table的入门使用——从服务器获取数据

    参考 xff1a Bootstrap Table 查询 xff08 服务器端 xff09 刷新数据 这里需要使用 bootstrap table 插件 使用了CSS3loader显示加载过程 效果如下 xff1a index html lt
  • MySql中UTF8 和 GBK 编码中文字符长度问题

    转载自 xff1a MySql中UTF8 和 GBK 编码中文字符长度问题 MySql中UTF8 和 GBK 编码中文字符长度问题 出处 xff1a http blog csdn net 为什么要了解MySql中UTF8 和 GBK 编码中
  • PHP对表单提交特殊字符的过滤和处理

    转载自 xff1a PHP对表单提交特殊字符的过滤和处理 函数名 释义 介绍htmlspecialchars将与 单双引号 大于和小于号化成HTML格式 amp 转成 amp amp 34 转成 amp quot 39 转成 amp 039
  • ThinkPHP中数据库操作返回值总结

    转载自 xff1a ThinkPHP中数据库操作返回值总结 关键字 xff1a Thinkphp 返回值 数据库操作 select返回值 add返回值 setDec返回值 Thinkphp中的Think Model类提供了数据库的基本CUR
  • 基于 Token 的身份验证

    转载自 xff1a 基于 Token 的身份验证 最近了解下基于 Token 的身份验证 xff0c 跟大伙分享下 很多大型网站也都在用 xff0c 比如 Facebook xff0c Twitter xff0c Google 43 xff
  • 打造 Bootstrap Tags Input 同 Modal 结合的利器

    Boostrap Tags input 的使用 xff1a http bootstrap tagsinput github io bootstrap tagsinput examples Boostrap Tags Input 插件基于Bo
  • 打造 Bootstrap Tags Input 同 Modal 结合的利器(改)

    对上文 打造 Bootstrap Tags Input 同 Modal 结合的利器 中的 js 进行整合 xff0c 如下 xff1a bootstrap tagsinput demo js Created by DreamBoy on 2
  • 我的简单PHP框架——LabPHP v1.0.1

    此前讲到 我做的一个基于MVC设计思想的简单PHP框架 xff08 我的简单PHP框架 LabPHP xff09 xff0c 这里对其进行一些改进 xff0c 改进地方如下 xff1a 1 对 LabPHP Common functions
  • 关于ThinkPHP中URL及模板文件名大小写的讨论

    参考 xff1a ThinkPHP3 2 3完全开发手册 URL模式 thinkphp中处理url大小写敏感的技术方案 TP模板因路径大小写获取不到的Bug 特别地 xff0c 需要注意的是 xff1a 调试模式下URL区分大小写 xff1
  • 【免费送书】说说哪本书曾经让你爱不释手

    编程狗在线 自由的编程学习平台 一本好书带给人的不止于知识收获 xff0c 还会对你的成长有所帮助 xff0c 与你的每次经历产生共鸣 每天读一点 xff0c 坚持不懈 xff0c 你就能成为专业高手 如果你能每两个月读一本好的编程书 xf
  • PHP中的cURL函数

    今天看了一个接口的使用 xff0c 其中接口的示例中使用到PHP的cURL函数 xff0c 那么有趣的事情就来了 使用PHP向某个URL发送数据并接收响应数据 xff1a function request data url data 61
  • 设计模式之适配器(Adapter)模式

    转载自 xff1a 设计模式学习笔记 适配器 Adapter 模式 参考 xff1a Java设计模式之Adapter模式 2 自己阅读了原文中的例子颇有受益 xff0c 在此前常听到Java中adapter适配器一词 xff08 虽说现在
  • Java软件体系结构设计模式之结构模式 知识点摘录

    以下知识点摘录自 xff1a Java软件体系结构设计模式标准指南 一书 其中可能包含本人的一些感悟 Java软件体系结构设计模式之结构模式 xff08 11种 xff09 结构模式主要用来 xff1a 1 xff09 处理把责任委托给其他
  • 支付宝在线支付接口开发教程与总结

    转载自 xff1a 支付宝在线支付接口开发教程与总结 1 什么是第三方支付 所谓第三方支付 xff0c 就是一些和各大银行签约 并具备一定实力和信誉保障的第三方独立机构提供的交易支持平台 在通过第三方支付平台的交易中 xff0c 买方选购商
  • Android 应用商店评分+APP分享

    转载自 xff1a Android Market链接的生成 调用Market 搜索软件 Android 调用已安装市场 xff0c 进行软件评分的功能实现 参考 xff1a Android跳转到应用商店的APP详情页面 xff0c 以及 G
  • 用一个二维码做下载地址,自动区分是 ios 还是 android

    转载自 xff1a 用一个二维码做下载地址 xff0c 自动区分是 ios 还是 android 更多参考 xff1a 好推二维码如何通过应用宝微下载支持微信自动打开APP下载 xff1f 用一个二维码做下载地址 xff0c 自动区分是 i
  • Node中的JavaScript

    Node中的JavaScript global对象 在浏览器中 xff0c 全局对象指的就是window对象 xff1b Node中有两个类似却各自代表着不同含义的对象 xff1a global和process xff1b 任何global
  • Node中的HTTP

    来自对 了不起的Node js 一书的学习 HTTP协议 超文本传输协议 xff0c 又称为HTTP xff0c 是一种Web协议 HTTP协议构建在请求和响应的概念上 xff0c 对应在Node js中就是由http ClientRequ