【Linux網絡】Http服務優化 - 增加請求后綴、狀態碼描述、重定向、自動跳轉及注冊多功能服務

📢博客主頁:https://blog.csdn.net/2301_779549673
📢博客倉庫:https://gitee.com/JohnKingW/linux_test/tree/master/lesson
📢歡迎點贊 👍 收藏 ?留言 📝 如有錯誤敬請指正!
📢本文由 JohnKi 原創,首發于 CSDN🙉
📢未來很長,值得我們全力奔赴更美好的生活?

在這里插入圖片描述

在這里插入圖片描述

文章目錄

  • 🏳??🌈一、增加請求后綴
    • 1.1 HttpRequest 類
    • 1.2 HttpHandler 類
  • 🏳??🌈二、狀態碼描述 及 自動跳轉404
    • 2.1 狀態碼描述
    • 2.2 自動跳轉404
  • 🏳??🌈三、重定向狀態碼
  • 🏳??🌈四、注冊等多功能服務
    • 4.1 HttpRequest 類
    • 4.2 HttpHandler 類
    • 4.3 TcpServer.cpp
    • 4.4 測試
  • 👥總結


🏳??🌈一、增加請求后綴

我們在瀏覽器上訪問我們自己的服務端時,會遇到客戶端發送來的請求,想要訪問 1.jpg 或者 default.html 因此我們可以將這個后綴給整理一下,通過日志打印告訴我們自己目標想要訪問的資源在當前的哪里。

1.1 HttpRequest 類

我們在這個類里進行如下操作

  1. 添加成員變量 _suffix
  2. 在請求行解析方法中,增添一段,通過后綴分隔符 "." ,來找到我們的后綴,沒有找到就返回默認后綴
  3. 添加函數方法,獲取當前請求的后綴名
const static std::string _suffixsep = ".";                      // 后綴分隔符    class HttpRequest {
private:// 解析請求行void PraseReqLine() {// 以空格為分隔符,不斷讀取std::stringstream ss(_req_line);ss >> _method >> _url >> _version;_path += _url;// 處理url,如果是根目錄,則返回默認路徑if (_url == "/")_path += _default_path;// 獲取后綴auto pos = _path.rfind(_suffixsep);if (pos == std::string::npos)_suffix = ".default";else_suffix = _path.substr(pos);}public:std::string Suffix() {LOG(LogLevel::INFO) << "client want suffix : " << _suffix;return _suffix;}
}

1.2 HttpHandler 類

這里我們需要先知道一個概念 - MIMIE

MIME 是一種 ?互聯網標準,最初設計用于擴展電子郵件協議(如 SMTP),使其能傳輸非文本數據(如圖片、音頻)。后被 HTTP 協議廣泛采用,用于標識網絡資源的 ?數據類型。

  • .html → text/html(HTML 文檔)
  • .jpg → image/jpeg(JPEG 圖片)
  • .json → application/json(JSON 數據)

這個類中我們需要增加一個后綴映射,并將其添加在返回報文的報頭列表中

