[netty5: HttpHeaders HttpHeadersFactory]-源碼分析

HttpHeaders

HttpHeaders 是用于存儲和操作HTTP請求或響應頭部字段的接口。

// DefaultHttpHeaders, HttpHeadersFactory.TrailingHttpHeaders 
public interface HttpHeaders extends Iterable<Entry<CharSequence, CharSequence>> {static HttpHeaders emptyHeaders() {return newHeaders(2, true, true, true);}static HttpHeaders newHeaders() {return newHeaders(true);}static HttpHeaders newHeaders(boolean validate) {return newHeaders(16, validate, validate, validate);}static HttpHeaders newHeaders(int sizeHint, boolean checkNames, boolean checkCookies, boolean checkValues) {return new DefaultHttpHeaders(sizeHint, checkNames, checkCookies, checkValues);}HttpHeaders copy();@NullableCharSequence get(CharSequence name);default CharSequence get(final CharSequence name, final CharSequence defaultValue) {final CharSequence value = get(name);return value != null ? value : defaultValue;}@NullableCharSequence getAndRemove(CharSequence name);default CharSequence getAndRemove(final CharSequence name, final CharSequence defaultValue) {final CharSequence value = getAndRemove(name);return value == null ? defaultValue : value;}Iterator<CharSequence> valuesIterator(CharSequence name);default Iterable<CharSequence> values(CharSequence name) {return () -> (Iterator<CharSequence>) valuesIterator(name);}default boolean contains(final CharSequence name) {return get(name) != null;}default boolean contains(CharSequence name, CharSequence value) {return AsciiString.contentEquals(get(name), value);}default boolean containsIgnoreCase(CharSequence name, CharSequence value) {return AsciiString.contentEqualsIgnoreCase(get(name), value);}int size();default boolean isEmpty() {return size() == 0;}Set<CharSequence> names();HttpHeaders add(CharSequence name, CharSequence value);HttpHeaders add(CharSequence name, Iterable<? extends CharSequence> values);default HttpHeaders add(CharSequence name, Iterator<? extends CharSequence> valuesItr) {while (valuesItr.hasNext()) {add(name, valuesItr.next());}return this;}HttpHeaders add(CharSequence name, CharSequence... values);HttpHeaders add(HttpHeaders headers);HttpHeaders set(CharSequence name, CharSequence value);HttpHeaders set(CharSequence name, Iterable<? extends CharSequence> values);default HttpHeaders set(CharSequence name, Iterator<? extends CharSequence> valueItr) {remove(name);while (valueItr.hasNext()) {add(name, valueItr.next());}return this;}default HttpHeaders set(CharSequence name, CharSequence... values) {remove(name);for (CharSequence value : values) {add(name, value);}return this;}default HttpHeaders set(final HttpHeaders headers) {if (headers != this) {clear();add(headers);}return this;}default HttpHeaders replace(final HttpHeaders headers) {if (headers != this) {for (final CharSequence key : headers.names()) {remove(key);}add(headers);}return this;}boolean remove(CharSequence name);boolean remove(CharSequence name, CharSequence value);boolean removeIgnoreCase(CharSequence name, CharSequence value);HttpHeaders clear();@OverrideIterator<Entry<CharSequence, CharSequence>> iterator();@Overridedefault Spliterator<Entry<CharSequence, CharSequence>> spliterator() {return Spliterators.spliterator(iterator(), size(), Spliterator.SIZED);}@OverrideString toString();default String toString(BiFunction<? super CharSequence, ? super CharSequence, CharSequence> filter) {return HeaderUtils.toString(this, filter);}@NullableHttpCookiePair getCookie(CharSequence name);@NullableHttpSetCookie getSetCookie(CharSequence name);default Iterable<HttpCookiePair> getCookies() {return () -> (Iterator<HttpCookiePair>) getCookiesIterator();}Iterator<HttpCookiePair> getCookiesIterator();default Iterable<HttpCookiePair> getCookies(CharSequence name) {return () -> (Iterator<HttpCookiePair>) getCookiesIterator(name);}Iterator<HttpCookiePair> getCookiesIterator(CharSequence name);default Iterable<HttpSetCookie> getSetCookies() {return () -> (Iterator<HttpSetCookie>) getSetCookiesIterator();}Iterator<HttpSetCookie> getSetCookiesIterator();default Iterable<HttpSetCookie> getSetCookies(CharSequence name) {return () -> (Iterator<HttpSetCookie>) getSetCookiesIterator(name);}Iterator<HttpSetCookie> getSetCookiesIterator(CharSequence name);default Iterable<HttpSetCookie> getSetCookies(CharSequence name, CharSequence domain, CharSequence path) {return () -> (Iterator<HttpSetCookie>) getSetCookiesIterator(name, domain, path);}Iterator<HttpSetCookie> getSetCookiesIterator(CharSequence name, CharSequence domain, CharSequence path);HttpHeaders addCookie(HttpCookiePair cookie);default HttpHeaders addCookie(final CharSequence name, final CharSequence value) {return addCookie(new DefaultHttpCookiePair(name, value));}HttpHeaders addSetCookie(HttpSetCookie cookie);default HttpHeaders addSetCookie(final CharSequence name, final CharSequence value) {return addSetCookie(new DefaultHttpSetCookie(name, value));}boolean removeCookies(CharSequence name);boolean removeSetCookies(CharSequence name);boolean removeSetCookies(CharSequence name, CharSequence domain, CharSequence path);
}

