Spring rest模板401错误响应
Spring rest template 401 error response
我有一个休息控制器在 http://localhost:8080/documents 上回答。
我应该有授权 header 才能调用它。
所以在我的客户端代码中我有:
HttpHeaders headers = new HttpHeaders();
headers.set(HttpHeaders.AUTHORIZATION, "myToken");
HttpEntity entity = new HttpEntity(null, headers);
restTemplate = new RestTemplate();
restTemplate.getMessageConverters().add(new MappingJackson2HttpMessageConverter());
restTemplate.getMessageConverters().add(new StringHttpMessageConverter());
response = restTemplate.exchange("http://localhost:8080/documents", HttpMethod.GET, entity, Document[].class);
一切正常。
之后我想测试错误。
所以,我删除了授权 header.
当我使用邮递员之类的工具进行测试时,我收到了 401 响应。
但是使用我的其余模板,我只收到 IllegalArgumentException。
我还测试了 ResponseErrorHandler。
public class MyErrorHandler implements ResponseErrorHandler {
@Override
public boolean hasError(ClientHttpResponse clientHttpResponse) throws IOException {
return false; //i've also tried return true
}
@Override
public void handleError(ClientHttpResponse clientHttpResponse) throws IOException {
String theString = IOUtils.toString(clientHttpResponse.getBody());
FunctionalTestException exception = new FunctionalTestException();
Map<String, Object> properties = new HashMap<String, Object>();
properties.put("code", clientHttpResponse.getStatusCode().toString());
properties.put("body", theString);
properties.put("header", clientHttpResponse.getHeaders());
exception.setProperties(properties);
throw exception;
}
}
在我的客户中我有
restTemplate.setErrorHandler(new MyErrorHandler());
没用。
所以我的问题是如何使用其余模板找到我的 401 错误响应。
这里是例外:
java.lang.IllegalArgumentException: invalid start or end
和堆栈跟踪:
sun.net.www.protocol.http.HttpURLConnection.getInputStream0(HttpURLConnection.java:1455)
sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1441)
sun.net.www.protocol.http.HttpURLConnection.getHeaderField(HttpURLConnection.java:2979)
java.net.HttpURLConnection.getResponseCode(HttpURLConnection.java:489)
org.springframework.http.client.SimpleBufferingClientHttpRequest.executeInternal(SimpleBufferingClientHttpRequest.java:84)
org.springframework.http.client.AbstractBufferingClientHttpRequest.executeInternal(AbstractBufferingClientHttpRequest.java:48)
org.springframework.http.client.AbstractClientHttpRequest.execute(AbstractClientHttpRequest.java:53)
org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:619)
org.springframework.web.client.RestTemplate.execute(RestTemplate.java:580)
org.springframework.web.client.RestTemplate.exchange(RestTemplate.java:498)
org.boite.dq.steps.UnauthorizedUser.callListCategories(UnauthorizedUser.java:61)
sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
java.lang.reflect.Method.invoke(Method.java:498)
org.jbehave.core.steps.StepCreator$ParametrisedStep.perform(StepCreator.java:733)
org.jbehave.core.embedder.PerformableTree$FineSoFar.run(PerformableTree.java:346)
org.jbehave.core.embedder.PerformableTree$PerformableSteps.perform(PerformableTree.java:1088)
org.jbehave.core.embedder.PerformableTree$AbstractPerformableScenario.performRestartableSteps(PerformableTree.java:953)
org.jbehave.core.embedder.PerformableTree$NormalPerformableScenario.perform(PerformableTree.java:992)
org.jbehave.core.embedder.PerformableTree$PerformableScenario.perform(PerformableTree.java:902)
org.jbehave.core.embedder.PerformableTree$PerformableStory.performScenarios(PerformableTree.java:825)
org.jbehave.core.embedder.PerformableTree$PerformableStory.perform(PerformableTree.java:798)
org.jbehave.core.embedder.PerformableTree.performCancellable(PerformableTree.java:422)
org.jbehave.core.embedder.PerformableTree.perform(PerformableTree.java:393)
org.jbehave.core.embedder.StoryManager$EnqueuedStory.call(StoryManager.java:292)
org.jbehave.core.embedder.StoryManager$EnqueuedStory.call(StoryManager.java:266)
java.util.concurrent.FutureTask.run(FutureTask.java:266)
java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
java.lang.Thread.run(Thread.java:745)
崩溃发生在 HttpURLConnection::getHeaderField
,因此我怀疑您的其中一个回复 header 格式不正确(不是 HttpURLConnection
所期望的)。通常 401
响应附带 WWW-Authenticate
响应 header 将代理指向服务支持的身份验证方法。我怀疑这是 header 导致崩溃的原因。
Jersey 的 issue-tracker 中的 A bug report 表明 HttpURLConnection
对 WWW-Authentication
header 格式施加了一些限制。在这种特殊情况下,导致类似崩溃的值是 oauth_problem=token_rejected
。提出的解决方法是:
Workaround is to send valid header values (spec compliant) or using the ApacheConnector
我有一个休息控制器在 http://localhost:8080/documents 上回答。 我应该有授权 header 才能调用它。
所以在我的客户端代码中我有:
HttpHeaders headers = new HttpHeaders();
headers.set(HttpHeaders.AUTHORIZATION, "myToken");
HttpEntity entity = new HttpEntity(null, headers);
restTemplate = new RestTemplate();
restTemplate.getMessageConverters().add(new MappingJackson2HttpMessageConverter());
restTemplate.getMessageConverters().add(new StringHttpMessageConverter());
response = restTemplate.exchange("http://localhost:8080/documents", HttpMethod.GET, entity, Document[].class);
一切正常。 之后我想测试错误。 所以,我删除了授权 header.
当我使用邮递员之类的工具进行测试时,我收到了 401 响应。 但是使用我的其余模板,我只收到 IllegalArgumentException。
我还测试了 ResponseErrorHandler。
public class MyErrorHandler implements ResponseErrorHandler {
@Override
public boolean hasError(ClientHttpResponse clientHttpResponse) throws IOException {
return false; //i've also tried return true
}
@Override
public void handleError(ClientHttpResponse clientHttpResponse) throws IOException {
String theString = IOUtils.toString(clientHttpResponse.getBody());
FunctionalTestException exception = new FunctionalTestException();
Map<String, Object> properties = new HashMap<String, Object>();
properties.put("code", clientHttpResponse.getStatusCode().toString());
properties.put("body", theString);
properties.put("header", clientHttpResponse.getHeaders());
exception.setProperties(properties);
throw exception;
}
}
在我的客户中我有
restTemplate.setErrorHandler(new MyErrorHandler());
没用。
所以我的问题是如何使用其余模板找到我的 401 错误响应。
这里是例外:
java.lang.IllegalArgumentException: invalid start or end
和堆栈跟踪:
sun.net.www.protocol.http.HttpURLConnection.getInputStream0(HttpURLConnection.java:1455)
sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1441)
sun.net.www.protocol.http.HttpURLConnection.getHeaderField(HttpURLConnection.java:2979)
java.net.HttpURLConnection.getResponseCode(HttpURLConnection.java:489)
org.springframework.http.client.SimpleBufferingClientHttpRequest.executeInternal(SimpleBufferingClientHttpRequest.java:84)
org.springframework.http.client.AbstractBufferingClientHttpRequest.executeInternal(AbstractBufferingClientHttpRequest.java:48)
org.springframework.http.client.AbstractClientHttpRequest.execute(AbstractClientHttpRequest.java:53)
org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:619)
org.springframework.web.client.RestTemplate.execute(RestTemplate.java:580)
org.springframework.web.client.RestTemplate.exchange(RestTemplate.java:498)
org.boite.dq.steps.UnauthorizedUser.callListCategories(UnauthorizedUser.java:61)
sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
java.lang.reflect.Method.invoke(Method.java:498)
org.jbehave.core.steps.StepCreator$ParametrisedStep.perform(StepCreator.java:733)
org.jbehave.core.embedder.PerformableTree$FineSoFar.run(PerformableTree.java:346)
org.jbehave.core.embedder.PerformableTree$PerformableSteps.perform(PerformableTree.java:1088)
org.jbehave.core.embedder.PerformableTree$AbstractPerformableScenario.performRestartableSteps(PerformableTree.java:953)
org.jbehave.core.embedder.PerformableTree$NormalPerformableScenario.perform(PerformableTree.java:992)
org.jbehave.core.embedder.PerformableTree$PerformableScenario.perform(PerformableTree.java:902)
org.jbehave.core.embedder.PerformableTree$PerformableStory.performScenarios(PerformableTree.java:825)
org.jbehave.core.embedder.PerformableTree$PerformableStory.perform(PerformableTree.java:798)
org.jbehave.core.embedder.PerformableTree.performCancellable(PerformableTree.java:422)
org.jbehave.core.embedder.PerformableTree.perform(PerformableTree.java:393)
org.jbehave.core.embedder.StoryManager$EnqueuedStory.call(StoryManager.java:292)
org.jbehave.core.embedder.StoryManager$EnqueuedStory.call(StoryManager.java:266)
java.util.concurrent.FutureTask.run(FutureTask.java:266)
java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
java.lang.Thread.run(Thread.java:745)
崩溃发生在 HttpURLConnection::getHeaderField
,因此我怀疑您的其中一个回复 header 格式不正确(不是 HttpURLConnection
所期望的)。通常 401
响应附带 WWW-Authenticate
响应 header 将代理指向服务支持的身份验证方法。我怀疑这是 header 导致崩溃的原因。
A bug report 表明 HttpURLConnection
对 WWW-Authentication
header 格式施加了一些限制。在这种特殊情况下,导致类似崩溃的值是 oauth_problem=token_rejected
。提出的解决方法是:
Workaround is to send valid header values (spec compliant) or using the ApacheConnector