.Net HttpClient 使用代理功能

HttpClient 使用代理功能

實際開發中,HttpClient 通過代理訪問目標服務器是常見的需求。

本文將全面介紹如何在 .NET 中配置 HttpClient 使用代理(Proxy)功能,包括基礎使用方式、代碼示例、以及與依賴注入結合的最佳實踐。

注意:運行代碼之前,先開啟Fiddler Classic及其代理功能,充當代理服務器。

初始化

開啟Fiddler Classic及其代理功能,充當代理服務器

在這里插入圖片描述

導入初始終化筆記文件,并且執行一次

#!import "./Ini.ipynb"//共享變量
var fiddlerProxyAddress = "127.0.0.1:8888";

🧩 什么是代理?

代理(Proxy)是一種中間服務器,用于轉發客戶端請求到目標服務器。它常用于以下目的:

  • 訪問受限資源:企業內網中,通過代理服務器訪問外部資源;
  • 提高安全性和隱私保護:代理可隱藏真實 IP 地址,保護目標服務器的隱私和數據安全;
  • 提高性能:代理可使用請求緩存和負載均衡等,減少目標服務器的壓力,提高性能;
  • 方便調試、測試
    • 代理服務器可記錄請求和響應信息,方便調試和測試;
    • Fiddler Classic等軟件,默認是抓不到 HttpClient 的請求的,需要將其設置為代理服務器,才能抓取到 HttpClient 的請求;

在 .NET HttpClient 中,可以通過多種方式來設置代理服務器。

🛠? 設置 HttpClient 代理

? 基本方式使用(無用戶名密碼)

{   // 設置 SocketsHttpHandler 使用代理var handler = new SocketsHttpHandler(){UseProxy = true,Proxy = new WebProxy(fiddlerProxyAddress),};// 創建 HttpClient,并且請求using (var client = new HttpClient(handler)){var response = await client.GetAsync("https://www.baidu.com");Console.WriteLine($"響應狀態:{response.StatusCode}");}
}

執行上面的單元格,應該在fiddler classic 中,抓到請求包:可以查看和管理詳細信息.

在這里插入圖片描述

? 帶用戶名和密碼的代理

{   // 設置 SocketsHttpHandler 使用代理var handler = new SocketsHttpHandler(){UseProxy = true,Proxy = new WebProxy(fiddlerProxyAddress){//正式項目:機密數據一定要脫敏處理或者使用環境變量、機密管理器等手段//因為Fiddler代理服務器,沒有用戶憑據要求,所以此處隨意填寫的。需要的話,真實填寫正確的用戶憑據。Credentials = new NetworkCredential("username", "password"),},};// 創建 HttpClient,并且請求using (var client = new HttpClient(handler)){var response = await client.GetAsync("https://www.baidu.com");Console.WriteLine($"響應狀態:{response.StatusCode}");}
}

📦 在IoC和工廠中使用 Proxy [推薦方式]

在 ASP.NET Core 或基于 IServiceCollection 的項目中,可以通過 UseSocketsHttpHandler 擴展方法,統一管理代理服務器配置。

還可以根據客戶端的命名不同,進行不同的代理服務器配置!

//IoC或工廠中設置代理
{//IoCvar services = new ServiceCollection();//默認命名客戶端services.AddHttpClient<HttpClient>(string.Empty).ConfigureHttpClient(client => {client.BaseAddress = new Uri(webApiBaseUrl);client.Timeout = TimeSpan.FromSeconds(10);})//配置代理服務器.UseSocketsHttpHandler(handlerBuilder =>{handlerBuilder.Configure((handler,s) => {handler.Proxy = new WebProxy(fiddlerProxyAddress);}); });//發送請求var factory = services.BuildServiceProvider().GetRequiredService<IHttpClientFactory>();//正常請求var defaultClient = factory.CreateClient();var defaultContent = await defaultClient.GetStringAsync("api/hello/ping");Console.WriteLine($"正常請求,響應內容為: {defaultContent}");
}

🔄 動態切換代理服務器

要根據請求的不同(請求地址、請求方法、請求頭、請求參數等),動態選擇使用一同的代理服務器,可以使用Pipeline中間件,來管理。