1, 增加成員變量 后綴后綴存儲 的映射
2.`構造函數 時,初始化映射
3. 處理請求時,將映射結果添加到響應報頭中

class HttpHandler {
public:HttpHandler() {_mime_type.insert(std::make_pair(".html", "text/html"));_mime_type.insert(std::make_pair(".jpg", "image/jpg"));_mime_type.insert(std::make_pair(".png", "image/png"));_mime_type.insert(std::make_pair(".default", "text/html"));}std::string HandleRequest(std::string req) {std::cout << "------------------------------------" << std::endl;std::cout << req;HttpRequest req_obj;req_obj.Descrialize(req);std::string content = GetFileContent(req_obj.Path());if (content.empty())return std::string();HttpResponse rsp;rsp.AddCode(200);rsp.AddHeader("Content-Length", std::to_string(content.size()));rsp.AddHeader("Content-type", _mime_type[req_obj.Suffix()]);rsp.AddBodyText(content);return rsp.Serialize();}
private:std::unordered_map<std::string, std::string> _mime_type;
};

🏳??🌈二、狀態碼描述 及 自動跳轉404

前面的文章中我們已經知道了狀態碼描述的存在,但是沒有可利用過,這里再介紹一下這個狀態碼,添加一個狀態碼的映射并且根據訪問內容,去判斷要不要顯示404界面

2.1 狀態碼描述

這里需要進行兩方面的更改,一個是 HttpResponse一個是 HttpHandler 的構造和成員變量

HttpHandler 中我們添加 狀態碼狀態碼描述映射,然后在構造中表示出來

class HttpHandler {
public:HttpHandler() {_mime_type.insert(std::make_pair(".html", "text/html")); // HTML 類型_mime_type.insert(std::make_pair(".jpg", "image/jpeg")); // JPEG 圖片_mime_type.insert(std::make_pair(".png", "image/png"));  // PNG 圖片_mime_type.insert(std::make_pair(".default", "text/html")); // 默認文本類型_status_code_desc.insert(std::make_pair(100, "Continue"));_status_code_desc.insert(std::make_pair(200, "OK"));_status_code_desc.insert(std::make_pair(201, "Created"));_status_code_desc.insert(std::make_pair(404, "Not Found"));}
private:std::unordered_map<int, std::string> _status_code_desc;
};

HttpResponse 中的 AddCode 方法,我們之前默認是不論什么都是 OK,現在我們對其進行專屬化處理

// 添加 狀態碼 和 狀態碼描述
void AddCode(int code, std::string desc) {_status_code = code;_desc = desc;
}

2.2 自動跳轉404

我們在 HttpHandlerHandleRequest 方法中,當判定訪問的路徑內容為空時,就將這個路徑改成 404.html

std::string HandleRequest(std::string req) {std::cout << "------------------------------------" << std::endl;std::cout << req;HttpRequest req_obj;req_obj.Descrialize(req);std::string content = GetFileContent(req_obj.Path());HttpResponse rsp;if (content.empty()) {content = GetFileContent("wwwroot/404.html");rsp.AddCode(404, _status_code_desc[404]);rsp.AddHeader("Content-Length", std::to_string(content.size()));rsp.AddHeader("Content-type", _mime_type[".default"]);rsp.AddBodyText(content);} else {rsp.AddCode(200, _status_code_desc[200]);rsp.AddHeader("Content-Length", std::to_string(content.size()));rsp.AddHeader("Content-type", _mime_type[req_obj.Suffix()]);rsp.AddBodyText(content);}return rsp.Serialize();
}

🏳??🌈三、重定向狀態碼

在這里插入圖片描述

HTTP 狀態碼 301(永久重定向)和 302(臨時重定向)都依賴 Location 選項。

無論是 HTTP 301 還是 HTTP 302 重定向,都需要依賴 Location 選項來指定資源的新位置。這個 Location 選項是一個標準的 HTTP 響應頭部,用于告訴瀏覽器應該將請求重定向到哪個新的 URL 地址。

我們現在 default.html 中添加 測試重定向 的選項

在這里插入圖片描述

我們測試永久重定向,將當前的網址重定向到 qq.com

std::string HandleRequest(std::string req) {std::cout << "------------------------------------" << std::endl;std::cout << req;HttpRequest req_obj;req_obj.Descrialize(req);HttpResponse rsp;if (req_obj.Url() == "/redirect") {// 重定向處理std::string redirect_path = "https://www.qq.com";rsp.AddCode(302, _status_code_desc[302]);rsp.AddHeader("Location", redirect_path);rsp.AddHeader("Content-Type", "text/plain"); // 添加 Content-Typersp.AddHeader("Content-Length", "0");        // 顯式設置內容長度為 0rsp.AddBodyText("");                         // 確保響應體為空} else {std::string content = GetFileContent(req_obj.Path());if (content.empty()) {content = GetFileContent("wwwroot/404.html");rsp.AddCode(404, _status_code_desc[404]);rsp.AddHeader("Content-Length", std::to_string(content.size()));rsp.AddHeader("Content-type", _mime_type[".default"]);rsp.AddBodyText(content);} else {rsp.AddCode(200, _status_code_desc[200]);rsp.AddHeader("Content-Length", std::to_string(content.size()));rsp.AddHeader("Content-type", _mime_type[req_obj.Suffix()]);rsp.AddBodyText(content);}}return rsp.Serialize();
}

在這里插入圖片描述

🏳??🌈四、注冊等多功能服務

因為存在兩種主要的提交方式,分別是 POSTGET,因此參數的位置會不一樣,

GET 下,位于 網址 的 后面

在這里插入圖片描述

POST 下,位于請求正文中

所以我們要根據不同的情況,分出響應的 參數,以及路徑

4.1 HttpRequest 類

需要改的主要有三部分

  1. 增加新的成員變量_args 用來記錄參數,_isexcute 用來記錄是否有參數
  2. 構造函數中給 _isexcute 默認為false
  3. 更改 Descrialize 細節,使其區分 GETPOST,并且能夠準確提取出 _args_path
class HttpRequest{private:public:HttpRequest() : _blank_line(_base_sep), _path(_prefix_path), _isexcute(false) {}void Descrialize(std::string& reqstr){// 基本的反序列化_req_line = GetLine(reqstr);    // 讀取第一行請求行// 請求報頭std::string header;do{header = GetLine(reqstr);// 如果既不是空,也不是空行,就是請求報頭,加入到請求報頭列表中if(header.empty()) break;else if(header == _base_sep) break;_req_headers.push_back(header);}while(true);// 正文if(!reqstr.empty())_req_body = reqstr;// 進一步反序列化請求行PraseReqLine();// 分割請求報頭,獲取鍵值對PraseHeader(); // 判斷是否需要動態執行if(_method == "POST"){_isexcute = true;_args = _req_body;LOG(LogLevel::INFO) << "POST _path : " << _path;LOG(LogLevel::INFO) << "POST _args : " << _args;} else if(_method == "GET"){auto pos = _path.find("?");if(pos != std::string::npos){_isexcute = true;_args = _path.substr(pos + 1);_path = _path.substr(0, pos);LOG(LogLevel::INFO) << "GET _path : " << _path;LOG(LogLevel::INFO) << "GET _args : " << _args;}}}std::string Args(){LOG(LogLevel::INFO) << "client want _args : " << _args;  return _args;}bool Isexecute(){LOG(LogLevel::INFO) << "client want _isexcute : " << _isexcute;  return _isexcute;}private:bool _isexcute;                              // 是否需要動態執行std::string _args;                           // 動態執行的參數};

4.2 HttpHandler 類

增加功能路由表也就是映射目標路徑和方法unoredered_map。同時也要構建能夠處理相應操作的回調函數類型

using http_handler_t = std::function<HttpResponse(HttpRequest&)>;
std::unordered_map<std::string, http_handler_t> _route; // 功能路由表

增加注冊服務的相關功能

	// 注冊服務功能void RegisterHandler(std::string funcname, http_handler_t service) {std::string name = _prefix_path + funcname;_route.insert(std::make_pair(name, service));}// 判斷是否存在該功能bool HasHandler(std::string funcname) {auto iter = _route.find(funcname);if (iter == _route.end())return false;elsereturn true;}

將http請求處理主要分為三塊

  1. 重定向處理
  2. 動態操作處理
  3. 靜態頁面變化處理
std::string HandleRequest(std::string req) {std::cout << "------------------------------------" << std::endl;std::cout << req;HttpRequest req_obj;req_obj.Descrialize(req);HttpResponse rsp;if (req_obj.Url() == "/redirect") {LOG(LogLevel::DEBUG) << "重定向服務";// 重定向處理std::string redirect_path = "https://www.qq.com";rsp.AddCode(302, _status_code_desc[302]);rsp.AddHeader("Location", redirect_path);rsp.AddHeader("Content-Type", "text/plain"); // 添加 Content-Typersp.AddHeader("Content-Length", "0");        // 顯式設置內容長度為 0rsp.AddBodyText("");                         // 確保響應體為空} else if (req_obj.Isexecute()) {LOG(LogLevel::DEBUG) << "注冊服務";if (HasHandler(req_obj.Path())) {LOG(LogLevel::DEBUG) << "找到注冊服務";rsp = _route[req_obj.Path()](req_obj);} else {LOG(LogLevel::DEBUG) << "沒有找到注冊服務";std::string content = GetFileContent("wwwroot/404.html");rsp.AddCode(404, _status_code_desc[404]);rsp.AddHeader("Content-Length", std::to_string(content.size()));rsp.AddHeader("Content-type", _mime_type[".default"]);rsp.AddBodyText(content);}} else {LOG(LogLevel::DEBUG) << "靜態頁面服務";std::string content = GetFileContent(req_obj.Path());if (content.empty()) {content = GetFileContent("wwwroot/404.html");rsp.AddCode(404, _status_code_desc[404]);rsp.AddHeader("Content-Length", std::to_string(content.size()));rsp.AddHeader("Content-type", _mime_type[".default"]);rsp.AddBodyText(content);} else {rsp.AddCode(200, _status_code_desc[200]);rsp.AddHeader("Content-Length", std::to_string(content.size()));rsp.AddHeader("Content-type", _mime_type[req_obj.Suffix()]);rsp.AddBodyText(content);}}return rsp.Serialize();
}

4.3 TcpServer.cpp

這里我們需要將注冊服務具體化,并添加到 功能路由表

現實生活中,我們還需要對這個傳進來的參數(用戶名、密碼等)進行序列化,到數據庫中查找等操作,這里就不拓展了,簡簡單單地使用 success.html 界面表示我們登錄成功就行了

HttpResponse Login(HttpRequest& req){HttpResponse rsp;LOG(LogLevel::INFO) << "進入登錄模塊" << req.Path() << ", " << req.Args();std::string req_args = req.Args();// 1. 解析參數格式,得到要的參數// 2. 訪問數據庫,驗證對應的用戶是否是合法用戶,以及...// 3. 登錄成功HttpHandler httphandler;std::string content = httphandler.GetFileContent("wwwroot/success.html");rsp.AddCode(200, "OK");rsp.AddHeader("Content-Length", std::to_string(content.size()));rsp.AddHeader("Content-Type", "text/html");rsp.AddHeader("Set-Cokkie", "req_args");rsp.AddBodyText(content);return rsp;
}

4.4 測試

當 ·login 方法是 GET
在這里插入圖片描述

在這里插入圖片描述

當是 POST
在這里插入圖片描述

在這里插入圖片描述


👥總結

本篇博文對 【Linux網絡】Http服務優化 - 增加請求后綴、狀態碼描述、重定向、自動跳轉及注冊多功能服務 做了一個較為詳細的介紹,不知道對你有沒有幫助呢

覺得博主寫得還不錯的三連支持下吧!會繼續努力的~

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/80719.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/80719.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/80719.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

AIGC(生成式AI)試用 32 -- AI做軟件程序測試 3

總結之前的AI做程序測試過程&#xff0c;試圖優化提問方式&#xff0c;整合完成的AI程序測試提問&#xff0c;探索更多可能的AI測試 AIGC&#xff08;生成式AI&#xff09;試用 30 -- AI做軟件程序測試 1 AIGC&#xff08;生成式AI&#xff09;試用 31 -- AI做軟件程序…

C語言實現迪杰斯特拉算法進行路徑規劃

使用C語言實現迪杰斯特拉算法進行路徑規劃 迪杰斯特拉算法是一種用于尋找加權圖中最短路徑的經典算法。它特別適合用于計算從一個起點到其他所有節點的最短路徑&#xff0c;前提是圖中的邊權重為非負數。 一、迪杰斯特拉算法的基本原理 迪杰斯特拉算法的核心思想是“貪心法”…

引領印尼 Web3 變革:Mandala Chain 如何助力 1 億用戶邁向數字未來?

當前 Web3 的發展正處于關鍵轉折點&#xff0c;行業亟需吸引新用戶以推動 Web3 的真正大規模采用。然而&#xff0c;大規模采用面臨著核心挑戰&#xff1a;數據泄露風險、集中存儲的安全漏洞、跨系統互操作性障礙&#xff0c;以及低效的服務訪問等問題。如何才能真正突破這些瓶…

WebSocket是h5定義的,雙向通信,節省資源,更好的及時通信

瀏覽器和服務器之間的通信更便利&#xff0c;比http的輪詢等效率提高很多&#xff0c; WebSocket并不是權限的協議&#xff0c;而是利用http協議來建立連接 websocket必須由瀏覽器發起請求&#xff0c;協議是一個標準的http請求&#xff0c;格式如下 GET ws://example.com:3…

Kaamel白皮書:IoT設備安全隱私評估實踐

1. IoT安全與隱私領域的現狀與挑戰 隨著物聯網技術的快速發展&#xff0c;IoT設備在全球范圍內呈現爆發式增長。然而&#xff0c;IoT設備帶來便捷的同時&#xff0c;也引發了嚴峻的安全與隱私問題。根據NSF&#xff08;美國國家科學基金會&#xff09;的研究表明&#xff0c;I…

php安裝swoole擴展

PHP安裝swoole擴展 Swoole官網 安裝準備 安裝前必須保證系統已經安裝了下列軟件 4.8 版本需要 PHP-7.2 或更高版本5.0 版本需要 PHP-8.0 或更高版本6.0 版本需要 PHP-8.1 或更高版本gcc-4.8 或更高版本makeautoconf 安裝Swool擴展 安裝官方文檔安裝后需要再php.ini中增加…

服務器傳輸數據存儲數據建議 傳輸慢的原因

一、JSON存儲的局限性 1. 性能瓶頸 全量讀寫&#xff1a;JSON文件通常需要整體加載到內存中才能操作&#xff0c;當數據量大時&#xff08;如幾百MB&#xff09;&#xff0c;I/O延遲和內存占用會顯著增加。 無索引機制&#xff1a;查找數據需要遍歷所有條目&#xff08;時間復…

Android四大核心組件

目錄 一、為什么需要四大組件&#xff1f; 二、Activity&#xff1a;看得見的界面 核心功能 生命周期圖解 代碼示例 三、Service&#xff1a;看不見的勞動者 兩大類型 生命周期對比 注意陷阱 四、BroadcastReceiver&#xff1a;消息傳遞專員 兩種注冊方式 廣播類型 …

「Mac暢玩AIGC與多模態01」架構篇01 - 展示層到硬件層的架構總覽

一、概述 AIGC&#xff08;AI Generated Content&#xff09;系統由多個結構層級組成&#xff0c;自上而下涵蓋交互界面、API 通信、模型推理、計算框架、底層驅動與硬件支持。本篇梳理 AIGC 應用的六層體系結構&#xff0c;明確各組件在系統中的職責與上下游關系&#xff0c;…

[MERN 項目實戰] MERN Multi-Vendor 電商平臺開發筆記(v2.0 從 bug 到結構優化的工程記錄)

[MERN 項目實戰] MERN Multi-Vendor 電商平臺開發筆記&#xff08;v2.0 從 bug 到結構優化的工程記錄&#xff09; 其實之前沒想著這么快就能把 2.0 的筆記寫出來的&#xff0c;之前的預期是&#xff0c;下一個階段會一直維持到將 MERN 項目寫完&#xff0c;畢竟后期很多東西都…

互斥量函數組

頭文件 #include <pthread.h> pthread_mutex_init 函數原型&#xff1a; int pthread_mutex_init(pthread_mutex_t *restrict mutex, const pthread_mutexattr_t *restrict attr); 函數參數&#xff1a; mutex&#xff1a;指向要初始化的互斥量的指針。 attr&#xf…

互聯網的下一代脈搏:深入理解 QUIC 協議

互聯網的下一代脈搏&#xff1a;深入理解 QUIC 協議 互聯網是現代社會的基石&#xff0c;而數據在其中高效、安全地傳輸是其運轉的關鍵。長期以來&#xff0c;傳輸層的 TCP&#xff08;傳輸控制協議&#xff09;一直是互聯網的主力軍。然而&#xff0c;隨著互聯網應用場景的日…

全球城市范圍30米分辨率土地覆蓋數據(1985-2020)

Global urban area 30 meter resolution land cover data (1985-2020) 時間分辨率年空間分辨率10m - 100m共享方式保護期 277 天 5 時 42 分 9 秒數據大小&#xff1a;8.98 GB數據時間范圍&#xff1a;1985-2020元數據更新時間2024-01-11 數據集摘要 1985~2020全球城市土地覆…

【Vue】單元測試(Jest/Vue Test Utils)

個人主頁&#xff1a;Guiat 歸屬專欄&#xff1a;Vue 文章目錄 1. Vue 單元測試簡介1.1 為什么需要單元測試1.2 測試工具介紹 2. 環境搭建2.1 安裝依賴2.2 配置 Jest 3. 編寫第一個測試3.1 組件示例3.2 編寫測試用例3.3 運行測試 4. Vue Test Utils 核心 API4.1 掛載組件4.2 常…

數據湖的管理系統管什么?主流產品有哪些?

一、數據湖的管理系統管什么&#xff1f; 數據湖的管理系統主要負責管理和優化存儲在數據湖中的大量異構數據&#xff0c;確保這些數據能夠被有效地存儲、處理、訪問和治理。以下是數據湖管理系統的主要職責&#xff1a; 數據攝入管理&#xff1a;管理系統需要支持從多種來源&…

英文中日期讀法

英文日期的讀法和寫法因地區&#xff08;英式英語與美式英語&#xff09;和正式程度有所不同&#xff0c;以下是詳細說明&#xff1a; 一、日期格式 英式英語 (日-月-年) 寫法&#xff1a;1(st) January 2023 或 1/1/2023讀法&#xff1a;"the first of January, twenty t…

衡量矩陣數值穩定性的關鍵指標:矩陣的條件數

文章目錄 1. 定義2. 為什么要定義條件數&#xff1f;2.1 分析線性系統 A ( x Δ x ) b Δ b A(x \Delta x) b \Delta b A(xΔx)bΔb2.2 分析線性系統 ( A Δ A ) ( x Δ x ) b (A \Delta A)(x \Delta x) b (AΔA)(xΔx)b2.3 定義矩陣的條件數 3. 性質及幾何意義3…

4月22日復盤-開始卷積神經網絡

4月24日復盤 一、CNN 視覺處理三大任務&#xff1a;圖像分類、目標檢測、圖像分割 上游&#xff1a;提取特征&#xff0c;CNN 下游&#xff1a;分類、目標、分割等&#xff0c;具體的業務 1. 概述 ? 卷積神經網絡是深度學習在計算機視覺領域的突破性成果。在計算機視覺領…

【網絡原理】從零開始深入理解TCP的各項特性和機制.(三)

上篇介紹了網絡原理傳輸層TCP協議的知識,本篇博客給大家帶來的是網絡原理剩余的內容, 總體來說,這部分內容沒有上兩篇文章那么重要,本篇知識有一個印象即可. &#x1f40e;文章專欄: JavaEE初階 &#x1f680;若有問題 評論區見 ? 歡迎大家點贊 評論 收藏 分享 如果你不知道分…

解決qnn htp 后端不支持boolean 數據類型的方法。

一、背景 1.1 問題原因 Qnn 模型在使用fp16的模型轉換不支持類型是boolean的cast 算子&#xff0c;因為 htp 后端支持量化數據類型或者fp16&#xff0c;不支持boolean 類型。 ${QNN_SDK_ROOT_27}/bin/x86_64-linux-clang/qnn-model-lib-generator -c ./bge_small_fp16.cpp -b …