ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

【LINUX网络】HTTP服务器搭建完善+报头属性状态码

【LINUX网络】HTTP服务器搭建完善+报头属性状态码 【LINUX网络】HTTP协议基本结构、搭建自己的HTTP简单服务器-CSDN博客本文是基于自己用C原生接口搭建的HTTP服务器进行的进一步学习建议读者先看前文。下面基于HTTP协议的原理理解几个概念1. 代理服务器在之前的概念中所有的数据、功能都集成于自己的http服务器上但其实真正的情景远不止如此。如上图所示大量的数据可能存在于若干个存储数据的“红色服务器”我们的服务器更大意义上是一种代理服务器在客户端访问我们的服务器时可能代理服务器会采用轮询等测率依次把获得数据访问数据库的任务交给“红色服务器”减轻自己的任务量提升整体效率。同时http代理服务器转发时还要兼顾负载均衡的任务主要功能还包括如缓存、匿名浏览、安全过滤、访问控制和负载均衡以及在企业网络、数据采集、跨国访问等方面的使用场景。有想深入了解的读者深入解析HTTP代理服务器原理、功能与配置-CSDN博客内网的转发与负载均衡与操作系统中的文件系统部分也非常相似总之计算机想要提高效率都是靠封装一层缓存拉解决问题。2. HTTP的报头属性以上一文中我们实现的小小服务器为例子可以解析出来浏览器发给了header中的内容。其实真正的header中不止这部分请求报头只是因为当前的网页请求很简单所以对应的KV对也比较少。HTTP报头主要分为请求报头和响应报头两种类型。由于这两种报头的属性结构完全相同我们将首先以HTTP请求报头为例进行详细讲解然后再通过HTTP响应报头来具体演示如何设置报头参数。上一文中的Content-Type和Content-Length的设置其实就是在做这件事。请读者注意实现demo的时候名字一定要写一样的不要写成Content_type或content_size等错误一样的字段才能让HttpResponse的value值被成功设置。常见的报头Host: 81.70.12.246:8080 Connection: keep-alive User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/139.0.0.0 Safari/537.36 Edg/139.0.0.0 Accept: image/avif,image/webp,image/apng,image/svgxml,image/*,*/*;q0.8 Referer: http://81.70.12.246:8080/ Accept-Encoding: gzip, deflate Accept-Language: zh-CN,zh;q0.9,en;q0.8,en-GB;q0.7,en-US;q0.6HOST指定服务器的主机名和端口号浏览器客户端通过这个报头告诉服务器它想访问的机器位置Connection: keep-alive- 表示客户端希望与服务器保持连接以便在同一连接上发送多个请求。还有个选项是close表示请求/响应完成后应立即关闭TCP连接。User-Agent : 表示客户端的用户代理字符串包含了浏览器和操作系统的信息Accept: 表示客户端可以接受的 MIME类型Accept-Encoding: gzip, deflate, br, zstd - 表示客户端可以接受的内容编码。这里表示客户端可以接受gzip、deflate、br和zstd编码的内容Accept-Language: en,zh-CN;q0.9,zh;q0.8,en-US;q0.7 - 表示客户端可以接受的语言。这里表示客户端可以接受英语en、简体中文zh-CN、中文zh和美式英语en-USreferer:当前页面是从哪个页面跳转过来的;再比如我现在从login界面跳转到rigister界面这个字段可能在以下情景中使用的比较多自动跳转/自动弹框/想访问a不小心访问到B对最重要的几个进行分类### HTTP报头属性说明与分类- **Host**客户端通过此字段告知服务器所请求的资源位于哪个主机的哪个端口上。它是HTTP/1.1规范中唯一必须包含在请求中的字段用于指定服务器的主机名和端口号。- **User-Agent**此字段声明用户的操作系统和浏览器版本信息仅出现在请求中用于向服务器表明客户端应用程序的相关信息。- **Referer**当用户从一个页面跳转到当前页面时此字段会记录跳转来源页面的URL仅出现在请求中。- **Location**此字段搭配3xx状态码使用后文介绍用于告知客户端接下来应访问的资源位置仅出现在响应中。- **Content-Type**此字段表示数据的媒体类型既可能出现在请求报头中也可能出现在响应报头中。- **Content-Length**此字段表示实体主体的大小既可能出现在请求报头中也可能出现在响应报头中。- **Cookie**用于在客户端存储少量信息通常用于实现会话session功能。客户端会通过此字段发送之前服务器存储的Cookie信息仅出现在请求中。关于Cookie和Session的详细内容将在后续章节中讲解。- **Set-Cookie**此字段用于服务器指示客户端保存Cookie仅出现在响应中需要与客户端的Cookie配合使用具体介绍将在后续Cookie章节中展开。### 常见报头属性分类- **只出现在请求报头中**- **Host**HTTP/1.1规范中唯一必须包含在请求中的字段用于指定服务器的主机名和端口号。- **User-Agent**表示客户端应用程序的信息仅出现在请求中。- **Referer**表示用户从哪个页面链接过来的仅出现在请求中。- **Cookie**客户端发送之前服务器存储的Cookie信息仅出现在请求中。- **只出现在响应报头中**- **Location**主要配合3xx重定向状态码使用仅出现在响应中。- **Set-Cookie**用于服务器指示客户端保存Cookie仅出现在响应中需搭配客户端的Cookie使用具体介绍见后续Cookie章节。- **可能同时出现在请求或响应报头中**- **Content-Type**表示实体的媒体类型既可能出现在请求报头中也可能出现在响应报头中。- **Content-Length**表示实体主体的大小既可能出现在请求报头中也可能出现在响应报头中。3. HTTP状态码_status_code状态码分成五个类型分别对应不同的数字开头100 Continue: 客户端发送了一个带有Expect: 100-continue头部的请求服务器响应此状态码发送表示客户端可以继续发送请求体比如上传大文件时不可能一次性传完可能会分多次请求。200 OK请求成功服务器返回了请求的数据。4XX 都称之为Client Error比如客户端进行了非法请求404 Not Found服务器无法找到请求的资源5XX Server Error服务器错误状态码表示当前的服务器有错状态码含义应用场景100Continue上传大文件时服务器通知客户端继续上传200OK访问网站首页时服务器返回网页内容201Created发布新文章后服务器返回创建成功信息204No Content删除文章后服务器返回无内容表示操作成功301Moved Permanently网站更换域名时自动跳转搜索引擎更新链接时使用302Found/See Other用户登录成功后重定向到个人主页304Not Modified浏览器缓存未修改资源时返回400Bad Request表单提交格式错误导致请求失败401Unauthorized访问需登录页面时未认证或认证失败403Forbidden尝试访问无权限查看的页面404Not Found访问不存在的网页链接500Internal Server Error服务器崩溃或数据库错误导致页面加载失败502Bad Gateway代理服务器无法从上游服务器获取有效响应503Service Unavailable服务器维护或过载时暂时无法处理请求在讲3xx对应的重定向之前给读者记录点小背景浏览器——HTTP中的客户端拥有流量入口的服务器叫搜索引擎这就是感觉小时候都是百度一家独大的原因浏览器在商业价值上是仅次于操作系统的浏览器可以内置很多内容所以会有很多公司开发了浏览器每个浏览器都可能有细微的差异导致前端工程师需要考虑每一种浏览器是否兼容所以在大量的浏览器中对于返回码的应答不一定百分百关心因为每一种服务器的返回可能不会完全一样但是一定大差不差所以不用特别纠结于一种浏览器的返回的状态码Location重定向其中了解价值最大的莫过于302和301 无论是 301 还是 302浏览器在接收到响应后都会自动跳转无需用户点击。这个跳转行为由 HTTP 响应头中的Location字段驱动。状态码含义是否为临时重定向应用场景301Moved Permanently否永久重定向网站更换域名时自动跳转搜索引擎更新网站链接时使用302Found / See Other是临时重定向用户登录成功后重定向到个人首页HTTP 状态码 301永久重定向和 302临时重定向都需要使用 Location 头部字段。以下是具体说明HTTP 状态码 301永久重定向表示请求的资源已永久迁移至新位置服务器会在响应中包含 Location 头部指明资源的新 URL浏览器会自动重定向到该地址并缓存此重定向浏览器在首次收到 301 响应后会将这个跳转关系缓存起来。下次你再访问旧地址时浏览器会直接跳转到新地址甚至不再向服务器发起请求。示例响应头HTTP/1.1 301 Moved Permanently Location: https://www.new-url.comHTTP 状态码 302临时重定向表示请求的资源临时迁移至新位置服务器同样会返回 Location 头部指明新 URL浏览器会临时使用新地址但不会缓存该重定向表示资源只是暂时被移动到新地址。浏览器收到 302 后虽然也会立即跳转但不会缓存这个跳转关系。下次访问旧地址时浏览器仍会先向服务器发起请求服务器再返回 302 和新地址。示例响应头HTTP/1.1 302 Found Location: https://www.new-url.com临时重定向和永久重定向的区别就好像一家店铺是“道路维修暂时搬迁至xxx”和“门店已搬迁至xxx”临时先去原地址再去新地址。永久直接去新地址。测试如下确实成功重定向了只不过未能成功打开因为服务器可能出于自身安全考虑不允许这样不停的重定向。因为当前的代码是硬编码一次重定向失败无论如何都会返回302然后就会一直死循环。简易理解重定向的过程发现_status_code是302就会自动发起二次请求即重定向走到重定向的地址去而对于301更多的应用场景是搜索引擎SEO首先是最简单最简单的爬虫原理网络爬虫通过解析HTML中的a标签提取链接从而发现并抓取新的网页。这个过程是递归进行的从初始页面出发不断提取新链接并访问逐步扩展抓取范围。另外对于搜索引擎来说需要不停的去爬各个网站以获取信息但是网站成千上万也会出现变更域名的情况。此时就能体现301重定向的作用当网站变更域名或URL时搜索引擎通过301永久重定向机制来更新索引。这种重定向主要服务于搜索引擎持续的更新SEO的缓存确保它们能够追踪到网站的最新地址。所以301主要是给搜索引擎做的。搜索引擎会定期进行爬取和索引更新以保持信息的时效性。大多数网站都欢迎搜索引擎爬取因为这会提高网站在搜索结果中的可见度。其实还有很多其他的重定向在此记录如下“临时重定向”302 Found - 最常用的临时重定向状态码303 See Other - 特别用于将POST请求重定向到GET请求307 Temporary Redirect - 临时重定向但严格保持原始请求方法不变“永久重定向”301 Moved Permanently - 资源已永久移动到新位置308 Permanent Redirect - 永久重定向但严格保持原始请求方法不变“其他重定向”300 Multiple Choices - 表示请求有多个可能的响应304 Not Modified - 缓存重定向表示资源未修改4. HTTP的请求方法首先理解一下什么是表单HTML 表单 | 菜鸟教程对于一个HTTP的请求Request排在第一位的数据就是http方法是用于指定客户端希望对资源执行的操作类型。这些方法定义了HTTP请求的行为是HTTP协议的核心组成部分。稍微常见一点的四种GET请求指定的资源。GET方法应该只用于获取数据并且不会对服务器上的数据产生任何影响。POST向指定的资源提交要被处理的数据通常用于表单提交或者上传文件。数据被包含在请求的主体中。PUT将请求主体中的实体数据更新到指定的资源如果该资源不存在则创建新资源。DELETE删除指定的资源其实一共有9-10种方法但是最常用的只有GET和POST方法会被暴露出来90%的网站只暴露出来GET和POST为了安全比如PUT方法大部分网站不允许客户端无限制的上传。如果恶意客户端不停的传传满了服务器就崩了。DELETE方法直接让客户端删文件直接删库跑路服务器不全完蛋了OPTION方法让客户端可以看清楚漏洞有了以上理解之后再来理解什么是动态资源、静态资源动态资源与静态资源在上面以及之前两节中服务器都是向客户端直接响应字符串或者一个静态资源图片网页视频音频、js、css但是有的时候不只有静态资源还有很多的动态资源例如在表单提交时form标签内的action字段的值数据提供的URL就是对应的一个动态资源表单提供的就是一种交互式的资源比如需要你输入账号密码等等......正如上文所说表单中的input就是干这个工作的。input会被浏览器解释成一个个的输入框。自动把action后面的内容放到ipport的后面形成的表单form就会发送给上面的地址此时的提交方法是method post所以对于动态资源的理解其实不是浅层的传统中文意义上的“资源”动态资源可以是一个接口、几种方法URI传过来不一定必须要返回一个具体的文件URI也可能是希望我的服务器调用几个接口比如表单提交的过程种URL请求的其实是服务器对这个数据进行处理的方法希望后端去处理这个数据而不是提供数据。之前有了解URL和URI区别的朋友也应该有了解过URL是一个资源定位器但是大部分时候我们更喜欢称之为URI就是因为不是每一次都要去定义一个资源有的时候一个identify更能满足广义的描述。静态资源和动态资源的利用密不可分联系紧密比如进行一个登录就是先返回了界面的html这个静态资源通过前端输入账号密码之后再用带问号的http请求去执行这个对应的接口进一步学习GET和POST方法一句话来说GET就是把远端的资源拿下来 POST就是把参数上传。但其实GET也可以用于上传参数下面通过实验来观察先把之前的网页的登录界面的一个表单的提交方法改成GET请仔细观察这次的URIGET 后面的参数就是我们在登录界面输入的内容直接在?后作为参数被传递了并且HttpRequest的body是空的发现GET的第一个特点参数直接在URI种传递。再看看POST同样的由客户端发动登录参数不再出现在URI中而是通过body传输。GET和POST的区别GET参数通过URL传递POST通过请求体传递GET参数附加在URL后面以键值对的形式出现多个参数之间用连接。例如http://example.com?nameKimiage30。POST参数包含在请求体中对URL不可见。这使得POST可以发送大量数据并且可以包含非ASCII字符。GET请求有长度限制POST没有严格限制GET由于参数通过URL传递受到URL长度限制通常由浏览器和服务器决定但一般不超过2KB。这意味着GET请求能发送的数据量有限。POST参数通过请求体传递理论上没有长度限制取决于服务器配置和网络环境。这使得POST可以发送大量数据如文件上传。GET请求可被缓存POST通常不缓存GET由于GET请求的结果通常不依赖于用户状态因此可以被缓存以提高性能和减少服务器负载。浏览器和代理服务器可能会缓存GET请求的结果。POST由于POST请求通常用于修改服务器状态如表单提交因此结果依赖于用户状态通常不会被缓存。这确保了每次POST请求都能得到最新的结果。GET相对不安全POST相对更私密GET由于参数通过URL传递可能会在浏览器历史记录、服务器日志中留下敏感信息如用户名、密码等。此外GET请求可以被书签化这意味着敏感操作可以被意外地重复执行。POST由于参数通过请求体传递不会在URL中暴露敏感信息相对更安全。然而POST请求的数据仍然可能被拦截如通过中间人攻击因此仍然需要使用HTTPS等加密措施来保护数据安全。GET具有幂等性POST通常非幂等GET幂等性意味着多次执行相同的GET请求结果总是相同的不会改变服务器状态。例如多次获取同一资源服务器状态不会改变。POST非幂等性意味着多次执行相同的POST请求可能会多次修改服务器状态。例如多次提交表单可能会导致多次创建相同的记录。这使得POST请求的结果可能因执行次数而异。在参数传递功能方面GET方法确实不如POST完善。POST通过请求体传输数据不仅支持更长的文本内容而且安全性更高能避免将敏感信息直接暴露在URL中。不过需要说明的是POST只是相对更私密。由于当前数据传输都是明文的对于现代网络来说使用抓包工具依然可以完整获取请求内容包括请求体中的数据。故单纯使用POST和GET都是不安全的几乎都等于暴露给别人看。内容回顾之前的百度的URL里有一个/s后面才接的是各种参数由此可以推出表单上的action写的就是s会把action后面的内容自动放到ipport处去之前的代码中永远都是提供静态资源今天要改写代码让代码拥有操作动态资源的能力5. DEMO CODE-----------------------记录完成demo代码中的过程与遇到的困难处理动态资源及其请求post方法body不为空get方法的URL带有说明都是需要交互式设置的如果只是请求一般的静态资源就是原来的步骤。有参数就去交互式设计无参数就走Build的老路请求静态资源构建好之后直接准备Serialize现在的问题是当有参数需要请动态资源时不同的请求一般对应着不一样的动态资源。1、需要使用一个容器如哈希表来把对应的请求和动态资源对应起来此时的动态资源默认就是方法接口2、由1得请求要和动态资源对应起来那么相对来说一定是POST方法更简单因为POST方法的URI更简单明了更适合直接提取出来作为参数最后就希望我们的调用方式可以是这里就涉及到了一种RESTful风格的网络接口设计的概念每个路由都与一个处理函数如Login、Register、Search、Test关联这些函数定义了当特定路由被请求时应该执行的操作。这种设计符合RESTful接口的原则因为它提供了一种统一的方式来访问和操作资源并且每个请求都包含了执行操作所需的所有信息。这样到时候发起访问的URI其实就是wwwroot/login或者wwwroot/Register简洁明了。现在的Build是一种请求静态资源并且构造返回的Response的办法我们只不过是要多实现点请求动态资源的版本所以对于需要参数的交互式方法来说现在需要想办法去获得参数我们设计成一个unordered_map用函数名和解析后的uri依次对应。using handler_argus_req std::functionvoid(HttpRequest req, HttpResponse *rep);这个函数的目的就是去构建一个response和build同级、同层次所以还需要一个注册方法能把函数和URI都注册进入map//动态资源的服务对照表 std::unordered_mapstd::string,handler_argus_req _route;//功能路由void Register(std::string funcname,handler_argus_req func) { _route.insert(std::make_pair(funcname,func)); }一点代码细节Url接口返回的是一个加入了wwwroot的接口而现在我们只需要从解析上解析下来的那个“方法名字”也就是说_url是wwwroot/login_Method_Url是/loginHasArgus的初步实现再引入两个新变量_path和_argus因为在GET方法下_url已经不再简单是个路径还带有参数。调用码间休息 tips什么是favicon.ico读者在自己尝试demo或者访问网站的时候网站的左上角通常都有一个图标。请求看到favicon.ico的时候表示浏览器正在请求这个小图标只不过暂时还没有找到可以进行应答的资源。测试POST方法GET方法刚刚一直在做的就是把整个URI给出的请求解析出来要调的函数、然后去调用。现在就可以构建对应的Response否则一直send回去的都是空的处理返回的HttpResponse鉴于现在的Build函数现在更名为StaticBuild不具备构造交互式Response的能力所以需要我们自己去实现。void DynamicBuild(HttpRequest req) { // body的build已经在上层完成了 if (_content.empty()) { _status_code 302; SetKV(Location, /wating.html); } else { _status_code 200; SetKV(Content-Length, std::to_string(_content.size())); SetKV(Content-Type, Suffix2Desc(req.Suffix())); } _status_desc Code2Desc(_status_code); for (auto e : _header_KV) { _res_head.push_back(e.first Header_sep e.second); } }这里简单玩了一下加入了一个注册功能如果请求了这个动态资源就返回一个还在建设中的页面使用重定向完成事实是登录成功之后很多情况不会专门返回一个“登陆成功”而是直接使用302跳转到对应的页面或者用前端代码完成这个功能。再次理解什么是百度中的/ss就是一个被百度工程师注册进来的名字就像我们的register和login浏览器把搜索框表单中的参数采用GET方法直接在URL中带参传递解析出来/s和?后面的内容找到/s对应的方法就可以去执行对应的搜索逻辑了。6. 整体文件搭建的简单电商城http服务器 · 6771069 · lsnmjp/code of cpp Linux 算法 - Gitee.com更新_Method_Url的解析应该对POST和GET都有效如下原代码存在POST请求总是404的问题。不过要注意这个demo代码我们没有做完整性的检查有时候请求失败是正常的。另外这个地方也需要调整没有三种情况只有两种情况。原来的第三种情况是给完整性检测用的。
返回列表