【Http】一文備忘Http狀態碼(406,415,422)


最近在調試接口時,web api 報了一個415狀態碼。好久沒見到這個狀態碼,一時還真不知道啥情況。所以,人的大腦是有遺忘規律的,為了加深印象,所以我覺得我有必要再復習一下。

1.HTTP的狀態碼

首先復習一下所有的狀態碼。

  • 1xx:屬於信息性的狀態碼。Web API並不使用1xx的狀態碼。

  • 2xx:意味着請求執行的很成功。

    • 200:Ok,表示請求成功;
    • 201:Created,請求成功並創建了資源;
    • 204:No Content,請求成功,但是不應該返回任何東西,例如刪除操作。
  • 3xx:用於跳轉。例如告訴搜素引擎,某個頁面的網址已經永久的改變了。絕大多數的Web API都不需要使用這類狀態碼。

  • 4xx:客戶端錯誤

    • 400:Bad Request,表示API消費者發送到服務器的請求是有錯誤的;
    • 401:Unauthorized,表示沒有提供授權信息或者提供的授權信息不正確;
    • 403:Forbidden,表示身份認證已經成功,但是已認證的用戶卻無法訪問請求的資源;
    • 404:Not Found,表示請求的資源不存在;
    • 405:Method not allowed,當嘗試發送請求到資源的時候,使用了不被支持的HTTP方法時,就會返回405狀態碼;
    • 406:Not acceptable,這表示API消費者請求的表述格式並不被Web API所支持,並且API不會提供默認的表述格式。例如請求的媒體類型是application/xml,但是Web API僅支持application/json類型,並且API不會將application/json作為默認格式提供;
    • 409:Conflict,表示請求與服務器當前狀態沖突。通常指更新資源時發生的沖突,例如,當你編輯某個資源的時候,該資源在服務器上又進行了更新,所以你編輯的資源版本和服務器的不一致。當然有時候也用來表示你想要創建的資源在服務器上已經存在了。它就是用來處理並發問題的狀態碼。
    • 415:Unsupported media type,與406正好相反,有一些請求必須帶着數據發往服務器,這些數據都屬於特定的媒體類型,如果API不支持該媒體類型格式,415就會被返回。
    • 422:Unprocessable entity,它是HTTP擴展協議的一部分。它說明服務器已經懂得了實體的Content Type,也就是說415狀態碼肯定不合適;此外,實體的語法也沒有問題,所以400也不合適。但是服務器仍然無法處理這個實體數據,這時就可以返回422。所以它通常是用來表示語意上有錯誤,通常就表示實體驗證的錯誤。
  • 5xx:服務器錯誤

  • 500:Internal server error,表示服務器出現了錯誤,客戶端無能為力,只能以后再試試了。

——摘自楊旭老師B站視頻

本篇重點關注狀態碼406和415,順帶看一下422。

2.”我要的你不給“——406

在http請求中,Accept表明客戶端希望接收的數據類型。當請求包含accept頭,在ASP.NET Core框架中,將會:

  • accept頭中順序枚舉媒體類型
  • 嘗試找到一個能生成accept中指定的格式之一的格式化器

一旦找不到格式化器,ASP.NET Core將會:

  • 返回406 Not acceptable,只要需要設置如下:
public void ConfigureServices(IServiceCollection services)
{
    services.AddControllers(options =>
    {
        options.ReturnHttpNotAcceptable = true;
    })
}
  • 或者嘗試找到第一個可以生成響應的格式化程序:如果ASP.NET Core沒有為所請求的格式配置格式化程序,則使用可以格式化該對象的第一個格式化程序.

如果請求沒有Accept頭:

  • 使用第一個可以處理對象的格式化器來響應序列化
  • 不執行任何協商,由ASP.NET Core決定返回的格式

Accept: */*,..,..,如果Accept 包含*/*,那么就會忽略Accept,除非做如下配置:

public void ConfigureServices(IServiceCollection services)
{
    services.AddControllers(options =>
    {
        options.RespectBrowserAcceptHeader = true; // false by default
    });
}

這樣,在使用 API 時,與在瀏覽器中的體驗一致:

  • 忽略Accept
  • 若為另行配置,將會使用JSON返回內容

3.“我給的你不要”——415

說會我們問題的初衷,報了415,我這邊ajax設置的Content-Type:application/x-www-form-urlencoded,然后asp.net core返回了415.

在HTTP中,Content-Type代表客戶端發送的實體數據的數據類型,如果客戶端是以application/x-www-form-urlencoded ,在asp.net core中用[FromBody]接收,服務端api是不會接收數據,便會返回415 Unsupported Media Type-不支持的媒體類型。

  • application/x-www-form-urlencoded,使用[FromForm]接收數據
  • application/json,使用[FromBody]接收數據

4.“我給的你還不要”——422

順帶提一下並不常用,但是卻非常有用的狀態碼——422。

422:Unprocessable entity,它是HTTP擴展協議的一部分。

  • 服務器已經懂得了實體的Content Type的媒體類型,也就是說415狀態碼肯定不合適;
  • 此外,實體的語法也沒有問題,所以400也不合適。

但是服務器仍然無法處理這個實體數據,這時就可以返回422。所以它通常是用來表示語意上有錯誤,或者不符合接口要求的數據,通常就表示實體驗證的錯誤。對於實體模型驗證錯誤:

ASP.NET Core默認使用的是400狀態碼-Bad Request

{
  "errors": {
  },
  "type": "https://tools.ietf.org/html/rfc7231#section-6.5.1",
  "title": "One or more validation errors occurred.",
  "status": 400,
  "traceId": "|cb69a381-495c34b204e78961."
}

采用422會更准確的說明是實體數據問題。如果想要服務端返回422,還需要做單獨配置,詳細配置如下:

services.AddControllers(options =>
{
    options.ReturnHttpNotAcceptable = true;
})
.ConfigureApiBehaviorOptions(options =>
{
    options.InvalidModelStateResponseFactory = context =>
    {
        var problemDetails = new ValidationProblemDetails(context.ModelState)
        {
            Type = "https://tools.ietf.org/html/rfc4918#section-11.2",
            Title = "One or more validation errors occurred.",
            Status = StatusCodes.Status422UnprocessableEntity,
            Detail = "",
            Instance = context.HttpContext.Request.Path
        };
        problemDetails.Extensions.Add("traceId", context.HttpContext.TraceIdentifier);
        return new UnprocessableEntityObjectResult(problemDetails)
        {
            ContentTypes = { "application/problem+json" }
        };
	};
});
{
  "errors": {
  },
  "type": "https://tools.ietf.org/html/rfc4918#section-11.2",
  "title": "One or more validation errors occurred.",
  "status": 422,
  "detail": "",
  "instance": "/api/admin/Sms",
  "traceId": "0HM25M2D86T30:00000001"
}

作者:Garfield

同步更新至個人博客:http://www.randyfield.cn/

本文版權歸作者所有,未經許可禁止轉載,否則保留追究法律責任的權利,若有需要請聯系287572291@qq.com


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM