资讯专栏INFORMATION COLUMN

Node.js系列-http

JinB / 578人阅读

摘要:是无状态协议,意味着服务器不会在两个请求直接保留任何数据状态。客户端发送一个请求到服务器的请求消息包括以下格式请求行请求头部空行和请求数据四个部分组成。读取服务端返回的报文信息响应状态行消息报头空行和响应正文。

HTTP了解

超文本传输协议(HTTP)是用于传输褚如HTML的超媒体文档的应用层协议。
它被设计用于Web浏览器和Web服务器之间的通信,但它也可以用于其他目的。
HTTP遵循经典的客户端-服务端模型,客户端打开一个连接以发送请求,然后等待它收到服务器端响应。
HTTP是无状态协议,意味着服务器不会在两个请求直接保留任何数据(状态)。

HTTP概述



HTTP是应用层的协议,虽然理论上它可以通过任何可靠的传输协议来发送,但是它还是
通过TCP或者是TLS-加密的TCP连接来发送。
它不仅被用来传输超文本文档,还用来传输图片、视频或者向服务器发送如HTML表单这样的信息。HTTP还可以根据网页需求,仅获取部分Web文档内容更新网页。

HTTP组件系统

HTTP是一个client-server协议:请求通过一个实体(即用户代理)被发出。大多数情况下,这个用户代理都是指浏览器,也可能是一个爬区网页生成维护搜索引擎索引的机器爬虫等。
每一个发送到服务器的请求,都会被服务器处理并返回一个消息(response)。在client和server之间,还有许多的被称为proxies的实体,他们的作用和表现各不相同,比如有些是网关,caches等。

实际上,在一个浏览器和处理请求的服务器之间,还有计算机、路由器、调制解调器等许多实体。由于Web的层次设计,那些在网络层和传输层的细节都被隐藏起来了。

客户端:user-agent

user-agent就是任何能够为用户发起行为的工具。但实际上,这个角色通常都是由浏览器来扮演。
要渲染出一个网页,浏览器首先要发送第一个请求来获取页面的HTML文档,再解析文档中的资源信息发送其他请求,获取可执行脚本或css样式来进行页面布局渲染,以及一些其它网页资源(如图片和视频等)。然后,浏览器将这些资源整合在一起,展示出一个完整的文档,也就是网页。
一个网页就是一个超文本文档,有一部分显示的文本可能是链接,启动它(通常是鼠标的点击)就可以获取一个新的网页。网页使得用户可以控制客户端进行网上冲浪。由浏览器来负责发送HTTP请求,呈现HTTP返回消息,让用户能清晰地看到返回的网页内容。

Web服务端

在上述通信过程的另一端,是由Web Server来服务并提供客户端所请求的文档。Server只是虚拟意义上的:
它可以是许多共同分担负载(负载均衡)一组服务器组成的计算机集群,也可以是一种复杂的软件,通过向其他计算机发起请求来获取部分或全部资源。
Server不再只是一枚多带带的机器,它可以是在同一个机器上装载的众多服务之一。在HTTP/1.1Host头部中,它们甚至可以共享同一个IP地址。

代理(proxies)

在浏览器和服务器之间,有许多计算机和其他设备转发了HTTP消息。由于Web栈层次结构的原因,它们大多都出现在传输层、网络层和物理层上,对于HTTP应用层而言就是透明的,虽然它们可能会对应用层性能有重要影响。还有一部分也表现在应用层上,就是代理(Proxies)。代理既可以表现得透明,又可以
不透明(得看请求是否通过它们),代理主要有一下作用:
1.缓存(可以是公开的也可以是私有的,像浏览器的缓存)
2.过滤(像反病毒扫描,家长控制...)
3.负载均衡(让多个服务器服务不同的请求)
4.认证(对不同资源进行权限管理)
5.登陆(允许存储历史信息)

HTTP基本性质

HTTP是简单的

HTTP是可扩展的

在HTTP/1.0中出现的HTTP headers让协议扩展变得非常容易。只要服务端和客户端就新headers达成语义一致,新功能就可以加入进来。

HTTP是无状态,有会话的

HTTP是无状态的:在同一个连接中,两个执行成功的请求直接是没有关系的。使用HTTP的头部扩展,HTTP Cookies就可以创建有状态的会话。把Cookies添加到头部中,创建一个会话让每次请求都能共享相同的上下文信息,达成相同的状态。

HTTP 和连接

一个连接是由传输层来控制的,这基本不属于HTTP的范围。HTTP并不需要其下传输层的协议是面向连接的,只需要它是可靠的,就是说不能丢失消息。
HTTP/1.0曾为每一个请求/响应都打开一个TCP连接,导致了2个缺点:打开一个TCP连接需要多次消息传递,速度很慢。但当多个消息周期性发送时,这样就变得更加高效。
为了减少连接开销,HTTP/1.1引入了流水线和持久连接的概念:下层的TCP连接可以通过Connection头部来部分控制。HTTP/2则发展得更远,通过一个连接多个消息的方式来让这个链接始终保持为暖连接。

HTTP 流

当客户端想要和服务端进行信息交互时(服务端是指最终服务器,或者是一个中间代理),过程表现为:
1 打开一个TCP连接(或重用之前的一个):TCP连接用来发送一条或多条请求,当然也用来接受回应消息。
客户端可能重用一个已经存在的连接,或者也可能重开几个新的TCP连接连向服务端。
2 发送一个HTTP报文(HTTP请求):HTTP报文(在HTTP/2之前)是语义可读的。在HTTP/2中,这些简单的消息被封装在
了帧中,这使得报文不能被直接读出来,但是报告格式仍是相同的。
客户端发送一个HTTP请求到服务器的请求消息包括以下格式:请求行、请求头部、空行和请求数据四个
部分组成。

