【计网】【计网】从零开始学习http协议 ---理解http重定向和请求方法

在这里插入图片描述

去光荣地受伤,
去勇敢地痊愈自己。
--- 简嫃 《水问》---

从零开始学习http协议

  • 1 知识回顾
  • 2 认识网络重定向
  • 3 http请求方法
    • 3.1 http常见请求方法
    • 3.2 postman工具进行请求
    • 3.3 处理GET和POST参数

1 知识回顾

前面两篇文章中我们学习并实现了http协议下的请求与应答:

  • http请求包括四个部分:请求行 , 报头 , 空行 , 请求正文。请求行中的URL是客户端想要获取的资源,这是对于服务器来说最重要的部分,服务器后续通过URL在网络根目录中搜索对应的资源,然后通过应答报文返回。
  • http应答包括四个部分:状态行 , 报头 , 空行 , 应答正文。应答正文中包含从服务器返回的实际内容,如HTML页面、图片或其他数据。
  • 请求与应答中的报头都是用于传输请求和应答的一些基础信息,以键值对的形式储存。

http协议作为通信协议,必然要支持序列化与反序列化。我们需要做的是服务器的操作,只需要进行请求的反序列化和应答的序列化就可以了,请求的序列化和应答的反序列化是浏览器(客户端)需要考虑的。要做到序列化和反序列化需要按照请求和应答的结构,从字符串中读取分离出来,具体操作可以参考之前的文章:

  1. 【计网】从零开始学习http协议 — http的请求与应答
  2. 【计网】从零开始学习http协议 — 通过http实现客户端交互

实现了http协议中服务器的序列化和反序列化,接下来就可以加入一些资源来供客户端获取。
对于状态行的http版本与http状态码,我们也有了初步的了解:

  1. http版本:浏览器和服务端需要互相告诉各自的版本号,进而做到对应的处理!因为http协议会不断更新,不能保证对方是否更新协议!
  2. http状态码:状态码是服务器做出应答时根据数据处理的情况返回给浏览器。每个状态码对应一种情况!

2 认识网络重定向

状态码中3XX是代表重定向的:

状态码含义
301Moved Permanently 永久重定向
302Found 临时重定向
307Temporary Redirect 临时重定向资源到新位置
308Permanent Redirect 永久重定向资源到新位置

其中大部分使用301 302,307 308很少使用!我们介绍一下临时重定向和永久重定向。

首先,网络中的重定向和文件的重定向概念上比较类似。一般来说,我们访问对应的网址会直接找到对应的服务器进程。当这个服务器让课客户端重新进行请求另一个服务器时,此时就是重定向!

举个例子:学校南门口有一家非常好吃的饺子馆,小明经常去那里吃饭。后来因为道路施工问题,饺子馆搬到看学校北门口,并为了让老客户可以找到新地址,在原来门店贴上新地址。小明这天去了,看到了这个告示,就知道应该去北门口找到这家饺子馆,这就是重定向!以后小明在想去饺子馆应该去老地址还是新地址呢?
这就需要分两种情况:

  1. 如果饺子馆是临时搬到北门口,那么小明一个去原南门口的饺子馆看看,再来决定是否去北门口。
  2. 如果饺子馆是永久搬到北门口,那么下面不用犹豫,直接就去北门口就可以!

这里的两种情况就是临时重定向和永久重定向的区别:临时重定向只修改一次,下次客户端依然访问原网址。永久重定向会永久修改,下次客户端直接访问新地址!

实际应用中,也有实际的例子:

甲公司使用www.hello.com网址使用了很多年,积攒了很多用户。后来甲公司将公司网址改成了www.world.com
那么下一次老用户访问原网址时,对老客户进行重定向访问到新网址,并修改老客户中浏览器中的对应网址信息。这就是永久重定向!

