Golang之我想写个"web框架"-2: 构建响应报文

简介: Golang之我想写个"web框架"-2: 构建响应报文

接上一篇文章,我们已经写好了如何去获取请求报文

如果你还从没有接触过http请求报文协议,请参考上一篇文章Golang之我想写个"web框架"-1: 获取请求报文

本篇文章,我们来看下如何构建响应报文



http响应报文协议


http响应报文概述

具体http响应报文大致是这样的


image.png


我们一般将http响应报文,称之为状态行,而后紧跟若干个首部行,上述我们统称为首部行,我们判断报文首部是否结束,其响应报文和请求报文一样,当响应报文结束后,会在其后加入2个CRLF作为分割,而后则根据首部行的Content-Length来记录响应报文主体的长度。


我们分别来解释一下



状态行

状态行除了最后的CRLF以外,中间不允许有CR或者LF


http响应报文的第一行,称之为状态行,是用于记录http状态的。其值分别为 协议版本 、 状态码 以及 短语 各个部分分别用空格隔开,状态行使用CRLF标致结束。


协议版本


这里指的是服务器所使用的http协议版本,注意这里的版本和客户端版本没有关系,例如: 客户端使用1.0版本进行访问,而服务器使用1.1版本进行回复,一般而言,服务器http版本是要等于或高于客户端http版本的。


这里我们可以简单使用curl命令进行测试一下

curl --http1.0 www.juejin.cn -v -I

使用--http1.0是用1.0协议发送请求,-v是指debug请求过程 -I是指请求方法使用HEAD


image.png

通过上述案例可以验证上述观点。



状态码

当客户端向服务器发送请求时,服务器处理时,可能出现多种情况,状态码的作用就是通知客户端响应情况,客户端拿到状态码后,在进行其他判断以及处理。


这里举个简单的例子: 若服务器返回状态码为301,客户端在拿到后,会去取首部行keyLocation的地址,进行再次访问,实际上,我们浏览器也是这么做的。


状态码分为5类,其分类以及含义如下

类别 范围 含义
1XX 100~199 信息提示
2XX 200~299 成功类
3XX 300~399 重定向
4XX 400~499 客户端错误
5XX 500~599 服务器错误



短语

短语的作用是对状态码进行简单的文本描述,这里你可能会好奇,既然有了状态码,为什么还需要短语呢?

其实是这样的,状态码是用于客户端便于控制其流程,而短语是为了让用户方便阅读。


常见的http状态码及其含义

这里简单列举常见的http状态码、及其含义

状态码 短语 含义
100 Continue 服务器收到客户端请求
101 Switching Protocols 协议切换
200 OK 成功
301 Moved Permanently 重定向
400 Bad Request 客户端请求错误
401 Unauthorized 未授权
404 Not Found 找不到资源
500 Internal Server Error 服务器错误
504 Gateway Time-out 网关错误


本节目的是为了编写响应报文,所以这里简单叙述即可,不会再讨论。


首部行

这里首部行格式和http请求报文首部行格式是一样的,都是由key: value\r\n的格式,这里就不啰嗦了。


响应主体

这里应当和请求报文一样,在首部应当添加keyContent-Length,值为响应主体的长度,而后在首部结束后,我们进行相应长度的主体信息。


生成响应报文

我们想要生成响应报文,我们需要什么信息呢?

通过上述信息,我们知晓了,我们生成带响应主体的报文,我们至少需要 协议版本、状态码 以及 短语 , 而后是首部,我们想要包含响应主体,我们至少需要Content-Length来指定我们的长度。


设计响应报文

假设我们想返回给客户端一个<h1>hello world</h1>,我们报文应当如何构建呢?

根据上述概述,我们可以用图示生成一下如下报文。

image.png

其描述可以写为

HTTP/1.0 200 OK
Content-Length: 20
<h1>hello world</h1>


利用go返回其响应报文


我们使用go来返回相应的报文,单单返回意义不大,我们可以承接上一篇文章,来写个题目。

