Reputation: 4339
I'm running a spring app on JBoss to provide a REST interface to a database. When my front-end code tries to access the REST app, the request is cancelled because the server is not setting the Access-Control-Allow-Origin
header to permit the client to request the data. How can I set this either on the JBoss server or in the spring application? One of the controllers is shown below. I want this REST API to be open to the whole organisation so I just want to set the header to be '*'
.
package com.mycompany.esb.components.controllers;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.hateoas.Resource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import com.mycompany.esb.components.ResourceBuilder;
import com.mycompany.esb.jpa.dao.ServicesDAO;
import com.mycompany.esb.jpa.entity.ServicesEntity;
import static org.springframework.hateoas.mvc.ControllerLinkBuilder.linkTo;
import static org.springframework.hateoas.mvc.ControllerLinkBuilder.methodOn;
@Controller
@RequestMapping( value = "/services")
public class ServicesController extends BaseController {
/*
* Static final values for to limit size of result set
* for queries where no limits are set
*/
public static final String DAYS_PREVIOUS = "0.0";
public static final String HOURS_TO_SHOW = "2.0";
@Autowired
private ServicesDAO servicesDAO;
@Autowired
private ResourceBuilder resourceBuilder;
public void addLinks(List<ServicesEntity> services) {
resourceBuilder.addServiceLink(this, services);
}
public void addLinks(ServicesEntity service) {
resourceBuilder.addServiceLink(this, service);
}
@RequestMapping(value = "",
method = RequestMethod.GET,
produces = "application/json")
@ResponseBody
public Resource<List<ServicesEntity>> getAllServices(
@RequestParam(value = "daysPrevious", defaultValue = DAYS_PREVIOUS) double daysPrevious,
@RequestParam(value = "hoursToShow", defaultValue = HOURS_TO_SHOW) double hoursToShow) {
List<ServicesEntity> services = servicesDAO.getAllServices(daysPrevious, hoursToShow);
addLinks(services);
Resource<List<ServicesEntity>> toReturn = new Resource<List<ServicesEntity>>(services);
toReturn.add(linkTo(methodOn(ServicesController.class).getAllServices(daysPrevious, hoursToShow)).withSelfRel());
return toReturn;
}
}
Upvotes: 1
Views: 10593
Reputation: 1
This is exactly what helped me! I 've put a class in the default package. for example com.package:
package com.package
import org.springframework.context.annotation.Configuration;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* Created by GMiskos on 14/6/2017.
*/
@Configuration
public class CORSFilter implements Filter{
public void doFilter(ServletRequest req, ServletResponse res, FilterChain
chain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) res;
response.setHeader("access-control-allow-origin", "*");
response.setHeader("Access-Control-Allow-Credentials", "true");
response.setHeader("Access-Control-Allow-Methods", "POST, GET,
OPTIONS, DELETE, HEAD, PUT");
response.setHeader("Access-Control-Max-Age", "3600");
//response.setHeader("Access-Control-Allow-Headers", "Content-
Type, Accept, X-Requested-With, remember-me");
response.setHeader("Access-Control-Allow-Headers", "Origin,
Accept, X-Requested-With, Content-Type, Access-Control-Request-Method,
Access-Control-Request-Headers");
chain.doFilter(req, res);
}
public void init(FilterConfig filterConfig) {
}
public void destroy() {
}
}
In my web.xml at the end befaure closing tag (..maybe it's important)
<filter>
<filter-name>cors</filter-name>
<filter-class>com.package.CORSFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>cors</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
and finally i added exactly this dependencies in to my pom.xml
<!-- servlet dependencies -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.0.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>jsp-api</artifactId>
<version>2.2</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.el</groupId>
<artifactId>javax.el-api</artifactId>
<version>2.2.4</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
Upvotes: 0
Reputation: 4339
This solution worked for me
Put this filter in web.xml
for my app:
<filter>
<filter-name>cors</filter-name>
<filter-class>com.mycompany.components.CorsFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>cors</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
Add this class to my application, referenced by the filter above:
package com.mycompany.components;
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletResponse;
public class CorsFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
HttpServletResponse response = (HttpServletResponse) servletResponse;
response.setHeader("Access-Control-Allow-Origin", "*");
response.setHeader("Access-Control-Allow-Credentials", "true");
response.setHeader("Access-Control-Allow-Methods", "GET, HEAD, OPTIONS, POST, PUT");
response.setHeader("Access-Control-Allow-Headers", "Origin, Accept, X-Requested-With, Content-Type, Access-Control-Request-Method, Access-Control-Request-Headers");
filterChain.doFilter(servletRequest, servletResponse);
}
@Override
public void destroy() {
}
}
Upvotes: 4
Reputation: 11643
You can use a filter in your Spring app, something like this:
@Component
public class CorsFilter extends OncePerRequestFilter {
@Override
protected void doFilterInternal(HttpServletRequest request,
HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
if(request.getHeader("Access-Control-Request-Method") != null
&& "OPTIONS".equals(request.getMethod())) {
response.addHeader("Access-Control-Allow-Origin", "*");
response.addHeader("Access-Control-Allow-Methods", "comma sep list of methods you want to support");
//additional Access-Control-* like Allow-Headers, Max-Age,...
...
}
filterChain.doFilter(request, response);
}
}
and the corresponding DelegatingFilterProxy
<filter>
<filter-name>corsFilter</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
Upvotes: 0