You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Java 11 HttpRequest POST请求无法被FastAPI服务识别问题

Java 11 HttpClient 请求FastAPI返回422错误的解决方法

使用Java 11的HttpClient发送POST请求到FastAPI接口时,返回422状态码,提示请求体缺失,但curl和Java旧版HttpURLConnection方式都能正常请求。


相关代码

FastAPI服务代码

# 启动命令:uvicorn simle_ws:app --host=0.0.0.0 --port=8001
from datetime import date
import pandas as pd

from fastapi import FastAPI
from pydantic import BaseModel


class Dataset(BaseModel):
    key: str
    value: float


app = FastAPI()


@app.post("/test/")
async def test(dataset: Dataset):
    return dataset

curl请求(正常工作)

curl -X 'POST' \
    'http://localhost:8001/test/' \
    -H 'accept: application/json' \
    -H 'Content-Type: application/json' \
    -d '{"key": "age","value": 43}'

返回结果:{"key":"age","value":42.0}

Java 11前的请求方式(正常工作)

@Test
void testPree11() throws IOException {
    URL url = new URL("http://localhost:8001/test/");
    HttpURLConnection con = (HttpURLConnection) url.openConnection();
    con.setRequestMethod("POST");
    con.setRequestProperty("Content-Type", "application/json");
    con.setRequestProperty("Accept", "application/json");
    con.setDoOutput(true);
    String jsonInputString = """{
            "key": "age",
            "value": 42
        }
        """;
    try (OutputStream os = con.getOutputStream()) {
        byte[] input = jsonInputString.getBytes(StandardCharsets.UTF_8);
        os.write(input, 0, input.length);
    }

    try (BufferedReader br = new BufferedReader(new InputStreamReader(con.getInputStream(), StandardCharsets.UTF_8))) {
        StringBuilder response = new StringBuilder();
        String responseLine;
        while ((responseLine = br.readLine()) != null) {
            response.append(responseLine.trim());
        }
        assertEquals(200, con.getResponseCode());
        String expected = """{
                "key":"age","value":42.0
                """;
        assertEquals(expected.trim(), response.toString().trim());
    }
}

Java 11 HttpClient请求方式(失败)

@Test
void testPost11() throws URISyntaxException, IOException, InterruptedException {
    String jsonInputString = """{
          "key": "age",
          "value": 42
        }
        """;
    HttpRequest request = HttpRequest.newBuilder()
            .uri(new URI("http://localhost:8001/test/"))
            .header("Accept", "application/json")
            .header("Content-Type", "application/json")
            .POST(HttpRequest.BodyPublishers.ofString(jsonInputString))
            .build();

    HttpClient.Builder clientBuilder = HttpClient.newBuilder();
    HttpClient client = clientBuilder.build();
    HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
    assertEquals(200, response.statusCode());
    String expected = """{
        "key":"age","value":42.0
        """;
    assertEquals(expected.trim(), response.body().trim());
}

返回状态码422,响应内容:

{
    "detail": [
        {
          "type": "missing",
          "loc": [
            "body"
          ],
          "msg": "Field required",
          "input": null
        }
    ]
}

问题原因

Java 11的HttpRequest.BodyPublishers.ofString(jsonInputString)方法会自动为请求添加Content-Type: text/plain;charset=utf-8头,覆盖掉手动设置的Content-Type: application/json。FastAPI接收到text/plain类型的请求后,不会将其解析为JSON请求体,因此提示请求体缺失。


解决方案

有两种可行的解决方式:

方式一:指定字符集并覆盖Content-Type头

使用ofString时指定UTF-8字符集,再通过setHeader方法覆盖自动添加的Content-Type头:

HttpRequest request = HttpRequest.newBuilder()
        .uri(new URI("http://localhost:8001/test/"))
        .header("Accept", "application/json")
        .POST(HttpRequest.BodyPublishers.ofString(jsonInputString, StandardCharsets.UTF_8))
        .setHeader("Content-Type", "application/json") // 覆盖自动添加的Content-Type
        .build();

方式二:使用字节数组发送请求

将JSON字符串转为UTF-8字节数组,通过BodyPublishers.ofByteArray发送,避免自动添加Content-Type头:

HttpRequest request = HttpRequest.newBuilder()
        .uri(new URI("http://localhost:8001/test/"))
        .header("Accept", "application/json")
        .header("Content-Type", "application/json")
        .POST(HttpRequest.BodyPublishers.ofByteArray(jsonInputString.getBytes(StandardCharsets.UTF_8)))
        .build();

验证

修改后重新运行测试,请求将返回200状态码,响应内容与预期一致。

内容的提问来源于stack exchange,提问作者Johan Walter

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.02 11:12:11