///<summary>
/// 代理服務選擇器中間件
/// 注意:此中間件會短路,必須設置為最后一個中間件
///</summary>
public class ProxySelectorLastHandler : DelegatingHandler
{/// <summary>/// 攔截請求,并動態設置代理/// 注意:會短路其它中間件,要放最后/// </summary>protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken ct){Console.WriteLine("ProxySelectorLastHandler -> SendAsync -> Before");//動態選擇示例var proxy = request.RequestUri.Host switch{string url when url.Contains("baidu") => new WebProxy("127.0.0.1:8888"),string url when url.Contains("qq") => new WebProxy("127.0.0.1:8888"),_ => null};InnerHandler = new SocketsHttpHandler{Proxy = proxy,UseProxy = proxy != null};//請求HttpResponseMessage response = await base.SendAsync(request, ct);Console.WriteLine("ProxySelectorLastHandler -> SendAsync -> After");return response;}
}//日志中間件(管道類)
public class LoggerDelegatingHandler : DelegatingHandler
{protected override HttpResponseMessage Send(HttpRequestMessage request, CancellationToken cancellationToken){Console.WriteLine("LoggerDelegatingHandler -> Send -> Before");HttpResponseMessage response = base.Send(request, cancellationToken);Console.WriteLine("LoggerDelegatingHandler -> Send -> After");return response;}protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken){Console.WriteLine("LoggerDelegatingHandler -> SendAsync -> Before");HttpResponseMessage response = await base.SendAsync(request, cancellationToken);Console.WriteLine("LoggerDelegatingHandler -> SendAsync -> After");return response;}
}//使用:ProxySelectorLastHandler必須設置為最后一個中間件
{var handlerLink = new LoggerDelegatingHandler(){InnerHandler = new ProxySelectorLastHandler(),};var myClient = new HttpClient(handlerLink);var response = await myClient.GetAsync("https://www.qq.com");Console.WriteLine(response.StatusCode);Console.WriteLine("---------------------------------------------------");
}// ProxySelectorLastHandler 不是最后一個的話,其它中間件無效(被短路)
{var handlerLink = new ProxySelectorLastHandler(){InnerHandler = new LoggerDelegatingHandler (),};var myClient = new HttpClient(handlerLink);var response = await myClient.GetAsync("https://www.qq.com");Console.WriteLine(response.StatusCode);
}//注意看輸出:后面的沒有日志中間件的任何輸出

🔐 HTTPS 代理信任問題

當使用 HTTPS 代理時,可能會遇到 SSL/TLS 證書不被信任的問題,尤其是在測試環境中使用自簽名證書。

?解決方法一:忽略證書驗證(?? 注意:僅用于開發環境)

var handler = new HttpClientHandler
{Proxy = new WebProxy(fiddlerProxyAddress),UseProxy = true,ServerCertificateCustomValidationCallback = (message, cert, chain, errors) => true
};using (var client = new HttpClient(handler))
{ var response = await client.GetAsync("https://www.baidu.com");Console.WriteLine(response.StatusCode);
};

? 解決方法二:手動添加根證書信任