题目: 仅对请求URL/pdudo返回<h1>hello world</h1>,其他则跳转到https://www.juejin.cn


我们可以分析下,客户端连接上来后,要不返回hello world,要不跳转到https://www.juejin.cn,判断的点为请求的URL是否为/pdudo

此伪代码可以写为

if url == /pdudo
    return "<h1>hello world</h1>"
else
    return "https://www.juejin.cn"

如上可知,我们需要返回2种结果,第一种,我们在上面已经写过报文了,关键是第二种,还记得我们前面讲述协议版本所介绍的案例么,我们可以返回301让客户端跳转到https://www.juejin.cn不就可以了么。



代码编写

代码我放到gitee上,如下只是关于本篇的核心代码


构建报文核心代码

type responsePackages struct {
  HttpVersion string
  StatusCode uint
  StatusMsg string
  responseHeader map[string]string
  Body []byte
}
func buildResponsePack(rp responsePackages)([]byte) {
  responseByte := make([]byte,0)
  // 构建状态行
  // 版本
  responseByte = append(responseByte, []byte(rp.HttpVersion+" ")...)
  // 状态码
  responseByte = append(responseByte, []byte(strconv.Itoa(int(rp.StatusCode))+" ")...)
  // 短语
  responseByte = append(responseByte, []byte(rp.StatusMsg+CRLF)...)
  // 首部信息
  for k,v := range rp.responseHeader {
    responseByte = append(responseByte, []byte(k+": ")...)
    responseByte = append(responseByte, []byte(v+CRLF)...)
  }
  // 添加响应主体
  if 0 < len(rp.Body) {
    // 新增 Content-Length
    responseByte = append(responseByte, []byte("Content-Length: "+strconv.Itoa(len(rp.Body))+"\r\n")...)
  }
  responseByte = append(responseByte, []byte(CRLF2)...)
  responseByte = append(responseByte, rp.Body...)
  fmt.Println(string(responseByte))
  return responseByte
}



我们可以根据请求,生成响应的报文,且将数据返回值客户端(部分代码)

// 分析URL
if httpHeader.Url == "/pdudo" {
    // 返回 hello world
    rp.HttpVersion = "HTTP/1.1"
    rp.StatusCode = 200
    rp.StatusMsg = "OK"
    rp.responseHeader["User-Agent"] = "pdudo_golang"
    rp.Body = []byte("<h1>hello world</h1>")
    repBuf = buildResponsePack(rp)
} else {
    // 返回 跳转报文
    rp.HttpVersion = "HTTP/1.1"
    rp.StatusCode = 301
    rp.StatusMsg = "Moved Permanently"
    rp.responseHeader["Location"] = "https://juejin.cn/"
    repBuf = buildResponsePack(rp)
}
// 将repBuf返回给客户端
sendLen := 0
for sendLen < len(repBuf) {
    n ,err := conn.Write(repBuf[sendLen:])
    if err != nil {
        fmt.Println(err)
        return
    }
    sendLen += n
}



测试其正确性

结果真的如此么,我们尝试下

测试链接: http://127.0.0.1:8081/pdudohttp://127.0.0.1:8081/hdasdadwdq

我们先使用curl进行获取一下

image.png


再使用浏览器进行访问

image.png



总结


响应报文状态码至关重要


我们注意到了上面的案例,有一个报文是状态码301,首部信息Locationhttps://juejin.cn/,这这个跳转和服务器没有关系,是客户端(浏览器)拿到状态码之后,发现是301,哦,要进行跳转,然后去拿首部信息的Location进行跳转的。


案例代码已经上传gitee: ResponseMessages.go

怎么样,好玩吧,快动动你的小手指,试试吧。




相关文章
|
19天前
|
前端开发 安全 JavaScript
构建高效Web应用的五个关键步骤
【9月更文挑战第21天】本文将引导读者通过五个核心步骤来构建一个高效的Web应用。我们将从选择合适的技术栈开始,到实现响应式设计、优化性能、保证安全性,最后确保可维护性和扩展性。每个步骤都配备了具体的代码示例,帮助理解如何在实践中应用这些概念。
|
2天前
|
Web App开发 JavaScript 前端开发
使用Node.js和Express框架构建Web服务器
使用Node.js和Express框架构建Web服务器
|
2天前
|
缓存 安全 JavaScript
掌握JAMstack:构建更快、更安全的Web应用
JAMstack 是一种现代 Web 开发架构,结合 JavaScript、APIs 和 Markup,创建更快、更安全的 Web 应用。其核心优势包括高性能、安全性、可扩展性和易维护性。JAMstack 通过预构建静态页面和 API 实现高效渲染,利用静态站点生成器如 Gatsby 和 Next.js,并借助 CDN 和缓存策略提升全球访问速度。尽管面临复杂交互、SEO 和数据更新等挑战,但通过 Serverless Functions、预渲染和实时 API 更新等方案,这些挑战正逐步得到解决。
|
3天前
|
前端开发 JavaScript 微服务
拥抱微前端架构:构建未来Web应用的新思路
随着互联网技术的发展,Web应用日益复杂,传统单体架构已难以满足需求。微前端架构将大型应用拆分为独立模块,便于管理和迭代。其核心优势包括技术栈无关性、独立部署、团队协作及易于扩展。实施时需定义边界、选用框架(如Single-spa)、管理状态通信,并解决样式隔离和安全性等问题。尽管存在挑战,微前端架构凭借灵活性和高效性,有望成为未来Web开发的主流趋势。
|
12天前
|
缓存 移动开发 安全
Web安全-HTTP响应拆分(CRLF注入)漏洞
Web安全-HTTP响应拆分(CRLF注入)漏洞
49 8
|
12天前
|
Web App开发 JavaScript 前端开发
构建高效Web应用:Node.js与Express框架的深度整合
【9月更文挑战第28天】在现代Web开发领域,Node.js和Express框架的结合已成为打造高性能、易扩展应用的黄金组合。本文将深入探讨如何利用这一技术栈优化Web应用架构,提供具体实践指导,并分析其性能提升的内在机制。通过代码示例,我们将展示从基础搭建到高级功能的实现过程,旨在为开发者提供一条清晰的学习路径,以实现技术升级和项目效率的双重提升。
26 3
|
16天前
|
JSON 安全 JavaScript
Web安全-JQuery框架XSS漏洞浅析
Web安全-JQuery框架XSS漏洞浅析
95 2
|
16天前
|
开发框架 JSON 缓存
震撼发布!Python Web开发框架下的RESTful API设计全攻略,让数据交互更自由!
在数字化浪潮推动下,RESTful API成为Web开发中不可或缺的部分。本文详细介绍了在Python环境下如何设计并实现高效、可扩展的RESTful API,涵盖框架选择、资源定义、HTTP方法应用及响应格式设计等内容,并提供了基于Flask的示例代码。此外,还讨论了版本控制、文档化、安全性和性能优化等最佳实践,帮助开发者实现更流畅的数据交互体验。
36 1
|
19天前
|
SQL 缓存 数据库
构建高效Web应用:掌握Python中的ORM映射技术
在Web开发中,数据库操作至关重要,但直接编写SQL语句会增加代码复杂度并降低效率。对象关系映射(ORM)技术通过将对象模型映射为数据库表,使开发者能以面向对象的方式处理数据,提升开发效率和代码可维护性。本文以Python和SQLAlchemy为例,介绍ORM的基本概念、安装方法及使用技巧,并展示其在提升Web应用性能方面的优势。通过ORM,开发者可以简化数据库操作,专注于业务逻辑实现,提高开发效率和代码质量。
38 1
|
1天前
|
JSON API 开发者
深入解析Python网络编程与Web开发:urllib、requests和http模块的功能、用法及在构建现代网络应用中的关键作用
深入解析Python网络编程与Web开发:urllib、requests和http模块的功能、用法及在构建现代网络应用中的关键作用
6 0