HttpCookiePair

HttpCookiePair 接口定義了 HTTP Cookie 鍵值對的結構,包括名稱、值、是否被雙引號包裹及其編碼表示, 格式如下:

  1. <cookie-name>=<cookie-value>
  2. <cookie-name>=“<cookie-value>”
// DefaultHttpCookiePair
public interface HttpCookiePair {CharSequence name();CharSequence value();boolean isWrapped();CharSequence encodedCookie();
}

HttpSetCookie

HttpSetCookie 接口擴展了 HttpCookiePair,表示一個完整的 Set-Cookie,包含域、路徑、生命周期、安全屬性、SameSite 策略等信息,支持編碼與過期計算。

Set-Cookie HTTP 頭的格式大致如下:

Set-Cookie: <cookie-name>=<cookie-value>; Expires=<date>; Max-Age=<seconds>; Domain=<domain>; Path=<path>; Secure; HttpOnly; SameSite=<Lax|Strict|None>; Partitioned
字段名是否必填值類型說明
name=value字符串Cookie 的名稱和值,必須出現在首位。value 可包含特殊字符,建議進行 URL 編碼。
Expires=<date>GMT 日期字符串設定 Cookie 的過期時間,格式如 Wed, 09 Jun 2027 10:18:14 GMT。過期即被刪除。
Max-Age=<秒數>整數(秒)設置 Cookie 的生存時間(從當前起多少秒),優先級高于 Expires
Domain=<domain>字符串指定 Cookie 可被哪些域訪問,默認是當前域,不帶子域;設置 .example.com 可包括子域。
Path=<path>字符串指定 Cookie 生效的路徑,默認是當前路徑及其子路徑。常用 / 表示全站有效。
Secure無值表示僅在 HTTPS 連接中發送該 Cookie,保障傳輸安全。
HttpOnly無值禁止通過 JavaScript 訪問該 Cookie,可防范 XSS 攻擊。
SameSiteLax | Strict | None控制是否允許跨站點請求攜帶該 Cookie。
? Strict: 嚴格禁止跨站請求
? Lax: 允許部分(如 GET 跳轉)
? None: 允許全部,需配合 Secure
Partitioned無值指示該 Cookie 為分區 Cookie(Partitioned Cookie)。必須與 SecureSameSite=None 一起使用,僅部分瀏覽器支持。
// DefaultHttpSetCookie
public interface HttpSetCookie extends HttpCookiePair {@NullableCharSequence domain();@NullableCharSequence path();@NullableLong maxAge();@NullableCharSequence expires();@Nullabledefault Long expiresAsMaxAge() {CharSequence expires = expires();if (expires != null) {Date expiresDate = DateFormatter.parseHttpDate(expires);if (expiresDate != null) {long maxAgeMillis = expiresDate.getTime() - System.currentTimeMillis();return maxAgeMillis / 1000 + (maxAgeMillis % 1000 != 0 ? 1 : 0);}}return null;}@NullableSameSite sameSite();boolean isSecure();boolean isHttpOnly();CharSequence encodedSetCookie();enum SameSite {Lax, Strict, None}boolean isPartitioned();
}

