I'm trying to make a cross-origin request using Spring's RestTemplate. The communication is done between two Spring-boot webapps, both running on localhost but different port. What I do is:
HttpHeaders httpHeaders = new HttpHeaders();
httpHeaders.setOrigin("http://localhost:8083");
httpHeaders.add("Authorization", token);
HttpEntity<Void> httpEntity = new HttpEntity<>(httpHeaders);
ParameterizedTypeReference<List<MyObj>> beanType = new ParameterizedTypeReference<List<MyObj>>() {};
ResponseEntity<List<MyObj>> list = restTemplate.exchange(serviceURL, HttpMethod.GET, httpEntity, beanType);
The call is executed, the "Authorization" header is passed just fine, but no matter what I try, there is no "Origin" header on the receiving side. When I create a simillar request using some other tool (SoapUI, RestClient Chrome plugin, etc.) the header is passed just as I provide it.
To print all headers on the receiving side I'm using a implementation of javax.servlet.Filter with:
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) res;
Enumeration<String> headerNames = request.getHeaderNames();
while (headerNames.hasMoreElements()) {
String headerName = headerNames.nextElement();
log.info(headerName + ": " + request.getHeader(headerName));
}
}
Why is the origin header not passed when using RestTemplate?
Had the same problem which I spent a century to fix.
The root cause is this line from the RestTemplate documentation
Note: by default the RestTemplate relies on standard JDK facilities to establish HTTP connections.
If you check source code of HttpUrlConnection
class in Java, you'll find below block of code, and header Origin
is one of the restricted headers that forbid changes:
/*
* Restrict setting of request headers through the public api
* consistent with JavaScript XMLHttpRequest2 with a few
* exceptions. Disallowed headers are silently ignored for
* backwards compatibility reasons rather than throwing a
* SecurityException. For example, some applets set the
* Host header since old JREs did not implement HTTP 1.1.
* Additionally, any header starting with Sec- is
* disallowed.
*
* The following headers are allowed for historical reasons:
*
* Accept-Charset, Accept-Encoding, Cookie, Cookie2, Date,
* Referer, TE, User-Agent, headers beginning with Proxy-.
*
* The following headers are allowed in a limited form:
*
* Connection: close
*
* See http://www.w3.org/TR/XMLHttpRequest2.
*/
private static final boolean allowRestrictedHeaders;
private static final Set<String> restrictedHeaderSet;
private static final String[] restrictedHeaders = {
/* Restricted by XMLHttpRequest2 */
//"Accept-Charset",
//"Accept-Encoding",
"Access-Control-Request-Headers",
"Access-Control-Request-Method",
"Connection", /* close is allowed */
"Content-Length",
//"Cookie",
//"Cookie2",
"Content-Transfer-Encoding",
//"Date",
//"Expect",
"Host",
"Keep-Alive",
"Origin",
// "Referer",
// "TE",
"Trailer",
"Transfer-Encoding",
"Upgrade",
//"User-Agent",
"Via"
};
There is a easy fix to this problem, just to set a JVM argument
-Dsun.net.http.allowRestrictedHeaders=true
or add a line in your code
System.setProperty("sun.net.http.allowRestrictedHeaders", "true");
which suppress the restriction.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With