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

WireMock自定义响应调用badRequest()返回422而非400的问题排查

WireMock请求过滤器返回422而非预期400错误的排查

在自定义WireMock请求过滤器类中,预期触发条件时返回400 Bad Request错误,但实际收到的是422 Unprocessable Entity错误。即便调用了ResponseDefinition.badRequest()方法,依然抛出422错误,想确认这是WireMock的预期行为还是代码实现有遗漏。

自定义请求过滤器代码

import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.List;

import org.apache.commons.codec.binary.Base64;
import org.springframework.stereotype.Component;

import com.example.wiremock.errorhandler.BadRequestError;
import com.example.wiremock.errorhandler.MockError;
import com.example.wiremock.errorhandler.MockErrorResponse;
import com.example.wiremock.luukuresponse.LuukkuBasicInfoResponse;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.github.tomakehurst.wiremock.common.Errors;
import com.github.tomakehurst.wiremock.common.Errors.Error;
import com.github.tomakehurst.wiremock.common.Errors.Error.Source;
import com.github.tomakehurst.wiremock.common.Json;
import com.github.tomakehurst.wiremock.extension.requestfilter.RequestFilterAction;
import com.github.tomakehurst.wiremock.extension.requestfilter.StubRequestFilter;
import com.github.tomakehurst.wiremock.http.HttpHeader;
import com.github.tomakehurst.wiremock.http.Request;
import com.github.tomakehurst.wiremock.http.ResponseDefinition;

@Component
public class BasicAuthRequestFilter extends StubRequestFilter { 

    public String decodeJwt(String token) throws UnsupportedEncodingException {
        String payload = token.split("\\.")[1];
        return new String(Base64.decodeBase64(payload), "UTF-8");
    }

    @Override
    public RequestFilterAction filter(Request request){
        if (request.header("Authorization").firstValue().matches("Bearer [a-zA-Z0-9&._-]{1,}")) {
            String authtoken = request.header("Authorization").firstValue();
            ObjectMapper objectMapper = new ObjectMapper();
            objectMapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);

            String str;
            try {
                String pattern = "^\\S{4}75-\\S{4}$";
                str = decodeJwt(authtoken);
                Token token = objectMapper.readValue(str, Token.class);
                String test = token.getRepresentation().getId();
                
                if(test.matches(pattern)) {
                    Error error = new Error(400, null, "response", null);
                    List<Error> listOfErros = new ArrayList<>();
                    listOfErros.add(error);
                    Errors errorList = new Errors(listOfErros);
                    return RequestFilterAction.stopWith(ResponseDefinition.badRequest(errorList));
                }
            } catch (UnsupportedEncodingException  | JsonProcessingException e) {
                e.printStackTrace();
            }
            return RequestFilterAction.continueWith(request);
        }
        return null;
    }

    @Override
    public String getName() {
        return "Authorization";
    }
}

实际错误表现

Postman请求返回截图显示响应状态码为422 Unprocessable Entity,而非预期的400。


问题原因

核心问题在于你使用了WireMock内置的Errors/Error类构建响应体。WireMock内部有预设逻辑:当响应体为Errors类型时,会自动将状态码覆盖为422 Unprocessable Entity,这会直接冲掉你通过badRequest()设置的400状态码,属于框架的内置行为。

解决方案

不要使用WireMock自带的错误类,改用你代码中已经导入的自定义错误DTO(比如BadRequestError/MockError),手动构建响应并指定状态码:

修改后的核心代码片段

if(test.matches(pattern)) {
    // 用自定义错误类构建响应内容
    MockError mockError = new MockError(400, "response", null);
    List<MockError> errorList = new ArrayList<>();
    errorList.add(mockError);
    BadRequestError badRequestError = new BadRequestError(errorList);
    
    ObjectMapper objectMapper = new ObjectMapper();
    String errorJson;
    try {
        errorJson = objectMapper.writeValueAsString(badRequestError);
    } catch (JsonProcessingException e) {
        e.printStackTrace();
        // 序列化失败时的兜底响应
        errorJson = "{\"errors\": [{\"status\": 400, \"source\": \"response\"}]}";
    }

    // 手动构建响应,明确指定400状态码
    ResponseDefinition responseDefinition = new ResponseDefinitionBuilder()
            .withStatus(400)
            .withHeader("Content-Type", "application/json")
            .withBody(errorJson)
            .build();
            
    return RequestFilterAction.stopWith(responseDefinition);
}

额外注意事项

  1. 先判断Authorization请求头是否存在,再调用firstValue(),避免空指针异常
  2. JWT解码逻辑未处理无效格式(比如token分割后不足3段),需要补充异常捕获
  3. Token类未在代码中导入,需补充对应的import语句

内容的提问来源于stack exchange,提问作者Shruti Mishra

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.22 02:50:25