HTTP

HTTP和REST

1. HTTP?

HTTP是应用层网络传输协议。所以,和其他网络协议一样,是为了实现两台电脑之间的信息传输,不过接收的电脑是作为服务器。

组成:

1.1 URL

1. Uniform Resource Locator,统一资源定位符,顾名思义,用来标识服务器上的资源文件,和数据库的id一样,每个文件都得通过URL来查找。
2. url由下划线分隔的字符串组成,以http或https开头

1.2 JSON / XML

JavaScript Object Notation,HTTP协议的数据交换格式,同样的,XML(eXtensible Markup Language)是另一种可选格式。

1.3 request / response

HTTP通过GET、POST、PUT、DELETE等方法(也称HTTP动词)来向服务器发送请求信息,并以HTTP请求消息的形式进行编码。请求消息的组成:

响应消息的组成:

  • 响应行,包含状态码和及其原因 HTTP/1.1 200 OK

  • 响应头字段 Content-Type: text/html

  • 空行

  • 可选的响应体

客户端如何处理,根据状态码和响应头字段。( status codes are machine-readable and reason phrases are human-readable .)

状态码

  • 1xx Information response
  • 2xx Success
  • 3xx Redirection
  • 4xx Client errors
  • 5xx Server errors

2. 使用Node HTTP模块实现一个服务

const http = require('http')

const hostname = 'localhost'
const port = 3000

// 创建服务
const server = http.createServer((req, res) => {
    console.log(req.headers)
    res.statusCode = 200	// 响应状态码
    res.setHeader('Content-Type', 'text/html')	// 响应头
    res.end('<html><body><h1>Hello, World!</h1></body></html>')	// 响应体
})

// 启动服务
server.listen(port, hostname, () => {
    console.log(`Server running at http://${hostname}:${port}/`)
})

3. REST

Resource Representational State Transfer,资源表征状态转移。。。一种Web服务的软件架构风格,REST 从资源的角度来观察整个网络,分布在各处的资源由URI确定,而客户端的应用通过URI来获取资源的表征。

REST定义了一些原则,概述了如何在服务器上提供资源,以及如何通过使用rest API在客户端访问这些资源。

3.1 四个基本设计原则:

  • 使用HTTP协议
  • 无状态
  • 使用URI暴露资源目录
  • 使用XML或JSON传输数据

无状态就意味着通信结束后,服务器不存储任何状态信息。服务端收到请求并恢复后,不记录任何通信状态信息。Uniform Resource Identifier,统一资源定位符。

3.2 REST and HTTP

REST设计的初衷就是有效利用Web服务的优点:

  • 使用URI来寻址资源
  • 在HTTP协议基础上设计
  • 使用request-response cycle

request-response cycle,发送请求,处理请求,回复响应,处理响应。

3.3 Nouns、Verbs、Representations

名词(noun)就是资源,用URL标识,不受约束(unconstrained)。动词(verb)指定对资源和representations执行的操作。

使用GET www.drinks.com/coffee这样的动宾结构就对资源施加影响。

3.3.1 Nouns

在REST中,资源是对信息的关键抽象。信息以资源的形式进行抽象,资源由特定的URL来标识。所以,任何可以被封装并提供的信息都可以标识为资源。可以命名的信息就可以是资源。

资源的命名

从一般到具体路径,类似目录的结构来标识资源

3.3.2 Verbs

Verbs 将映射到我们希望在服务器端的资源上执行的CRUD操作:

  • HTTP GET <--> READ

发出GET请求,从服务端以JSON或XML格式传输数据到客户端

  • HTTP POST <--> CREATE

创建一个资源,资源的内容以JSON或XML格式存储在请求体中,服务端创建资源后,返回错误或构造信息,

  • HTTP PUT <--> UPDATE

更改资源,更改成功后,在请求体返回更改的部分或整条数据

  • HTTP DELETE <--> DELETE

移除资源,移除成功,返回成功信息,资源不存在则返回错误信息

所以,和HTTP一样,REST也保持了幂等性,GET、PUT、DELETE。

3.3.3 Representations

数据是如何表示的,JSON、XML两种格式。

3.4 无状态服务

服务端不追踪客户端状态,客户端记录自己的状态。如果服务端追踪客户端状态,不利于服务的扩展。对于服务端,客户端的每一次请求都是全新的,客户端使用cookie或者客户端数据库追踪自己的状态。所以,每一次请求都要包含足够的信息,以便服务器响应请求的信息。

使用Express创建服务

index.js

const express = require('express'),
      http = require('http'),
      logger = require('morgan'),	// 日志中间件,打印http会话信息
      bodyParser = require('body-parser')

const hostname = 'localhost'
const port = 3000

const app = express()

app.use(logger('dev'))
app.use(express.static(__dirname + '/public'))
app.use(bodyParser.json())	// 解析请求体中的json数据

app.all('/dishes', (req, res, next) => {
    res.statusCode = 200
    res.setHeader('Content-Type', 'text/plain')
    next()
})

app.get('/dishes', (req, res, next) => {
    res.end('Will send all the dishes to you!')
})

app.post('/dishes', (req, res, next) => {
    res.end('Will add the dish: ' + req.body.name + ' with details: ' + req.body.description)
})

app.put('/dishes', (req, res. next) => {
    res.statusCode = 403
    res.end('PUT operation not supported on /dishes')
})

app.delete('/dishes', (req, res\, next) => {
    res.end('Deleting all dishes')
})

app.get('/dishes/:dishId', (req, res, next) => {
    res.end('Will send details of the dish: ' + req.params.dishId + ' to you!')
})

app.post('/dishes/:dishId', (req, res, next) => {
    res.statusCode = 403
    res.end('POST operation not supported on /dishes/' + req.params.dishId)
})

app.put('/dishes/:dishId', (req, res. next) => {
    res.write('Updating the dish: ' + req.params.dishId + '
')
    res.end('Will add the dish: ' + req.body.name + ' with details: ' + req.body.description)
})

app.delete('/dishes/:dishId', (req, res, next) => {
    res.end('Deleting dish: ' + req.params.dishId)
})

app.use((req, res, next) => {
    res.statusCode = 200
    res.setHeader('Content-Type', 'text/html')
    res.end('<html><body><h1>Hello, World!</h1></body></html>')
})

const server = http.createServer(app)

server.listen(port, hostname, () => {
    console.log(`Server running at http://${hostname}:${port}/`)
})

使用Express-Router优化

dishRouter.js

const express = require('express')
const bodyParser = require('body-parser')

const dishRouter = express.Router()

dishRouter.route('/')
.all((req,res,next) => {
    res.statusCode = 200;
    res.setHeader('Content-Type', 'text/plain');
    next();
})
.get((req,res,next) => {
    res.end('Will send all the dishes to you!');
})
.post((req, res, next) => {
    res.end('Will add the dish: ' + req.body.name + ' with details: ' + req.body.description);
})
.put((req, res, next) => {
    res.statusCode = 403;
    res.end('PUT operation not supported on /dishes');
})
.delete((req, res, next) => {
    res.end('Deleting all dishes');
});

module.exports = dishRouter;


index.js
...
const dishRouter = require('./dishRouter')
...
app.use('/dishes', dishRouter)
...
原文地址:https://www.cnblogs.com/wydumn/p/12590656.html