using System.Security;
using System.Security.Cryptography;
using System.Security.Cryptography.X509Certificates;var file = Environment.CurrentDirectory + "\\Assets\\FiddlerRoot.cer";
//Console.WriteLine(file);
var rootCert = System.Security.Cryptography.X509Certificates.X509CertificateLoader.LoadCertificateFromFile(file);var handler = new HttpClientHandler
{Proxy = new WebProxy(fiddlerProxyAddress),UseProxy = true,ServerCertificateCustomValidationCallback = (request, cert, chain, errors) =>{//return true;return chain.ChainElements.Any(x => x.Certificate.Thumbprint == cert.Thumbprint); // 驗證證書鏈包含指定根證書}
};using (var client = new HttpClient(handler))
{ var response = await client.GetAsync("https://www.baidu.com");Console.WriteLine(response.StatusCode);
};

📌 總結

通過本文,你應該掌握了以下內容:

  • 如何在 HttpClient 中直接設置代理
  • 如何在依賴注入系統中配置全局代理
  • 如何通過環境變量設置代理
  • 如何驗證代理是否生效
  • 實際使用中的注意事項
  • 動態選擇及證書信任

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

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

相關文章

【學習路線】 游戲客戶端開發入門到進階

目錄 游戲客戶端開發入門到進階&#xff1a;系統學習路線與推薦書單一、學習總原則&#xff1a;從底層出發&#xff0c;項目驅動&#xff0c;持續迭代二、推薦學習路線圖&#xff08;初學者→進階&#xff09;第一階段&#xff1a;語言基礎與編程思維第二階段&#xff1a;游戲開…

精益數據分析(57/126):創業移情階段的核心要點與實踐方法

精益數據分析&#xff08;57/126&#xff09;&#xff1a;創業移情階段的核心要點與實踐方法 在創業的浩瀚征程中&#xff0c;每一個階段都承載著獨特的使命與挑戰。今天&#xff0c;我們繼續秉持共同進步的理念&#xff0c;深入研讀《精益數據分析》&#xff0c;聚焦創業的首…

015枚舉之滑動窗口——算法備賽

滑動窗口 最大子數組和 題目描述 給你一個整數數組 nums &#xff0c;請你找出一個具有最大和的連續子數組&#xff08;子數組最少包含一個元素&#xff09;&#xff0c;返回其最大和。 原題鏈接 思路分析 見代碼注解 代碼 int maxSubArray(vector<int>& num…

微軟系統 紅帽系統 網絡故障排查:ping、traceroute、netstat

在微軟&#xff08;Windows&#xff09;和紅帽&#xff08;Red Hat Enterprise Linux&#xff0c;RHEL&#xff09;等系統中&#xff0c;網絡故障排查是確保系統正常運行的重要環節。 ping、traceroute&#xff08;在Windows中為tracert&#xff09;和netstat是三個常用的網絡…

解構認知邊界:論萬能方法的本體論批判與方法論重構——基于跨學科視閾的哲學-科學辯證

一、哲學維度的本體論批判 &#xff08;1&#xff09;理性主義的坍縮&#xff1a;從笛卡爾幻想到哥德爾陷阱 笛卡爾在《方法論》中構建的理性主義范式&#xff0c;企圖通過"普遍懷疑-數學演繹"雙重機制確立絕對方法體系。然而哥德爾不完備定理&#xff08;Gdel, 19…

【網絡入侵檢測】基于源碼分析Suricata的IP分片重組

【作者主頁】只道當時是尋常 【專欄介紹】Suricata入侵檢測。專注網絡、主機安全&#xff0c;歡迎關注與評論。 目錄 目錄 1.概要 2. 配置信息 2.1 名詞介紹 2.2 defrag 配置 3. 代碼實現 3.1 配置解析 3.1.1 defrag配置 3.1.2 主機系統策略 3.2 分片重組模塊 3.2.1…

二分查找的邊界問題

前言 二分查找(Binary Search)是一種高效的查找算法&#xff0c;時間復雜度為O(log n)。它適用于已排序的數組或列表。本文將詳細介紹二分查找的兩種常見寫法&#xff1a;閉區間寫法和左閉右開區間寫法。 一、二分查找基本思想 二分查找的核心思想是"分而治之"&am…

重慶醫科大學附屬第二醫院外科樓外擋墻自動化監測

1.項目概述 重慶醫科大學附屬第二醫院&#xff0c;重醫附二院&#xff0c;是集醫療、教學、科研、預防保健為一體的國家三級甲等綜合醫院。前身為始建于1892年的“重慶寬仁醫院”。醫院現有開放床位 1380張&#xff0c;年門診量超過百萬人次&#xff0c;年收治住院病人4.5萬人…

【Redis實戰篇】秒殺優化

1. 秒殺優化-異步秒殺思路 我們來回顧一下下單流程 當用戶發起請求&#xff0c;此時會請求nginx&#xff0c;nginx會訪問到tomcat&#xff0c;而tomcat中的程序&#xff0c;會進行串行操作&#xff0c;分成如下幾個步驟 1、查詢優惠卷 2、判斷秒殺庫存是否足夠 3、查詢訂單…

【idea】調試篇 idea調試技巧合集

前言&#xff1a;之前博主寫過一篇idea技巧合集的文章&#xff0c;由于技巧過于多了&#xff0c;文章很龐大&#xff0c;所以特地將調試相關的技巧單獨成章, 調試和我們日常開發是息息相關的&#xff0c;用好調試可以事半功倍 文章目錄 1. idea調試異步線程2. idea調試stream流…

postman 用法 LTS

postman 用法 LTS File ---- View ---- Show Postman Console

MySQL 數據庫故障排查指南

MySQL 數據庫故障排查指南 本指南旨在幫助您識別和解決常見的 MySQL 數據庫故障。我們將從問題識別開始&#xff0c;逐步深入到具體的故障類型和排查步驟。 1. 問題識別與信息收集 在開始排查之前&#xff0c;首先需要清晰地了解問題的現象和范圍。 故障現象&#xff1a; 數…

用AI寫簡歷是否可行?

讓AI批量寫簡歷然后投簡歷是絕對不行的&#xff01;&#xff01;&#xff01; 為什么不行&#xff0c;按照 "招聘經理" 工作經歷舉例&#xff1a; ai提示詞&#xff1a;請幫我寫一份招聘經理的工作經歷內容&#xff1a; 招聘經理 | XXX科技有限公司 | 2020年…

【從零實現JsonRpc框架#1】Json庫介紹

1.JsonCpp第三方庫 JSONCPP 是一個開源的 C 庫&#xff0c;用于解析和生成 JSON&#xff08;JavaScript Object Notation&#xff09;數據。它提供了簡單易用的接口&#xff0c;支持 JSON 的序列化和反序列化操作&#xff0c;適用于處理配置文件、網絡通信數據等場景。 2.Jso…

Ubuntu——執行echo $USE什么都不顯示

問題&#xff1a;“執行 echo $USER 什么都不顯示”&#xff1f; 一、原因分析 環境變量 $USER 未正確設置 $USER 是系統自動定義的環境變量&#xff0c;通常用于表示當前登錄的用戶名。若該變量未設置或為空&#xff0c;執行 echo $USER 會無輸出。可能場景&#xff1a; 用戶通…

uni-app學習筆記五--vue3插值表達式的使用

vue3快速上手導航&#xff1a;簡介 | Vue.js 模板語法 插值表達式 最基本的數據綁定形式是文本插值&#xff0c;它使用的是“Mustache”語法 (即雙大括號)&#xff1a; <span>Message: {{ msg }}</span> 雙大括號標簽會被替換為相應組件實例中 msg 屬性的值。同…

【PSINS工具箱】基于工具箱的單獨GNSS導航、單獨INS導航、兩者結合組合導航,三種導航的對比程序。附完整的代碼

本文給出基于PSINS工具箱的單獨GNSS導航、單獨INS導航、兩者結合組合導航(153EKF)的程序。并提供三者的軌跡對比、誤差對比。 文章目錄 運行結果MATLAB代碼代碼的簡單介紹簡介2. 平均絕對誤差 (MAE)主要模塊運行結果 三軸軌跡圖: 各軸誤差曲線: 命令行窗口的結果輸出: …

C. scanf 函數基礎

scanf 函數 1. scanf 函數基礎1.1 函數原型與頭文件1.2 格式化輸入的基本概念2.1 常見格式說明符整數格式說明符浮點數格式說明符字符和字符串格式說明符其他格式說明符2.2 格式說明符的高級用法寬度修飾符精度修飾符跳過輸入字段寬度組合修飾符對齊修飾符實際應用示例3.2 精度…

spring cloud loadbalancer實現機房感知的負載均衡

1 概述 在同城多機房情景下&#xff0c;各個機房各自部署一套微服務集群&#xff0c;正常情況下微服務調用在本機房閉環。在如下某些災難情景&#xff0c;可以嘗試拉遠調用以最大程度維持業務連續性&#xff0c;這些情景例如&#xff1a; A機房多個服務器宕機。應用由于BUG發…

vue中,created和mounted兩個鉤子之間調用時差值受什么影響

在 Vue 中&#xff0c;created 和 mounted 是兩個生命周期鉤子&#xff0c;它們之間的調用時差主要受以下幾個因素影響&#xff1a; &#x1f7e2; 1. 模板復雜度與渲染耗時&#xff08;最主要因素&#xff09; mounted 的觸發時間是在組件的 DOM 被掛載之后&#xff08;也就是…