HttpHeadersFactory

HttpHeadersFactory 是用于創建和配置 HTTP 頭部對象及其校驗行為的工廠接口。

// DefaultHttpHeadersFactory
public interface HttpHeadersFactory {HttpHeaders newHeaders();HttpHeaders newEmptyHeaders();int getSizeHint();boolean isValidatingNames();boolean isValidatingValues();boolean isValidatingCookies();
}

public final class DefaultHttpHeadersFactory implements HttpHeadersFactory {private static final int SIZE_HINT = 16;private static final DefaultHttpHeadersFactory FOR_HEADER =new DefaultHttpHeadersFactory(SIZE_HINT, true, true, true, false);private static final DefaultHttpHeadersFactory FOR_TRAILER =new DefaultHttpHeadersFactory(SIZE_HINT, true, true, true, true);private static final int MIN_SIZE_HINT = 2;// 用于提示內部數據結構(通常是哈希表)應該多大。private final int sizeHint;// 是否開啟 HTTP 頭名稱的合法性校驗(比如是否符合 RFC 規定的字符集等)。private final boolean validateNames;// 是否開啟 HTTP 頭的值的合法性校驗。private final boolean validateValues;// 是否在解析 Cookie 時對 Cookie 內容做合法性校驗(如格式、字符等)。private final boolean validateCookies;// 是否以“尾部頭”(trailer header)專用的規則進行名稱校驗。private final boolean validateAsTrailer;private DefaultHttpHeadersFactory(int sizeHint, boolean validateNames, boolean validateValues, boolean validateCookies, boolean validateAsTrailer) {this.sizeHint = Math.max(MIN_SIZE_HINT, sizeHint); this.validateNames = validateNames;this.validateValues = validateValues;this.validateCookies = validateCookies;this.validateAsTrailer = validateAsTrailer;}public static DefaultHttpHeadersFactory headersFactory() {return FOR_HEADER;}public static DefaultHttpHeadersFactory trailersFactory() {return FOR_TRAILER;}@Overridepublic HttpHeaders newHeaders() {if (validateAsTrailer) {return new TrailingHttpHeaders(sizeHint, validateNames, validateCookies, validateValues);}return HttpHeaders.newHeaders(sizeHint, validateNames, validateCookies, validateValues);}@Overridepublic HttpHeaders newEmptyHeaders() {if (validateAsTrailer) {return new TrailingHttpHeaders(MIN_SIZE_HINT, validateNames, validateCookies, validateValues);}return HttpHeaders.newHeaders(MIN_SIZE_HINT, validateNames, validateCookies, validateValues);}// ...private static final class TrailingHttpHeaders extends DefaultHttpHeaders {TrailingHttpHeaders(int arraySizeHint, boolean validateNames, boolean validateCookies, boolean validateValues) {super(arraySizeHint, validateNames, validateCookies, validateValues);}// 該類用于處理 HTTP 的 trailing headers —— 即 chunked 編碼中的最后一塊 trailer 部分。// RFC 7230 明確禁止 trailing headers 不能包含某些首部字段,如:Content-Length, Transfer-Encoding, Trailer@Overrideprotected CharSequence validateKey(@Nullable CharSequence name, boolean forAdd) {if (HttpHeaderNames.CONTENT_LENGTH.contentEqualsIgnoreCase(name)|| HttpHeaderNames.TRANSFER_ENCODING.contentEqualsIgnoreCase(name)|| HttpHeaderNames.TRAILER.contentEqualsIgnoreCase(name)) {throw new IllegalArgumentException("Prohibited trailing header: " + name);}return super.validateKey(name, forAdd);}}
}

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

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

相關文章

基于Flink 1.20、StarRocks與TiCDC構建高效數據處理鏈路教程

