Spring 引导:从服务器错误接收时如何解决 Content-Type
Spring Boot: How to resolve Content-Type when incorrectly received from server
我在 Java 中有以下 class。我期待它向 url 发出 GET 请求,取回 JSON 有效负载,并将该有效负载转换为 List<LocationData>
.
package ...
import ...
@Repository
public class ProxiedLocationRepo {
public List<LocationData> findAll() throws Exception {
RestTemplate restTemplate = new RestTemplate();
String url = UriComponentsBuilder
.fromUriString("https://my-host/path")
.queryParams("some", "queryParams")
.toUriString();
ResponseEntity<List<LocationData>> res = restTemplate.exchange(
url,
HttpMethod.GET,
null,
new ParameterizedTypeReference<List<LocationData>>(){});
if (res.getStatusCode() == HttpStatus.ACCEPTED) {
return res.getBody();
} else {
throw new ResponseStatusException(res.getStatusCode(), "Did not receive a 200 response from Server.");
}
}
}
但是,我得到了这个错误:
org.springframework.http.InvalidMediaTypeException: Invalid mime type "charset=UTF-8": does not contain '/'
这是预期的,因为如果我从 curl 执行相同的请求,并检查 headers 我得到这个(注意 Content-Type 行):
$ curl -sfi 'https://my-host/path?some=queryParams'
HTTP/1.1 200 OK
Server: nginx
Date: Wed, 06 Mar 2019 13:58:58 GMT
Content-Type: charset=UTF-8
Content-Length: 1821
Connection: keep-alive
Vary: Accept-Encoding
Strict-Transport-Security: max-age=31536000; includeSubDomains
X-Frame-Options: SAMEORIGIN
... # perfectly formatted JSON payload here
我知道从该服务器返回的 Content-Type 将是 application/json
,但它没有提供给我。
有没有办法告知 RestTemplate#exchange
响应的 Content-Type 是什么?如果没有,除了让服务器的所有者正确设置 Content-Type 之外,还有其他方法可以用来解决这个问题吗?
编辑:
我也尝试添加 "Accept" header 但得到了相同的结果:
$ curl -sfi 'https://my-host/path?some=queryParams' \
-H 'Accept: application/json'
不幸的是,我认为在利用 Spring 框架时没有任何方法可以解决此问题。即使您要创建接受 ANY MIME 类型的自定义 JsonbHttpMessageConverter
,Spring 仍然无法解析从请求中收到的不正确的 Content-Type(因为它找不到 "/"
在 Content-Type 字符串中)。
所以这里的解决方案是使用 java.net.HttpURLConnection
代替网络,然后使用 com.fasterxml.jackson.databind.ObjectMapper
从 JSON 映射到 POJO。
它有效,但代价是无法再利用任何 Spring 的 HTTP 处理,这可能比我单独实现的任何东西都要强大得多。
我在 Java 中有以下 class。我期待它向 url 发出 GET 请求,取回 JSON 有效负载,并将该有效负载转换为 List<LocationData>
.
package ...
import ...
@Repository
public class ProxiedLocationRepo {
public List<LocationData> findAll() throws Exception {
RestTemplate restTemplate = new RestTemplate();
String url = UriComponentsBuilder
.fromUriString("https://my-host/path")
.queryParams("some", "queryParams")
.toUriString();
ResponseEntity<List<LocationData>> res = restTemplate.exchange(
url,
HttpMethod.GET,
null,
new ParameterizedTypeReference<List<LocationData>>(){});
if (res.getStatusCode() == HttpStatus.ACCEPTED) {
return res.getBody();
} else {
throw new ResponseStatusException(res.getStatusCode(), "Did not receive a 200 response from Server.");
}
}
}
但是,我得到了这个错误:
org.springframework.http.InvalidMediaTypeException: Invalid mime type "charset=UTF-8": does not contain '/'
这是预期的,因为如果我从 curl 执行相同的请求,并检查 headers 我得到这个(注意 Content-Type 行):
$ curl -sfi 'https://my-host/path?some=queryParams'
HTTP/1.1 200 OK
Server: nginx
Date: Wed, 06 Mar 2019 13:58:58 GMT
Content-Type: charset=UTF-8
Content-Length: 1821
Connection: keep-alive
Vary: Accept-Encoding
Strict-Transport-Security: max-age=31536000; includeSubDomains
X-Frame-Options: SAMEORIGIN
... # perfectly formatted JSON payload here
我知道从该服务器返回的 Content-Type 将是 application/json
,但它没有提供给我。
有没有办法告知 RestTemplate#exchange
响应的 Content-Type 是什么?如果没有,除了让服务器的所有者正确设置 Content-Type 之外,还有其他方法可以用来解决这个问题吗?
编辑: 我也尝试添加 "Accept" header 但得到了相同的结果:
$ curl -sfi 'https://my-host/path?some=queryParams' \
-H 'Accept: application/json'
不幸的是,我认为在利用 Spring 框架时没有任何方法可以解决此问题。即使您要创建接受 ANY MIME 类型的自定义 JsonbHttpMessageConverter
,Spring 仍然无法解析从请求中收到的不正确的 Content-Type(因为它找不到 "/"
在 Content-Type 字符串中)。
所以这里的解决方案是使用 java.net.HttpURLConnection
代替网络,然后使用 com.fasterxml.jackson.databind.ObjectMapper
从 JSON 映射到 POJO。
它有效,但代价是无法再利用任何 Spring 的 HTTP 处理,这可能比我单独实现的任何东西都要强大得多。