Spring RestTemplate GET request returns 302 status - java

I am trying to consume a third party REST API using Spring's RestTemplate component. I have tried entering the same request on an external REST API Client (Postman) - using the same URI and custom headers and I am able to retrieve the correct data.
However, when I tried to mirror the exact request using RestTemplate, it returns me
<html><head>
<title>302 Found</title>
</head><body>
<h1>Found</h1>
<p>The document has moved here.</p>
<hr>
<address>Apache/2.4.7 (Ubuntu) Server at address Port 80</address>
</body></html>
This is a sample of the code I am using:
String uri = "http://address/{path of endpoint}";
RestTemplate restTemplate = new RestTemplate();
HttpHeaders headers = new HttpHeaders();
headers.set(someCustomHeaderKey, someCustomHeaderValue);
HttpEntity<String> entity = new HttpEntity<String>(headers);
ResponseEntity<String> response = restTemplate.exchange(uri, HttpMethod.GET, entity, String.class);
I have read that java does not allow redirect from one protocol to another, for instance, from http to https and vise versa. Would require some help on the approach on this.

RestTemplate will follow redirects by default, but not if the protocol is different,
which is the situation that you are seeing (redirecting from http to https).
For a more full explanation, and code that makes this work, see
HTTPURLConnection Doesn't Follow Redirect from HTTP to HTTPS

I have tried your code on my local machine and everything seems fine.
302 status code is indicating that your URI location is different.
as per your example, you should use https instead of Http in URI
I have tried your code as below
String uri = "https://jsonplaceholder.typicode.com/todos/1";
RestTemplate restTemplate = new RestTemplate();
HttpHeaders headers = new HttpHeaders();
headers.set("link", "http/:");
HttpEntity<String> entity = new HttpEntity<String>(headers);
ResponseEntity<String> response = restTemplate.exchange(uri, HttpMethod.GET,
entity, String.class);
System.out.println(response);
output in console
<200,{
"userId": 1,
"id": 1,
"title": "delectus aut autem",
"completed": false
},[Date:"Thu, 12 Mar 2020 03:45:44 GMT", Content-Type:"application/json; charset=utf-8", Content-Length:"83", Connection:"keep-alive", Set-Cookie:"__cfduid=d3104b8bbd25cbcb802977fc9183d559e1583984744; expires=Sat, 11-Apr-20 03:45:44 GMT; path=/; domain=.typicode.com; HttpOnly; SameSite=Lax", X-Powered-By:"Express", Vary:"Origin, Accept-Encoding", Access-Control-Allow-Credentials:"true", Cache-Control:"max-age=14400", Pragma:"no-cache", Expires:"-1", X-Content-Type-Options:"nosniff", Etag:"W/"53-hfEnumeNh6YirfjyjaujcOPPT+s"", Via:"1.1 vegur", CF-Cache-Status:"HIT", Age:"1747", Accept-Ranges:"bytes", Expect-CT:"max-age=604800, report-uri="https://report-uri.cloudflare.com/cdn-cgi/beacon/expect-ct"", Server:"cloudflare", CF-RAY:"572a862eab83d5e8-BOM"]>

Related

RestTemplate getting 403 Forbidden while request via Postman or Curl works fine

I am using RestTemplate to call an external service which is obviously developed with php. I am a user of this service and have no control over it to change any configurations. When I call the service with a GET request using Postman, I get the correct response. But when trying to call the service with RestTemplate within a Spring Boot application, like this:
String response = restTemplate.exchange(
SERVICE_URL_INCLUDING_TOKEN,
HttpMethod.GET,
null,
String.class).getBody();
I get this error:
You don't have permission to access this resource
I tried setting the user agent manually like this:
HttpHeaders headers = new HttpHeaders();
headers.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON));
headers.add(
HttpHeaders.USER_AGENT,
"Mozilla/5.0 Firefox/26.0"
);
HttpEntity<String> entity = new HttpEntity<>(null, headers);
String response = restTemplate.exchange(
SERVICE_URL_INCLUDING_TOKEN,
HttpMethod.GET,
entity,
String.class).getBody();
Now I get a different custom response with status 302:
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html><head>
<title>302 Found</title>
</head><body>
<h1>Found</h1>
<p>The document has moved here.</p>
</body></html>
This is not an error but definitely not the json response I was expecting. I noticed when sending the request with Postman a cookie PHPSESSID with a value like this bt1d4ea1cdd6afb49b0cca7a94ecb493 is set automatically in the header. But I have no clue how to get this cookie using restTemplate. Unfortunately the support staff of the external service are not also very helpful and couldn't help.
any idea how to solve this issue?

Follow original HTTP Method - What's the java fix?

