我正在尝试通过调用 API 通过 Spring Cloud Feign Client 发送音频 OGG 文件字节。
但是我得到了
400 Bad Request
,错误如下:
"error_message" : "OGG header has not been found"
尽管如此,如果 OGG 文件是从 Postman 发送的(具有相同的标头和 OGG 文件),那么一切都会正常工作。
FeignClient:
@FeignClient(name = "${integration[0].speech.name}",
url = "${integration[0].speech.url}",
configuration = SpeechRecognizerConfig.class)
public interface YandexSpeechRecognizerClient {
@PostMapping
@Headers({
"Content-Type", "audio/ogg"
})
RecognizedTextResponse recognizeText(@RequestHeader("Authorization") String token,
@RequestParam("lang") String lang,
@RequestBody ByteArrayResource oggFileBytes);
}
FeignClient 配置:
@Bean
public Logger.Level feignLoggerLevel() {
return Logger.Level.FULL;
}
@Bean
public Client httpFeignClient() {
return new OkHttpClient(new okhttp3.OkHttpClient.Builder()
.build());
}
@Bean
public Feign.Builder speechFeignBuilder(@Autowired Logger.Level logLevel, @Autowired Client client) {
return Feign.builder()
.logger(new Slf4jLogger(log))
.logLevel(logLevel)
.client(client);
}
测试方法:
byte[] bytes = Files.readAllBytes(oggFile.toPath());
RecognizedTextResponse yandexRecognizedTextResponse = underTest.recognizeText(
"Bearer " + authClient.getToken().getAccessToken(),
"en-EN",
false,
false,
"123123123",
new ByteArrayResource(bytes)
);
我已经尝试了所有其他替代方案,但没有一个有效。
如何解决这个问题?
参考:https://github.com/spring-cloud/spring-cloud-openfeign/issues/889
根本原因:您正在尝试使用/混合Core Feign与Spring Cloud Feign。
这不会起作用。
不起作用的原因 -
@Headers
注释是 feign
包的一部分,而不是 org.springframework.cloud.openfeign
的一部分。
可能的解决方案:
第一个解决方案: Spring Cloud Feign 仅通过方法参数上的
@RequestHeader
支持标头。
将代码更新为:
FeignClient:
@FeignClient(name = "${integration[0].speech.name}",
url = "${integration[0].speech.url}",
configuration = SpeechRecognizerConfig.class)
public interface YandexSpeechRecognizerClient {
@PostMapping
RecognizedTextResponse recognizeText(@RequestHeader("Authorization") String token,
@RequestHeader("Content-Type") String contentType,
@RequestParam("lang") String lang,
@RequestBody ByteArrayResource oggFileBytes);
测试方法:
byte[] bytes = Files.readAllBytes(oggFile.toPath());
RecognizedTextResponse yandexRecognizedTextResponse = underTest.recognizeText(
"Bearer " + authClient.getToken().getAccessToken(),
"audio/ogg",
"en-EN",
false,
false,
"123123123",
new ByteArrayResource(bytes)
);
第二种解决方案:
您可以通过
spring.cloud.openfeign.client.config.{name}.defaultRequestHeaders
设置默认标头,该标头将随假客户端的每个请求一起发送。
示例:
application.yaml
:
spring:
cloud:
openfeign:
client:
config:
{name}:
.....
......
defaultRequestHeaders:
Content-Type: audio/ogg
@Header
注释似乎没有按预期工作。您可以尝试以这种方式注入静态标头:
@PostMapping(headers = "content-type=audio/ogg")
// or
@PostMapping(produces = "audio/ogg")
另一种选择是在专用 FeignClientConfig 中使用
RequestInterceptor
:
@Bean
public RequestInterceptor requestInterceptor() {
return requestTemplate ->
requestTemplate.header("Content-Type", "audio/ogg");
}
或在配置属性中指定默认标头,如下所示:
feign:
client:
config:
your-client-name:
Content-Type:
- audio/ogg
但这两种方法的缺点是它们会影响同一假客户端的其他方法