3 读取服务端返回的报文信息(HTTP响应):状态行、消息报头、空行和响应正文。

content-type:内容类型,一般是指网页中存在的Content-type,用于定义网络问卷的类型和网页的编码,
决定浏览器将以什么形式、什么编码读取这个文件。
4 关闭连接或者为后续请求重用连接。
当HTTP流水线启动时,后续请求都可以不用等待第一个请求的成功回应就被发送。

起个demo

通过起一个HTTP服务进行简单的增删改查操作。
通过require HTTP 模块并创建一个服务器实例createServer,并监听8200端口即可完成监听端口并创建HTTP实例。
参考api:http://nodejs.cn/api/http.html

const http=require("http");
const server=http.createServer();
server.on("request",(req,res)=>{
    res.end("server had created");
});
server.listen(8200);

通过简单的了解后并启动HTTP服务后,我们即可根据request.method的请求方式对数据进行简单的增删改查的操作。

const http=require("http");
const url=require("url");//用于 URL 处理与解析
const server=http.createServer();
server.listen(8200);

let users=[];
server.on("request",(req,res)=>{
    const parseUrl=url.parse(req.url);
    if(parseUrl.path.indexOf("/user")===-1){
        res.statusCode=403;
        res.end(`${res.statusCode} not allowed` );
        return;
    }
    switch(req.method){
        case "GET":
            if(parseUrl.path.indexOf("/user/")>-1){
                let userName=parseUrl.path.substring(6,parseUrl.path.length);
                let user=users.find(u=>u.name===userName);
                res.statusCode=200;
                res.end(JSON.stringify(users));
            }
            break;
        case "POST":
            req.on("data",(buffer)=>{
                const userStr=buffer.toString();
                let contentType=req.headers["content-type"];
                if(contentType==="application/json"){
                    let user=JSON.parse(userStr);
                    users.push(user);
                }
                res.statusCode=201;
            });
            req.on("end",()=>{
                res.statusCode=200;
                res.end(JSON.stringify(users));
            });
            break;
        case "PATCH":
            req.on("data",(buffer)=>{
                let userStr=buffer.toString();
                let contentType=req.headers["content-type"];
                if(contentType==="application/json"){
                    let update=JSON.parse(userStr);
                    let user=users.find(u=>u.name===update.name);
                    console.log(user);
                    user.address=update.address;
                }
                res.statusCode=201;
            });
            req.on("end",()=>{
                res.statusCode=200;
                res.end(JSON.stringify(users));
            });
            break;
        case "DELETE":
            req.on("data",(buffer)=>{
                let contentType=req.headers["content-type"];
                if(contentType==="application/json"){
                    let index=users.find(u=>u.name===buffer.name);
                    users.splice(index,1);
                }
                res.statusCode=201;
            });
            req.on("end",()=>{
                res.statusCode=200;
                res.end(JSON.stringify(users));
            });
            break;
    }
});
Postman

为了方便模拟发送请求,我们可以下载个postman进行http请求的发送。这样我们就完成了简单的基于HTTP请求的对数据的操作了。

书籍推荐

《图解HTTP》、《HTTP权威指南》

参考链接

MDN:https://developer.mozilla.org...
菜鸟教程:http://www.runoob.com/http/ht...

备注

文章首发博客:http://www.cnblogs.com/aaron-...

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/92864.html

相关文章

  • Node.js开发系列(一)

    摘要:使用和开发系列之一配置如果你对的安装不熟悉,请参阅其他教程安装和。配置如下这里我们使用和两个依赖包。然后在项目的文件下执行,等待执行完成。这时候的文件目录下应该包含了这个文件夹。小结这是一个最简单的的一个示例,下一节我们使用来构造服务。 使用node.js,express和pug开发web系列之一 配置package.json如果你对node的安装不熟悉,请参阅其他教程安装node和n...

    Yi_Zhi_Yu 评论0 收藏0
  • Node.js开发系列(一)

    摘要:使用和开发系列之一配置如果你对的安装不熟悉,请参阅其他教程安装和。配置如下这里我们使用和两个依赖包。然后在项目的文件下执行,等待执行完成。这时候的文件目录下应该包含了这个文件夹。小结这是一个最简单的的一个示例,下一节我们使用来构造服务。 使用node.js,express和pug开发web系列之一 配置package.json如果你对node的安装不熟悉,请参阅其他教程安装node和n...

    X_AirDu 评论0 收藏0
  • Node.js 系列:原生 Node.js 应用

    摘要:原生应用是一个基于引擎的运行环境使用了一个事件驱动非阻塞式的模型,使其轻量又高效的包管理器,是全球最大的开源库生态系统本文主要介绍构建一个应用的基本步骤和模块,并假定你已经对有一定的了解本文引用部分代码作为例子,如果希望参看全部源码,欢迎去 原生 Node.js 应用 Node.js 是一个基于 Chrome V8 引擎的 JavaScript 运行环境Node.js 使用了一个事件驱...

    Ocean 评论0 收藏0
  • Node.js开发系列(三)

    摘要:上一节我们使用代替做了一个简单的应用模块分离现在我们再次来改造这个最简单的应用。重新启动在浏览器输入,可以看到显示。小结我们成功分离了模块,使得代码逻辑更清晰,方便我们下一步继续路由控制的功能 上一节我们使用express代替http做了一个简单的web应用 模块分离现在我们再次来改造这个最简单的应用。新建一个start.js文件 var http = require(http); v...

    mumumu 评论0 收藏0

发表评论

0条评论

JinB

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<