RestTemplate client with cookies
Solution 1
RestTemplate
has a method in which you can define Interface ResponseExtractor<T>
, this interface is used to obtain the headers of the response, once you have them you could send it back using HttpEntity
and added again.
.add("Cookie", "SERVERID=c52");
Try something like this.
String cookieHeader = null;
new ResponseExtractor<T>(){
T extractData(ClientHttpResponse response) {
response.getHeaders();
}
}
Then
HttpHeaders headers = new HttpHeaders();
headers.add("Cookie", cookieHeader );
ResponseEntity<byte[]> response = restTemplate.exchange("http://example.com/file/123",
GET,
new HttpEntity<String>(headers),
byte[].class);
Also read this post
Solution 2
I've solved the problem by creating an interceptor which stores a cookie and puts it in next requests.
public class StatefulRestTemplateInterceptor implements ClientHttpRequestInterceptor {
private String cookie;
@Override
public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution) throws IOException {
if (cookie != null) {
request.getHeaders().add(HttpHeaders.COOKIE, cookie);
}
ClientHttpResponse response = execution.execute(request, body);
if (cookie == null) {
cookie = response.getHeaders().getFirst(HttpHeaders.SET_COOKIE);
}
return response;
}
}
Set the interceptor for your RestTemplate:
@Bean
public RestTemplate restTemplate(RestTemplateBuilder templateBuilder) {
return templateBuilder
.requestFactory(new BufferingClientHttpRequestFactory(new HttpComponentsClientHttpRequestFactory()))
.interceptors(new StatefulRestTemplateInterceptor())
.build();
}
Solution 3
Small update to handle sessions in a complete test with 'java.net.HttpCookie' Object.
@Thanks Shedon
import java.io.IOException;
import java.net.HttpCookie;
import java.net.URI;
import java.util.ArrayList;
import java.util.List;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.client.ClientHttpRequest;
import org.springframework.http.client.ClientHttpRequestFactory;
import org.springframework.http.client.ClientHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RequestCallback;
import org.springframework.web.client.ResponseExtractor;
import org.springframework.web.client.RestClientException;
import org.springframework.web.client.RestTemplate;
/**
* @link https://stackoverflow.com/questions/22853321/resttemplate-client-with-cookies
*/
@Component
public class RestTemplateWithCookies extends RestTemplate {
private final List<HttpCookie> cookies = new ArrayList<>();
public RestTemplateWithCookies() {
}
public RestTemplateWithCookies(ClientHttpRequestFactory requestFactory) {
super(requestFactory);
}
public synchronized List<HttpCookie> getCoookies() {
return cookies;
}
public synchronized void resetCoookies() {
cookies.clear();
}
private void processHeaders(HttpHeaders headers) {
final List<String> cooks = headers.get("Set-Cookie");
if (cooks != null && !cooks.isEmpty()) {
cooks.stream().map((c) -> HttpCookie.parse(c)).forEachOrdered((cook) -> {
cook.forEach((a) -> {
HttpCookie cookieExists = cookies.stream().filter(x -> a.getName().equals(x.getName())).findAny().orElse(null);
if (cookieExists != null) {
cookies.remove(cookieExists);
}
cookies.add(a);
});
});
}
}
@Override
protected <T extends Object> T doExecute(URI url, HttpMethod method, final RequestCallback requestCallback, final ResponseExtractor<T> responseExtractor) throws RestClientException {
final List<HttpCookie> cookies = getCoookies();
return super.doExecute(url, method, new RequestCallback() {
@Override
public void doWithRequest(ClientHttpRequest chr) throws IOException {
if (cookies != null) {
StringBuilder sb = new StringBuilder();
for (HttpCookie cookie : cookies) {
sb.append(cookie.getName()).append(cookie.getValue()).append(";");
}
chr.getHeaders().add("Cookie", sb.toString());
}
requestCallback.doWithRequest(chr);
}
}, new ResponseExtractor<T>() {
@Override
public T extractData(ClientHttpResponse chr) throws IOException {
processHeaders(chr.getHeaders());
return responseExtractor.extractData(chr);
}
});
}
}
Solution 4
You need to use exchange
method of RestTemplate
of Java Spring framework.
Read this tutorial: http://codeflex.co/java-rest-client-get-cookie/
Solution 5
i've wrote a simple class that extends RestTemplate and handles cookies.
import java.io.IOException;
import java.net.URI;
import java.util.List;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.client.ClientHttpRequest;
import org.springframework.http.client.ClientHttpRequestFactory;
import org.springframework.http.client.ClientHttpResponse;
import org.springframework.web.client.RequestCallback;
import org.springframework.web.client.ResponseExtractor;
import org.springframework.web.client.RestClientException;
import org.springframework.web.client.RestTemplate;
public class RestTemplateWithCookies extends RestTemplate {
private List<String> cookies = null;
public RestTemplateWithCookies() {
}
public RestTemplateWithCookies(ClientHttpRequestFactory requestFactory) {
super(requestFactory);
}
private synchronized List<String> getCoookies() {
return cookies;
}
private synchronized void setCoookies(List<String> cookies) {
this.cookies = cookies;
}
public synchronized void resetCoookies() {
this.cookies = null;
}
private void processHeaders(HttpHeaders headers) {
final List<String> cookies = headers.get("Set-Cookie");
if (cookies != null && !cookies.isEmpty()) {
setCoookies(cookies);
}
}
@Override
protected <T extends Object> T doExecute(URI url, HttpMethod method, final RequestCallback requestCallback, final ResponseExtractor<T> responseExtractor) throws RestClientException {
final List<String> cookies = getCoookies();
return super.doExecute(url, method, new RequestCallback() {
@Override
public void doWithRequest(ClientHttpRequest chr) throws IOException {
if(cookies != null) {
for(String cookie : cookies) {
chr.getHeaders().add("Cookie", cookie);
}
}
requestCallback.doWithRequest(chr);
}
}, new ResponseExtractor<T>() {
@Override
public T extractData(ClientHttpResponse chr) throws IOException {
processHeaders(chr.getHeaders());
return responseExtractor.extractData(chr);
}
});
}
}
Tom
Updated on February 10, 2021Comments
-
Tom over 3 years
I'm writing a simple client in Java to allow reusable use of proprietary virus scanning software accessible through a RESTful API. To upload a file for scanning the API requires a
POST
for Connect, followed by aPOST
for Publishing the file to the server. In the response to the ConnectPOST
there are cookies set by the server which need to be present in the subsequentPOST
for publishing the file. I'm currently using SpringRestTemplate
in my client.My question is how do I access the cookies in the response to forward back to the server with the subsequent
POST
? I can see that they are present in the header that is returned but there are no methods on theResponseEntity
to access them.