HTTP 简易介绍
http 对于一个前端是软实力,其实如果你想往后端靠近,扎实的 HTTP 基础会很好的帮助你。
特点简介
消息结构
请求方法
响应状态
状态码
content-type 内容类型
全名
HyperText Transfer Protocol
超文本传输协议
基于
TCP/IP
传输数据类型
html
文件
查询结果
特点
无状态
媒体独立(只要客户端和服务器知道如何处理的数据内容,任何类型的数据都可以通过HTTP发送)
无连接,一次链接之处理一个请求。也能实现长链接
消息结构
客户端: 请求消息结构
请求行(request line)、请求头部(header)、空行和请求数据四个部分组成
请求行
请求体
空行
请求数据
服务端:响应应消息结果
状态行、消息报头、空行和响应正文。
状态行
消息报头
空行
响应正文
请求方法
HTTP1.0 包含以下三种
GET --- 请求指定的页面信息,并返回实体主体。
POST --- 一般用于创新新的数据、修改已有的数据
HEAD --- 用于获取报头
HTTP1.1 新增六种
OPTIONS --- 允许客户端查看服务器的性能。
PUT --- 从客户端向服务器传送的数据取代指定的文档的内容。
PATCH --- 是对 PUT 方法的补充,用来对已知资源进行局部更新 。
DELETE --- 请求服务器删除指定的页面。
TRACE --- 回显服务器收到的请求,主要用于测试或诊断。
CONNECT --- HTTP/1.1 协议中预留给能够将连接改为管道方式的代理服务器。
所以在 1.1 以及之前,包含 9 中方法。
响应头
Allow
Content-Encoding
Content-Length
Content-Type
Date
Expires
Last-Modified
Location
Refresh
Set-Cookie
WWW-Authenticate
状态码
对于状态码,我们时常不能记住他们具体的用处,有些具有多年工作经验的从业者,也不见得能记住状态码。
下面是最常用的状态码:成功、失败(失败的种类比较多了,所以可以理解为,整个状态码,就是对于 失败的识别,然后然用户知道,发生了什么失败!)
200 - 请求成功
301 - 资源(网页等)被永久转移到其它URL
404 - 请求的资源(网页等)不存在
500 - 内部服务器错误
分类
HTTP状态码分类
1 --- 信息,服务器收到请求,需要请求者继续执行操作
2 --- 成功,操作被成功接收并处理
3 --- 重定向,需要进一步的操作以完成请求
4 --- 客户端错误,请求包含语法错误或无法完成请求
5 --- 服务器错误,服务器在处理请求的过程中发生了错误
脚本化 HTTP
浏览器在 XMLHttpRequest 对象上定义了 HTTP 的API。浏览器中通过 XMLHttpRequest 完成 HTTP 的请求与响应工作。
使用 XMLHTTPRequest 创建一个请求实例
const request = new XMLHttpRequest(); |
其实 XMLHTTPRequest 是有兼容性问题的。在早起的 IE 浏览器宏是并不支持这个对象的。而是用的 ActiveXObject 对象创建。所以,为了兼容会自己封装一个具有兼容性的 XMLHttpRequest 对象,方便使用。
请求流程
open 打开一个请求
设置请求头
send 发送一个请求
监听请求状态
request.onReadyStateChange = function() {} |
响应
获取响应内容
state
readyState
responseText
getResponseHeader
responseXML
nestjs 中 http 状态码
nestjs 使用枚举类型 HttpStatus 定义了 http 状态码
export enum HttpStatus { CONTINUE = 100, SWITCHING_PROTOCOLS = 101, PROCESSING = 102, OK = 200, CREATED = 201, ACCEPTED = 202, NON_AUTHORITATIVE_INFORMATION = 203, NO_CONTENT = 204, RESET_CONTENT = 205, PARTIAL_CONTENT = 206, AMBIGUOUS = 300, MOVED_PERMANENTLY = 301, FOUND = 302, SEE_OTHER = 303, NOT_MODIFIED = 304, TEMPORARY_REDIRECT = 307, PERMANENT_REDIRECT = 308, BAD_REQUEST = 400, UNAUTHORIZED = 401, PAYMENT_REQUIRED = 402, FORBIDDEN = 403, NOT_FOUND = 404, METHOD_NOT_ALLOWED = 405, NOT_ACCEPTABLE = 406, PROXY_AUTHENTICATION_REQUIRED = 407, REQUEST_TIMEOUT = 408, CONFLICT = 409, GONE = 410, LENGTH_REQUIRED = 411, PRECONDITION_FAILED = 412, PAYLOAD_TOO_LARGE = 413, URI_TOO_LONG = 414, UNSUPPORTED_MEDIA_TYPE = 415, REQUESTED_RANGE_NOT_SATISFIABLE = 416, EXPECTATION_FAILED = 417, I_AM_A_TEAPOT = 418, UNPROCESSABLE_ENTITY = 422, FAILED_DEPENDENCY = 424, TOO_MANY_REQUESTS = 429, INTERNAL_SERVER_ERROR = 500, NOT_IMPLEMENTED = 501, BAD_GATEWAY = 502, SERVICE_UNAVAILABLE = 503, GATEWAY_TIMEOUT = 504, HTTP_VERSION_NOT_SUPPORTED = 505, } |
http 状态码广泛用于异常
总结
面试的过程中,关于 http 状态码,记忆模糊,其实 http 也是有规律的,不同的开头的状态码,被分到了不同的类型中。
错误类接口和错误
// 错误接口 interface Error { name: string; message: string; stack?: string; } // 错误构造器接口 interface ErrorConstructor { new(message?: string): Error; (message?: string): Error; readonly prototype: Error; } // 错误类 declare var Error: ErrorConstructor; // Http 异常类 export class HttpException extends Error { public readonly message: any; constructor( private readonly response: string | object, private readonly status: number, ) { super(); this.message = response; } // 获取响应对象 public getResponse(): string | object { return this.response; } // 获取状态码 public getStatus(): number { return this.status; } // 转变成字符串 public toString(): string { const message = this.getErrorString(this.message); return `Error: ${message}`; } // 获取错误字符串 private getErrorString(target: string | object): string { return isString(target) ? target : JSON.stringify(target); } // 静态方法创建 body public static createBody( message: object | string, error?: string, statusCode?: number, ) { if (!message) { return { statusCode, error }; } return isObject(message) && !Array.isArray(message) ? message : { statusCode, error, message }; } } // HttpStatus.BAD_REQUEST 是 400 export class BadRequestException extends HttpException { constructor(message?: string | object | any, error = 'Bad Request') { super( HttpException.createBody(message, error, HttpStatus.BAD_REQUEST), HttpStatus.BAD_REQUEST, ); } } // ConflictException 是 409 export class ConflictException extends HttpException { constructor(message?: string | object | any, error = 'Conflict') { super( HttpException.createBody(message, error, HttpStatus.CONFLICT), HttpStatus.CONFLICT, ); } } // ForbiddenException 是 403 export class ForbiddenException extends HttpException { constructor(message?: string | object | any, error = 'Forbidden') { super( HttpException.createBody(message, error, HttpStatus.FORBIDDEN), HttpStatus.FORBIDDEN, ); } } // GatewayTimeoutException 504 export class GatewayTimeoutException extends HttpException { constructor(message?: string | object | any, error = 'Gateway Timeout') { super( HttpException.createBody(message, error, HttpStatus.GATEWAY_TIMEOUT), HttpStatus.GATEWAY_TIMEOUT, ); } } // GoneException 401 export class GoneException extends HttpException { constructor(message?: string | object | any, error = 'Gone') { super( HttpException.createBody(message, error, HttpStatus.GONE), HttpStatus.GONE, ); } } // 505 export class HttpVersionNotSupportedException extends HttpException { constructor( message?: string | object | any, error = 'HTTP Version Not Supported', ) { super( HttpException.createBody( message, error, HttpStatus.HTTP_VERSION_NOT_SUPPORTED, ), HttpStatus.HTTP_VERSION_NOT_SUPPORTED, ); } } // 418 export class ImATeapotException extends HttpException { constructor(message?: string | object | any, error = `I'm a teapot`) { super( HttpException.createBody(message, error, HttpStatus.I_AM_A_TEAPOT), HttpStatus.I_AM_A_TEAPOT, ); } } // 500 export class InternalServerErrorException extends HttpException { constructor( message?: string | object | any, error = 'Internal Server Error', ) { super( HttpException.createBody( message, error, HttpStatus.INTERNAL_SERVER_ERROR, ), HttpStatus.INTERNAL_SERVER_ERROR, ); } } // 405 export class MethodNotAllowedException extends HttpException { constructor(message?: string | object | any, error = 'Method Not Allowed') { super( HttpException.createBody(message, error, HttpStatus.METHOD_NOT_ALLOWED), HttpStatus.METHOD_NOT_ALLOWED, ); } } // 406 export class NotAcceptableException extends HttpException { constructor(message?: string | object | any, error = 'Not Acceptable') { super( HttpException.createBody(message, error, HttpStatus.NOT_ACCEPTABLE), HttpStatus.NOT_ACCEPTABLE, ); } } // 404 export class NotFoundException extends HttpException { constructor(message?: string | object | any, error = 'Not Found') { super( HttpException.createBody(message, error, HttpStatus.NOT_FOUND), HttpStatus.NOT_FOUND, ); } } // 501 export class NotImplementedException extends HttpException { constructor(message?: string | object | any, error = 'Not Implemented') { super( HttpException.createBody(message, error, HttpStatus.NOT_IMPLEMENTED), HttpStatus.NOT_IMPLEMENTED, ); } } // 413 export class PayloadTooLargeException extends HttpException { constructor(message?: string | object | any, error = 'Payload Too Large') { super( HttpException.createBody(message, error, HttpStatus.PAYLOAD_TOO_LARGE), HttpStatus.PAYLOAD_TOO_LARGE, ); } } // 408 export class RequestTimeoutException extends HttpException { constructor(message?: string | object | any, error = 'Request Timeout') { super( HttpException.createBody(message, error, HttpStatus.REQUEST_TIMEOUT), HttpStatus.REQUEST_TIMEOUT, ); } } // 503 export class ServiceUnavailableException extends HttpException { constructor(message?: string | object | any, error = 'Service Unavailable') { super( HttpException.createBody(message, error, HttpStatus.SERVICE_UNAVAILABLE), HttpStatus.SERVICE_UNAVAILABLE, ); } } // 401 export class UnauthorizedException extends HttpException { constructor(message?: string | object | any, error = 'Unauthorized') { super( HttpException.createBody(message, error, HttpStatus.UNAUTHORIZED), HttpStatus.UNAUTHORIZED, ); } } // ... |
在 nestjs 中抛出一个异常
标准异常
标准异常的格式如下,只有两个字段:状态码和错误提示消息
{ "statusCode": 500, "message": "Internal server error" } |
下面我们可以控制器中,使用 throw 实例化HttpException 类型,输出标准的异常:
@Get() async findAll() { throw new HttpException('Forbidden', HttpStatus.FORBIDDEN); } |
第一个参数是 message, 第二个参数是状态码。
覆盖标准输出,自定义一些信息,只需要将第一个参数改成一个对象:
@Get() async findAll() { throw new HttpException({ status: HttpStatus.FORBIDDEN, error: 'This is a custom message', }, HttpStatus.FORBIDDEN); } |
当然我们可以自定义类,方便我们复用其他的项目:
export class ForbiddenException extends HttpException { constructor() { super('Forbidden', HttpStatus.FORBIDDEN); } } |
异常与过滤器层配合
异常过滤器,是使得有能力完全的控制异常。可以控制确切的控制流以及将响应的内容发送回客户端。
过滤可以作用于:
路由函数
controller 类
在全局中使用
捕获全部的异常
todo
jsonp
轮询
comet
本文内容不用于商业目的,如涉及知识产权问题,请权利人联系51Testing小编(021-64471599-8017),我们将立即处理