永久重定向是给搜索引擎看的!每个搜索引擎都会抓取全国各个网站的网址信息,然后建立起键值对。每次搜索时就可以通过关键词搜索到对应的网站。这个抓取是不断进行的。当一个网站的网址永久更改时,在原网址设置重定向到新网址,客户端每次进到原网址都要进行一次重定向,每次都进行重定向就太麻烦了!所以浏览器发现永久重定向之后就会修改内部信息,下次就会直接访问到新网址!
在这里插入图片描述
我们可以在服务器中测试一下重定向!
我们在页面中加入一个测试重定向的链接,这个链接会请求/redir资源,这个资源实际上并不存在,只是用来进行是否进行重定向的判断依据!
在这里插入图片描述

这样点入链接之后,就会再次发送请求/redir这个资源,我们可以在处理时进行一个硬处理,当客户端访问这个资源时进行一个特殊处理:

	if (hreq.Path() == "wwwroot/redir"){// 进行重定向LOG(DEBUG, "进行重定向!!!\n");std::string redir_path = "https://www.qq.com"; // 重定向的新地址resp.AddCode(302, _code_to_desc[302]);resp.AddHeader("Location", redir_path);// resp.AddBody(content);}else{//...}

这样进行序列化返回给浏览器之后,浏览器会自动识别,然后就跳转到新的网址中了!!!
在这里插入图片描述
非常好玩,这个现象就是重定向!!!

3 http请求方法

3.1 http常见请求方法

在http请求中有请求行,请求行中有一个参数:请求方法_method。这个请求方法到底是干什么用的呢?

http中有以下请求方法:

请求方法方法说明适配HTTP版本
GET请求指定的资源。一般用于信息查询,不应产生副作用。HTTP/1.0
POST向指定的资源提交数据进行处理请求(例如提交表单或上传文件)。HTTP/1.0
PUT向指定资源位置上传其最新内容。HTTP/1.0
DELETE请求服务器删除Request-URI所标识的资源。HTTP/1.0
HEAD类似于GET请求,但响应体不会返回,用于获取报头信息。HTTP/1.0
OPTIONS用于描述目标资源的通信选项。HTTP/1.1
TRACE回显服务器收到的请求,主要用于测试或诊断。HTTP/1.1
CONNECT用于将连接改为管道方式的代理服务器。HTTP/1.1
PATCH对资源进行部分修改。HTTP/1.1

其中最常见的就是GET方法和POST方法。 平时使用浏览器一般都是获取资源,就是进行GET。有时也会进行登录注册,这时会向服务器发送资源,就是进行POST!那么浏览器是如何进行呢?
我们可以在服务器中加入打印客户端请求方法,这样我们可以看到:
在这里插入图片描述
可以看到只要是获取资源都是使用的GET方法!

3.2 postman工具进行请求

那我们可以进行GET方法了,怎么进行POST方法呢?可以使用postman这个工具:

Postman提供了一个直观的界面来构建HTTP请求,包括设置请求头、请求体、认证等。
Postman允许用户发送各种HTTP请求(如GET, POST, PUT, DELETE等)到API端点,并检查响应。它支持测试脚本,可以自动验证响应数据。

我们通过postman快速创建http请求,使用POST方法发送。
在这里插入图片描述
这样服务器就得到了POST方法的请求。
在这里插入图片描述

GET方法不光可以获取数据,也可以向服务器发送数据。POST方法也可以向服务器推送数据!
我们可以在postman中加入两个键值对:
在这里插入图片描述
这样我们再次请求时,就会发现我们可以通过url向服务器进行传参了!
在这里插入图片描述

我们在使用POST方法试一试,POST方法需要再请求的正文中加入参数:
在这里插入图片描述
这样服务器会得到一个请求,这个请求正文中包含了传入的参数!
在这里插入图片描述
总结:

  • GET方法一般用来获取静态资源,也可以通过URL向服务器传递参数。
  • POST方法可以通过http请求的正文来进行参数的传递。
  • URL传参,参数的体量一定不大;正文传参,参数的体量可以很大!

3.3 处理GET和POST参数

但是在用户的实际使用中,用户不可能像POSTMAN一样可以手动选择请求方法,那么实际应用中,是通过前端的form表单完成GET和POST请求!

    <div><!-- 默认就是GET --><form action="/login" method="POST">用户名: <input type="text" name="username" value="."><br>密码: <input type="password" name="userpasswd" value=""><br><input type="submit" value="提交"></form></div>

这里最后使用POST方法,因为使用GET方法,会将参数加入到URL中,这样其他人可以就能够看到用户和密码了,这样可不行!
在这里插入图片描述
那么服务器如何处理参数呢?这个action="/login" 又是什么含义呢?

  • 当使用POST方法时,参数是写在正文中的,那么直接直接按照规则进行解析就可以了!
  • 如果使用GET方法,参数是加在URL中的。如果不做处理,会影响我们后续的很多操作,所以需要对URL进行处理!将真正的URL提取出来,并在正文中储存参数!
        // 解析参数 --- 忽略大小写进行比较if (strcasecmp(_method.c_str(), "GET") == 0){//寻找 ?auto pos = _url.find(arg_sep);//包含?说明带参数if(pos != std::string::npos) {_req_body_text = _url.substr(pos + arg_sep.size());_url.resize(pos);}}
    

这样不管是使用的什么方法传递的参数,我们都可以通过正文中获取参数了!

接下来我们来看action="/login",这个资源我们并不存在啊?这个action需要怎么处理呢?

我们在httpserver中加入一系列的服务名称与服务函数的哈希对应。

using func_t = std::function<HttpResponse(HttpRequest)>;std::unordered_map<std::string , func_t> server_list;void InsertService(const std::string servicename , func_t f){//加入网络根目录!std::string s = prefixpath + servicename;_server_list[s] = f;}

那么对于"/login"我们可以插入一个:

hserver.InsertService("/login" , login);

那么服务器可以在处理请求之后,进行特殊处理。识别出来action是"/login"时,就可以去执行func_t函数,然后可以返回对应的应答!

        if (hreq.Path() == "wwwroot/redir"){// 进行重定向LOG(DEBUG, "进行重定向!!!\n");//...}else if (!hreq.GetRequestBody().empty()){if (IsServiceExists(hreq.Path())){resp = _server_list[hreq.Path()](hreq);}}

这样就实现了对action的处理!!!所以http不光可以处理静态资源,也可以处理函数!

我们就可以设计一个处理login的方法:


HttpResponse Login(HttpRequest &req)
{HttpResponse resp;std::cout << "外部已经拿到了参数了: " << std::endl;req.GetRequestBody();std::cout << "####################### " << std::endl;resp.AddCode(200, "OK");resp.AddBody("<html><h1>result done!</h1></html>");// username=helloworld&userpasswd=123456//可以进行很多种的操作!// 1. pipe// 2. dup2// 3. fork();// 4. 其他进程执行 -> exec* -> python, PHP, 甚至是Java!return resp;
}

这样我们能处理不同的action了:
在这里插入图片描述
通过这种方式,我们可以通过回调函数func_t进行可以进行很多操作了:

  1. pipe创建管道
  2. dup2进行重定向
  3. fork创建子进程
  4. exec*系列进行进程替换

因为C++语言处理业务并不擅长,但是c++处理底层十分快速!所以我们可以通过管道或者新的进程将数据交给python或者java这样的web语言来处理,然后在将数据返回给服务器,服务器处理好之后将http应答交给客户端!
这样服务器中各种语言的关系我们也就大概了解了!!!

我们可以来看一个浏览器的实例:
在这里插入图片描述
其中的https://cn.bing.com/search?q=helloworld,我们可以大致了解其中的原理:

  1. /s应该就是search服务,告诉服务器去执行搜索服务,这个服务不确定是什么语言进行的!
  2. 参数q=helloworld,是使用GET方法传给服务器的!也就是我们要搜索的内容!

通过F12查看页面信息我们也能找到对应的form表单:
在这里插入图片描述
这里的action就是/search

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/54666.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Linux 命令 netstat 的 10 个基本用法

Netstat 简介 Netstat 是一款命令行工具&#xff0c;可用于列出系统上所有的网络套接字连接情况&#xff0c;包括 tcp, udp 以及 unix 套接字&#xff0c;另外它还能列出处于监听状态&#xff08;即等待接入请求&#xff09;的套接字。如果你想确认系统上的 Web 服务有没有起来…

行为设计模式 -观察者模式- JAVA

观察者模式 一.简介二. 案例2.1 抽象主题&#xff08;Subject&#xff09;2.2 具体主题&#xff08;Concrete Subject&#xff09;2.3 抽象观察者&#xff08;Observer&#xff09;2.4 具体观察者&#xff08;Concrete Observer&#xff09;2.5 测试 三. 结论3.1 优缺点3.2 使用…

STM32外设详解——ADC

来源&#xff1a;铁头山羊 基本概念 ①ADC是模数转换器的统称&#xff0c;stm32f103c8t6内部集成了2个12位主次逼近型ADC&#xff0c;外设名称为ADC1、ADC2。 ② 采样深度为12位意味着ADC可以将0~3.3V的模拟电压等比转换为0~4095的数字值&#xff08;分割为2的12次方份&…

网 络 安 全

网络安全是指保护网络系统及其所存储或传输的数据免遭未经授权访问、使用、揭露、破坏、修改或破坏的实践和技术措施。网络安全涉及多个方面&#xff0c;包括但不限于以下几个方面&#xff1a; 1. 数据保护&#xff1a;确保数据在传输和存储过程中的完整性和保密性&#xff0c;…

银河麒麟V10安装ToDesk远程控制

银河麒麟V10安装ToDesk远程控制 ARM版本安装 1.下载arm的deb包 wget https://dl.todesk.com/linux/todesk_4.0.3_aarch64.deb2.安装 sudo apt-get install ./todesk_4.0.3_aarch64.deb3.启动todesk todesk

文献翻译用什么软件?新手建议收藏这5个

在学术研究的广阔天地里&#xff0c;语言障碍往往是科研人员不得不跨越的一道难关。 面对海量的外文文献&#xff0c;如何高效、准确地获取其中的信息&#xff0c;成为了许多学者关注的焦点。 想知道文献翻译器推荐哪一个&#xff1f;今天这篇文章为大家推荐5个优秀的文献翻译…

如何制作低代码开发的视频教程?

如何制作低代码开发的视频教程&#xff1f; 随着数字化转型的加速&#xff0c;越来越多的企业和组织开始采用低代码开发平台来加速应用程序的构建。对于许多开发者和业务人员来说&#xff0c;学习如何使用这些平台可以显著提高工作效率。因此&#xff0c;创建一份清晰、实用且…

02_InFluxDb

InFluxDb 初始化初始化流程 交互InFluxDbWebUI交互 数据模型行协议添加标签数据格式 数据类型空格索引 Flux语言 初始化 初始化流程 用户 密码 组织名称 Bucket—mysql里面的数据库概念 交互InFluxDb 暂用了8086端口.提供了 http api WebUI交互 略... 数据模型 这是mys…

无源有损耗导电介质的平面电磁波——复数介电常数带来复波数k(导致幅度衰减)和复波阻抗(带来磁场电场相位不同)

推导中以εμσ是实数为假设 注意在线性介质中J 0和σ等于0其实是一个条件&#xff0c;因为J σE 线性介质的麦克斯韦方程 线性介质无源无损耗条件下 线性介质无源有损耗导电介质下 无源有损耗的复数麦克斯韦方程组&#xff0c;只有方程二与无源无损耗的麦克斯韦方程组不同…

双十一选购攻略:2024年双十一有什么值得入手好物?

又到一年双11&#xff0c;还有很多持币观望的小伙伴&#xff0c;可能还没想要买什么&#xff0c;所以我就来啦&#xff0c;给大家参谋参谋&#xff0c;结合我生活中的好物使用经验&#xff0c;来跟大家做个分享&#xff0c;如果能给已经进入双11“买买买”节奏的你一些参考&…

java.lang.NoClassDefFoundError: kotlin/Result解决方案

问题 在控制窗口上虽然报错是找不到对应的class&#xff0c;但是呢在我们导入kotlin的后&#xff0c;还是报相同的异常&#xff0c;在网上查找了各种资料&#xff0c;都没有解决方案。 问题分析 在idea2021之后&#xff0c;kotlin都使用远程仓库&#xff08;kotlinx-coeouti…

C语言 动态数据结构的C语言实现内存映像

C程序的内存映像 C程序中变量的内存分配方式  C程序中变量的内存分配方式  从静态存储区分配  全局变量和静态变量 C程序中变量的内存分配方式  从静态存储区分配  全局变量和静态变量  在栈上分配  存放函数参数值&#xff0c;局部变量值等  …

1.1 flexsim基础入门

连线和端口 A&#xff1a;连接 S&#xff1a;中间端口连接 &#xff08;经常用于货物搬运的时候&#xff0c;中间端口连接属于无方向连接&#xff09; 假设有一个任务分配器&#xff0c;用来分配任务。暂存区与任务分配器连接&#xff0c;说明通过任务分配器作为中间商下达任务…

【重学 MySQL】五十、添加数据

【重学 MySQL】五十、添加数据 使用INSERT INTO语句添加数据基本语法示例插入多行数据注意事项 使用LOAD DATA INFILE语句批量添加数据其他插入数据的方式注意事项 在MySQL中&#xff0c;添加数据是数据库操作中的基本操作之一。 使用INSERT INTO语句添加数据 使用 INSERT IN…

GPT系列

GPT&#xff08;Generative Pre-Training&#xff09;&#xff1a; 训练过程分两步&#xff1a;无监督预训练有监督微调 模型结构是decoder-only的12层transformer 1、预训练过程&#xff0c;窗口为k&#xff0c;根据前k-1个token预测第k个token&#xff0c;训练样本包括700…

配置静态ip

背景:因业务需要需要将一台服务器从机房搬到实验室,机房是光纤,实验室是网线,需要重新配置下静态ip 确认网络配置文件(网上没找到,不清楚一下方法对不对) 先随便一个网口连接网线,执行 ifconfig -a 找到带“RUNNING”的(lo不是哈)----eno1 到/etc/sysconfig/network…

ansible 剧本模式

目录 1.剧本格式 ​编辑​编辑2.案例1创建目录分发文件剧本 2.1剧本中用到的命令 2.2书写具体剧本 3.案例2 分发 安装软件包 启动服务的剧本 3.1下载软件包 3.2用yum安装 3.3启动服务 4.找出ansible中对应的模块 5.剧本实现 4.ansible 剧本变量 4.1常用的…

YOLO11涨点优化:注意力魔改 | 轻量级自注意力机制CoordAttention | CVPR2021

💡💡💡本文改进内容:CoordAttention优势,不仅会考虑输入的特征信息,还会考虑每个像素点的位置信息,从而更好地捕捉空间上的局部关系和全局关系。 💡💡💡本文改进:分别加入到YOLO11的backbone、neck、detect,助力涨点 改进1结构图: 改进2结构图: 改进3结构

【HTTPS】深入解析 https

我的主页&#xff1a;2的n次方_ 1. 背景介绍 在使用 http 协议的时候是不安全的&#xff0c;可能会出现运营商劫持等安全问题&#xff0c;运营商通过劫持 http 流量&#xff0c;篡改返回的网页内容&#xff0c;例如广告业务&#xff0c;可能会通过 Referer 字段 来统计是…

【Java】—— 泛型:泛型的理解及其在集合(List,Set)、比较器(Comparator)中的使用

目录 1. 泛型概述 1.1 生活中的例子 1.2 泛型的引入 2. 使用泛型举例 2.1 集合中使用泛型 2.1.1 举例 2.1.2 练习 2.2 比较器中使用泛型 2.2.1 举例 2.2.2 练习 1. 泛型概述 1.1 生活中的例子 举例1&#xff1a;中药店&#xff0c;每个抽屉外面贴着标签 举例2&…