在大數據處理領域&#xff0c;實現高效、實時的數據處理與分析至關重要。Flink作為強大的流批一體化計算框架&#xff0c;結合StarRocks這一高性能的實時分析型數據庫&#xff0c;再搭配TiCDC&#xff08;TiDB Change Data Capture&#xff09;用于捕獲數據變更&#xff0c;能夠…

便捷的Office批量轉PDF工具

軟件介紹 本文介紹的軟件是一款能實現Office批量轉換的工具&#xff0c;名為五五Excel word批量轉PDF。 軟件小巧 這款五五Excel word批量轉PDF軟件大小不到2M。 操作步驟一 使用該軟件時&#xff0c;只需把軟件和需要轉換的Word或Excel文件放在同一個文件夾里。 操作步驟…

tcp長連接與短連接

TCP連接本身是一個傳輸層協議&#xff0c;它既可以實現長連接&#xff0c;也可以實現短連接。這取決于應用層的使用方式。 短連接&#xff08;Short Connection&#xff09; 特點&#xff1a;每次請求都建立新的TCP連接&#xff0c;完成后立即關閉流程&#xff1a;建立連接 →…

llvm polly,親自測試

1&#xff09;下載并安裝 Polly - Getting Started git clone https://github.com/llvm/llvm-project.git 大概需要半個小時&#xff0c;有時候被墻掉就打不開 2&#xff09; mkdir build && cd build cmake -DLLVM_ENABLE_PROJECTSclang;polly ../llvm cmake --b…

Spring AI 項目實戰(十四):Spring Boot + Vue3 +AI + DeepSeek 實現空氣質量智能預測系統(附完整源碼)

系列文章 序號文章名稱1Spring AI 項目實戰(一):Spring AI 核心模塊入門2Spring AI 項目實戰(二):Spring Boot + AI + DeepSeek 深度實戰(附完整源碼)3Spring AI 項目實戰(三):Spring Boot + AI + DeepSeek 打造智能客服系統(附完整源碼)4

騰訊云 CDN 不支持 WebSocket 的現狀與華為云 CDN 的替代方案-優雅草卓伊凡

騰訊云 CDN 不支持 WebSocket 的現狀與華為云 CDN 的替代方案-優雅草卓伊凡 問題背景 卓伊凡今天發現&#xff0c;騰訊云 CDN 不支持 WebSocket 協議&#xff0c;而公司的部分業務&#xff08;如實時聊天、在線協作、游戲互動、股票行情推送等&#xff09;依賴長連接通信。昨…

MybatisPlus(一)擴展功能

擴展功能 一、靜態工具二、邏輯刪除三、通用枚舉1、定義枚舉2、配置枚舉處理器3、測試 四、JSON類型處理器1、定義實體2、使用類型處理器 五、分頁1、配置分頁插件2、分頁API3、示例 一、靜態工具 有的時候Service之間也會相互調用&#xff0c;為了避免出現循環依賴問題&#…

Redis哨兵模式之Sentinel模式(二)

一、多節點哨兵如何配置&#xff1f; 哨兵配置原理圖 注意&#xff1a;sentinel哨兵模式的搭建是建立在redis主從復制節點配置基礎而搭建&#xff0c;在主從配置中從庫需要配置好replicaof關聯上主庫并關閉安全模式&#xff0c;然后設置好bind端口才能關聯上機器&#xff0c;而…

基于Excel的數據分析思維與分析方法

數據分析一定要會Excel、SQL和Python&#xff1f;非常肯定地回答您&#xff0c;Python、R語言、Excel函數和VBA&#xff0c;以及高級數據分析軟件&#xff0c;都學不到&#xff0c;您將學到&#xff1a;5個有效的數據分析利器&#xff0c;以及分析思維 一、描述性統計分析 在…

計算機網絡筆記(不全)

一、計算機網絡體系結構1.計算機網絡的概念計算機網絡&#xff1a;由若干結點和連接這些結點的鏈路組成。結點可以是計算機、集線器、交換機、路由器等。互連網(internet)&#xff1a;多個計算機網絡通過路由器互相連接而成&#xff0c;可用任意協議通信。互聯網(因特網Interne…

XML Schema 復合元素

