相关文章推荐
打酱油的荒野  ·  Getting this error ...·  8 月前    · 
唠叨的碗  ·  Search | NSW Government·  9 月前    · 
强悍的台灯  ·  python - TensorFlow - ...·  2 年前    · 

HttpClient 有個 BaseAddress 屬性,若設定妥當,GetAsync() 或 PostAsync() 時可只傳相對路徑,用起來蠻方便的。

但最近我踩到一個雷,當 BaseAddress 只有主機名稱不包含路徑(例如: http://www.host.net ),HttpClient 對加不加 / 符號的包容度很高;但如果 BaseAddress 包含路徑(例如: http://www.host.net/api ),則 BaseAddress 結尾能不能加 /、GetAsync()/PostAsync() 路徑前方能不能加 / 則有很嚴格的要求,四種組合只有一種可被接受,感覺蠻雷的,寫篇筆記分享。

用以下範例來重現問題,假設我要連到 http://localhost/aspnet/check/test.txt ,其內容為字串 "OK"。使用 HttpClient BaseAddress + GetAsync() 下載,我做了兩組測試,BaseAddress 分別為 http://localhost (只有主機名稱) 以及 http://localhost/aspnet (主機名稱加路徑),每組測試會測試 BaseAddress 結尾加或不加 /、GetAsync() 前方加或不加 /,每組有四種組合。

// expect: http://localhost/aspnet/check/test.txt, content == "OK"
// host only
Console.WriteLine($"{"baseAddr",-24}\t{"path",-16}\tresult");
Console.WriteLine("*** host only ***");
await TestHttpClient("http://localhost/", "aspnet/check/test.txt");
await TestHttpClient("http://localhost/", "/aspnet/check/test.txt");
await TestHttpClient("http://localhost", "aspnet/check/test.txt");
await TestHttpClient("http://localhost", "/aspnet/check/test.txt");
// host + path
Console.WriteLine("*** host + path ***");
await TestHttpClient("http://localhost/aspnet/", "check/test.txt");
await TestHttpClient("http://localhost/aspnet/", "/check/test.txt");
await TestHttpClient("http://localhost/aspnet", "check/test.txt");
await TestHttpClient("http://localhost/aspnet", "/check/test.txt");
async Task TestHttpClient(string baseAddr, string path) 
    var c = new HttpClient();
    c.BaseAddress = new Uri(baseAddr);