Postman has a setting which corrects the method on calls which redirect.
Postman Settings : Follow original HTTP Method
Follow original HTTP Method: Redirect with the original HTTP method
instead of the default behavior of redirecting with GET.
How can we implement this in Java code? I am using OKHttp. I am also open to using other libs if necessary.
Error:{"detail": "Method "GET" not allowed."}
OkHttpClient client = new OkHttpClient().newBuilder()
.build();
MediaType mediaType = MediaType.parse("text/plain");
RequestBody body = new MultipartBody.Builder().setType(MultipartBody.FORM)
.addFormDataPart("job_id","z5G7h3l6a1kMvyS65NP3c0a2-MRSuDJL0EWa7zDjsGs=")
.addFormDataPart("firstname","Jhon")
.addFormDataPart("lastname","Doe")
.addFormDataPart("email","john.doe#gmail.com")
.addFormDataPart("city","Dallas")
.addFormDataPart("state","TX")
.addFormDataPart("country","US")
.addFormDataPart("mobile_number","555-5555")
.addFormDataPart("file_name","jd.pdf")
.addFormDataPart("resume","/C:/Users/test/Downloads/test.pdf",
RequestBody.create(MediaType.parse("application/octet-stream"),
new File("/C:/Users/test/Downloads/test.pdf")))
.build();
Request request = new Request.Builder()
.url("https://api.ceipal.com/xx-yy-zzz/ApplyJobWithOutRegistration")
.method("POST", body)
.build();
Response response = client.newCall(request).execute();
This results in these calls in the interceptor:
url: https://api.ceipal.com/xxx-yyy-zzz/ApplyJobWithOutRegistration
method:POST
header:Content-Type: multipart/form-data; boundary=21938c2b-0d98-4851-8532-a91ba219491d
Content-Length: 157614
Host: api.ceipal.com
Connection: Keep-Alive
Accept-Encoding: gzip
User-Agent: okhttp/4.9.1
url: https://api.ceipal.com/xxx-yyy-zzz/ApplyJobWithOutRegistration/
method:GET
header:Host: api.ceipal.com
Connection: Keep-Alive
Accept-Encoding: gzip
User-Agent: okhttp/4.9.1
as the redirect replaces the POST with GET the call responds with this error:
Error:{"detail": "Method "GET" not allowed."}
When I try this call in Postman,
Without the setting I get a response: Error:{"detail": "Method "GET" not allowed."}
With the setting turned on - {"status": 201, "success": 0, "message": "You have already applied for this job."}

RestTemplate returns 401 while Postman succeeds

I am trying to do post request to a rest service (https).
Everything works fine in postman although RestTemplate.exchange always returns 401 - unauthorized.
The body and the headers are the same.
HttpHeaders httpHeaders = new HttpHeaders();
httpHeaders.add("client_id", clientId);
httpHeaders.add("api_key", authToken);
// httpHeaders.add("Authorization", "Basic " + authToken); - also tried
HttpEntity<?> requestEntity = new HttpEntity<>(request, httpHeaders);
return restTemplate.exchange(getUrl(), httpMethod, requestEntity, responseType).getBody();
I've tried to skip ssl verification, also tried this solution: Spring Boot RestTemplate Basic Authentication using RestTemplateBuilder, it doesn't help.
Any ideas what I am missing?

How is HTTP Header set in Spring RestTemplate?

I wanted to get the plain string, not JSON. The code at client side:
HttpHeaders headers = new HttpHeaders();
headers.setAccept(Collections.singletonList(MediaType.TEXT_PLAIN));
HttpEntity<String> entity = new HttpEntity<String>("", headers);
RestTemplate restTemplate = new RestTemplate();
ResponseEntity<String> tickerResponse = restTemplate.exchange(serviceBase, HttpMethod.GET, entity,String.class);
It works well in local unit test. The log looks like:
08:24:46,291 DEBUG RestTemplate:598 - Setting request Accept header to
[text/plain, /]
However, it doesn't work in tomcat, the log was:
08:20:48,362 DEBUG RestTemplate:598 - Setting request Accept header
to [application/json, application/*+json, text/plain, /]
I guess RestTemplate set the Accept Header to JSON by default when running in my Tomcat 8. How to clean the default settings?

rest template returns 500 internal server error exception

I'm making an app and trying to get json written on the web page. So, I can see this page in browser: it contains only json.
But when I start a request with the RestTemplate it returns ma only 500 internal server error.
My caode is very simple:
RestTemplate restTemplate = new RestTemplate();
HttpHeaders requestHeaders = new HttpHeaders();
requestHeaders.setContentType(MediaType.APPLICATION_JSON);
HttpEntity<?> requestEntity = new HttpEntity<>(requestHeaders);
ResponseEntity<MyClass[]> responseEntity = restTemplate.exchange(url, HttpMethod.GET, requestEntity, MyClass[].class);
I cannot understand what is wrong: I have an access, it is simple, I'm not authentificated and I don't need id. Why an error?
The 500 Internal Server Error means something has gone wrong on the server side...
You should check your URL, parameter, cookies, etc... (in firebug by example)
I test your code and i got a 200 status on a valid URL.

Categories