如何在 Spring Boot 中编辑 feign 响应头

问题描述 投票:0回答:1

我的假客户给出了纯文本/文本响应。如何更改为application/java? 我无法将 json 响应转换为 pojo。我认为这是因为 API 返回 Content-type: plain/text 而不是 application/json 的 JSON。如何将响应标头更改为 application/json 而不是 plaint/text?

客户端.feign

@FeignClient(value = "${app.api.name}", url = "${app.api.url}")
public interface MozambiqueheApi {

    @GetMapping("/bridge?" + "auth=" + "${app.api.token}" + "&player={playerName}" + "&platform={playerPlatform}")
    @Headers("Content-Type: application/json")
    ResponseEntity<TestPojo> getInfoByPlayer(@PathVariable String playerName, @PathVariable Platforms playerPlatform); 

控制器.主控制器

@RestController
public class MainController {

    private Feign feign;

    public MainController() {
        this.feign= Feign.builder()
                .requestInterceptor(new HeaderTestRequestInterceptor())
                .encoder(new JacksonEncoder())
                .decoder(new JacksonDecoder())
                .contract(new SpringMvcContract())
                .target(Feign.class, "https://api.test.re");
    }

    @GetMapping(value = "/")
    public ResponseEntity<TestPojo> getMain() {
        return feign.getInfoByPlayer("name", Platforms.PC);
    }
}

modifier.headertestrequest拦截器

public class HeaderTestRequestInterceptor implements RequestInterceptor {
    @Override
    public void apply(RequestTemplate requestTemplate) {
        requestTemplate.header("Content-Type", "application/json");
    }
}

API 的 Json 响应

{
    "global": {
        "name": "name",
        "uid": 1234546897956,
        "avatar": "",
        "platform": "PC",
        "level": 23,
        "toNextLevelPercent": 62,
        "internalUpdateCount": 22,
        "bans": {
            "isActive": false,
            "remainingSeconds": 0,
            "last_banReason": "NONE"
        }
    }
}

模型.testpojo

public class TestPojo {

    public static class Global {
        private String name;

        public Global() {
        }

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }
    }

    private Global global;

    public TestPojo() {
    }

    public Global getGlobal() {
        return global;
    }

    public void setGlobal(Global global) {
        this.global = global;
    }
}
java spring-boot spring-mvc jackson spring-cloud-feign
1个回答
0
投票

我遇到同样的问题已经快两年了。由于 feign.ResponseInterceptor 中的 Javadoc 告诉我们

可以配置零个或一个响应拦截器以用于以下目的 作为验证或修改响应标头

但是传入 ResponseInterceptor 的 feign.Response#headers 是 UnmodifyingMap 的一个实例,因此没有简单的方法来配置它。下面的建议只是仰卧起坐的列表:

  1. 使用固定标头构造新的 Response 并将其传递给 InspirationContext#decoder:
@Override
    public Object aroundDecode(InvocationContext invocationContext) throws IOException {
        Response source = invocationContext.response();
        var headers = new HashMap<>(source.headers());
        //do what u want with headers
        
        Response fixedResponse = Response.builder()
                .headers(headers)
                .body(source.body())
                .build();
        return invocationContext.decoder().decode(fixedResponse, invocationContext.returnType());
    }

但最大的缺点是原始 InvocableContext#proceed 中需要重复的 try/catch 代码:

public Object proceed() {
try {
  return decoder.decode(response, returnType);
} catch (final FeignException e) {
  throw e;
} catch (final RuntimeException e) {
  throw new DecodeException(response.status(), e.getMessage(), response.request(), e);
} catch (IOException e) {
  throw errorReading(response.request(), response, e);
}
}
  1. 使用 java.lang.reflection 修改 Response.headers。但在java版本18及更高版本(我的情况)中,唯一的方法是使用java代理的机制:https://stackoverflow.com/a/56043252/16548953

顺便说一句,我选择了第一个。

© www.soinside.com 2019 - 2024. All rights reserved.