XML Schema 復合元素 引言 XML(可擴展標記語言)作為一種靈活的標記語言,廣泛應用于數據交換和存儲。XML Schema 是一種用于描述和定義 XML 文檔結構的語言,它定義了 XML 文檔的元素、屬性、類型和約束。本文將詳細介紹 XML Schema 中的復合元素,并探討其在實際應用中的重…

華為云Flexus+DeepSeek征文 | 彈性算力實戰:Flexus X實例自動擴縮容策略優化

華為云FlexusDeepSeek征文 | 彈性算力實戰&#xff1a;Flexus X實例自動擴縮容策略優化 &#x1f31f; 嗨&#xff0c;我是IRpickstars&#xff01; &#x1f30c; 總有一行代碼&#xff0c;能點亮萬千星辰。 &#x1f50d; 在技術的宇宙中&#xff0c;我愿做永不停歇的探索者…

【倉頡】運行環境配置VSCode + Win11

作者&#xff1a;大李子 團隊&#xff1a;堅果派 十年iOS&#xff0c;All in轉鴻蒙 前言 “倉頡編程語言是一款面向全場景智能的新一代編程語言&#xff0c;主打原生智能化、天生全場景、高性能、強安全。融入鴻蒙生態&#xff0c;為開發者提供良好的編程體驗。” ——摘自倉…

【K線訓練軟件研發歷程】【日常記錄向】1.K線滑動窗口

文章目錄 當前效果未來發展思路技術選型值得分享的技術點數據加載、解析的代碼echats的代碼當前效果 ??相當于有個hello world了。 未來發展思路 開源 技術選型 界面直接采用electron,等開源后,可以直接掛release,用戶下載安裝包后,一鍵安裝,一鍵運行,降低使用門檻…

抖音解析下載工具 v1.0.0:免安裝單文件,一鍵無水印保存高清視音頻

寶子們&#xff0c;今天給你們帶來一款超輕量的抖音下載神器——抖音解析下載工具 v1.0.0。 它只有單文件&#xff0c;雙擊就能用&#xff0c;免安裝、無廣告、完全免費&#xff0c;復制粘貼鏈接即可一鍵解析下載高清無水印視頻/音頻&#xff0c;簡直不要太方便&#xff01; 為…

Ingress——2

目錄 ?一. 域名重定向&#xff08;HTTP→HTTPS/舊域名跳轉&#xff09;? ?二. 前后端分離Rewrite&#xff08;路徑改寫&#xff09;? ?三. 混合配置示例&#xff08;重定向Rewrite&#xff09;? ?四. SSL/TLS配置&#xff08;HTTPS加密&#xff09;? ?五. 基本認…

12. grafana-Dashboard的Variable(過濾)使用

說明制作這樣一個選擇過濾的下拉框&#xff0c;可以選擇某個服務器的步驟1. 點擊最上面的Dashboard settings2. 選擇Variables 并點擊ADD variable3. 寫出過濾的標簽名和查詢條件&#xff08;label_values(查詢條件)&#xff09;4. 點擊 save as... 保存退出5. 出來后左上角就…

Cursor一鍵續杯pro教程,支持最新1.0系列版本

使用前檢查&#xff1a; 使用前請先看左下角&#xff0c;是否獲取到Cursor的版本號 如果沒有請先在 功能頁面 -→ 自定義Cursor路徑 選擇你Cursor的安裝的路徑&#xff0c;并開啟后重啟YCursor&#xff0c;獲取到版本后才能正常使用功能 檢查軟件左下角的權限標識是否為綠色 如…

pyhton基礎【25】面向對象進階六

目錄 十七.單例模式 實現單例模式的兩種方式 __new__方法概述 單例模式的使用場景 十七.單例模式 引入 單例模式是一種常用的軟件設計模式&#xff0c;它確保一個類只有一個實例&#xff0c;并提供一個全局訪問點來獲取這個實例。 實現單例模式的兩種方式 使用類屬性創…

后端樹形結構

案例 在后端開發中&#xff0c;樹形結構數據的查詢和處理是一個常見的需求&#xff0c;比如部門管理、分類目錄展示等場景。接下來&#xff0c;我們以一個部門管理系統為例&#xff0c;詳細介紹如何實現后端的樹查詢功能。 案例背景 假設我們正在開發一個公司的內部管理系統&am…