Spring Annotation-Based Interceptor - spring

can any of you please post a snippet for the following. I've looked in a couple of places but they all seem to be xml based. I'd like to have this code in java configuration style only.
I am trying to accomplish the following..
1) I need to intercept a specific url, for example "http://localhost:8080/test" and only a url that starts with "/test/*". This is not a spring security question, this is just for an endpoint I like to intercept.
2) I need to intercept the HttpServletRequest object of that request and add a specific header to that request. For example, "authorization", "bearer xxxx".
3) When the /test endpoint finally hits, I should be able to see the authorization header inside my HttpServletRequest object.
Thank you guys.

you can do this like this:
(Whithin "YourOwnInterceptor" you can add the value to the header...)
#Configuration
public class MvcConfig extends WebMvcConfigurerAdapter {
#Bean
public YourOwnInterceptor yourOwnInterceptor() {
return new YourOwnInterceptor();
}
#Override
public void addInterceptors(InterceptorRegistry registry) {
super.addInterceptors(registry);
registry.addInterceptor(yourOwnInterceptor()).
addPathPatterns("/<your-url-to-intercept>/**");
}
}

Related

How to get Application properties configuration into Annotation as parameter

I want to use #CrossOrigin annotation on my RestController in my Spring Boot application and set origins parameter with the values from application.properties file.
#CrossOrigin(origins = {"${app.cors.origins}"})
public class SomeController(){
//
//
}
I set the property in my application.properties file like
app.cors.origins =http://www.google.com,http://localhost:8001
However that doesn't work as a cross origin request from http://localhost:8001 to my app fails with CORS error on the browser.
Am I missing something on setting the property?
Update : Problem is to set origins as a string array from the value of application property entry. When I hardcode the urls in origin, it works.
Thanks
If you want to use application.properties to set origins of CORS then this is the solution.
#Configuration
public class WebMvcConfig implements WebMvcConfigurer {
#Value("${app.cors.origins}")
private String corsAllowedOrigins;
#Value("${app.cors.methods}")
private String corsAllowedMethods;
#Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOrigins(corsAllowedOrigins)
.allowedMethods(corsAllowedMethods);
}
application.properties
app.cors.origins=http://www.google.com,http://localhost:8001
app.cors.methods=GET,OPTIONS
I'm also working on this issue, I found another post mentioned about controller level parameter annotation for Cors. I haven't try it yet. share it with you:
Create your custom annotation and annotate the API with that.
#Retention(RetentionPolicy.RUNTIME)
#Target({ElementType.METHOD})
#CrossOrigin
public #interface CrossOriginsList {
public String[] crossOrigins() default {
"http://domain1.com", "http://domain1.com"
"http://domain1.com", "http://domain1.com"
// Pass as many as you want
};
}
And now Annotate your API with this custom Annotation
#CrossOriginsList
public String methodName() throws Exception
{
//Business Logic
}

Simple Reverse Proxy with Spring Boot and Netflix Zuul

I'm looking to implement a simple reverse proxy with Spring Boot that is:
Easy to add routes
Ability to add custom authentication on a per route basis
Add additional headers as needed
I've looked at the facilities provided by the #EnableZuulProxy annotation but it seems too heavyweight as I don't have a desire to use Eureka, Ribbon, or Hystrix. However, #EnableZuulServer is a bit light on configuration.
Would anyone be able to provide an example of what I'm after? Is Netflix Zuul the right choice for this or is there another library I should be looking at?
Thanks!
Simple Reverse Proxy Server
It's easy to set up a simple proxy reverse using Spring Boot without Ribbon, Eureka, or Hystrix.
Simply annotate your main application class with #EnableZuulProxy and set the following property in your configuration:
ribbon.eureka.enabled=false
Then define your routes in your configuration like such:
zuul.routes.<route_name>.path=<route_path>
zuul.routes.<route_name>.url=http://<url_to_host>/
where <route_name> is an arbitrary name for your route and <route_path> is a path using Ant-style path matching.
So a concrete example would be something like this
zuul.routes.userservice.path=users/**
zuul.routes.userservice.url=http://localhost:9999/
Custom Filters
You can also implement your custom authentication and any additional headers by extending and implementing the ZuulFilter class and adding it as an #Bean to your #Configuration class.
So another concrete example:
public class MyFilter extends ZuulFilter {
#Override
public String filterType() {
// can be pre, route, post, and error
return "pre";
}
#Override
public int filterOrder() {
return 0;
}
#Override
public boolean shouldFilter() {
return true;
}
#Override
public Object run() {
// RequestContext is shared by all ZuulFilters
RequestContext ctx = RequestContext.getCurrentContext();
HttpServletRequest request = ctx.getRequest();
// add custom headers
ctx.addZuulRequestHeader("x-custom-header", "foobar");
// additional custom logic goes here
// return isn't used in current impl, null is fine
return null;
}
}
and then
#Configuration
public class GatewayApplication {
#Bean
public MyFilter myFilter() {
return new myFilter();
}
}
Zuul is a good choice. Am not sure about other alternatives but, we've started building Zuul filters (Pre/Post and Route) that could intercept the request and do all pre/post processing and route based upon your need. It is not mandatory to use the whole bunch of Eureka, Ribbon and Hysterix along with Zuul.

Add interceptor to spring boot mongodb rest example

I am trying to add an interceptor to a simple Spring-boot-mongodb-rest app, as can be seen here : http://spring.io/guides/gs/accessing-mongodb-data-rest/, in order to perform certain actions after the default rest handler is invoked. Here is my MongoRepository, whose CRUD operation is called upon a POST request to the server:
#RepositoryRestResource(collectionResourceRel = "reminder", path = "reminder")
public interface ReminderRepository extends MongoRepository<Reminder, String> {
List<Reminder> findBySendee(#Param("sendee") String sendee);
}
I am trying to register an interceptor for all HTTP requests by extending the WebMvcConfigurerAdapter class like this:
#Configuration
#ComponentScan
public class RemindxWebConfig extends WebMvcConfigurerAdapter {
#Override
public void addInterceptors(InterceptorRegistry registry){
registry.addInterceptor(new RemindxInterceptor());
}
}
As mentioned in the spring boot docs, I have not added the #EnableWebMvc annotation to this. While running the application, the addInterceptors function does get called and adds the interceptor. However, the given interceptor is not called after the POST handler is invoked. I am unable to figure out a way to have spring use this RemindxWebConfig for all MongoRepository http requests. Any inputs are appreciated.

Spring defaultContentType ignored

I have a Spring 3.2.4 application with the following mvc setup:
#Configuration
public class WebConfig extends WebMvcConfigurationSupport {
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/assets/**").addResourceLocations("/assets/");
}
#Override
public void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
configurer.defaultContentType(MediaType.APPLICATION_JSON);
configurer.mediaType("json", MediaType.APPLICATION_JSON);
configurer.mediaType("xml", MediaType.APPLICATION_XML);
}
when I access my controller's url like /rest/products.json I get JSON response and via /rest/products.xml I get XML as expected.
But when I accesss /rest/products I get XML, but I expected JSON as I set that as default content type.
This seems to be ignored by Spring.
The Spring documentation says:
This content type will be used when neither the request path
extension, nor a request parameter, nor the Accept header could help
determine the requested content type.
So there are at least three ways to tell Spring which format you are trying to receive. My guess would be that you are still telling Spring somehow that you want to get the data in XML, maybe in a requests parameter or - more likely as it is not that visible - in a header.
Try checking the headers of your request.

Custom default headers for REST API only using Spring Data REST

I have a use case where my application hosts REST API and web application and we need to add custom header to REST APIs only. REST APIs are enabled through Spring Data REST. Typically we could use Servlet Filter to achieve this but we need code the logic of isolating requests to our REST API and add the custom headers. It would be nice if Spring Data REST API allows to add a default header to all the responses it generates. What are your thoughts? Don't say I am lazy :)
For folks looking for actual implementation details..
Interceptor
public class CustomInterceptor extends HandlerInterceptorAdapter {
#Override
public boolean preHandle(HttpServletRequest request,
HttpServletResponse response, Object handler) throws Exception {
System.out.println("adding CORS headers.....");
response.addHeader("HEADER-NAME", "HEADER-VALUE");
return true;
}
}
Java Configuration
#Configuration
public class RepositoryConfig extends
RepositoryRestMvcConfiguration {
#Override
public RequestMappingHandlerMapping repositoryExporterHandlerMapping() {
RequestMappingHandlerMapping mapping = super
.repositoryExporterHandlerMapping();
mapping.setInterceptors(new Object[] { new CustomInterceptor() });
return mapping;
}
}
As Spring Data REST is built on top of Spring MVC, the easiest way is to configure a custom HandlerInterceptor as described in the reference documentation.
With Spring Data REST the easiest way is to extend RepositoryRestMvcConfiguration and override repositoryExporterHandlerMapping, call the parent method and then invoke ….setInterceptors(…) on it.
Finally I managed to make the setup of custom interceptor working also on spring-data-rest 2.4.1.RELEASE.
#Configuration
public class RestMvcConfig extends RepositoryRestMvcConfiguration {
#Autowired UserInterceptor userInterceptor;
#Autowired ApplicationContext applicationContext;
#Override
public DelegatingHandlerMapping restHandlerMapping() {
RepositoryRestHandlerMapping repositoryMapping = new RepositoryRestHandlerMapping(resourceMappings(), config());
repositoryMapping.setInterceptors(new Object[] { userInterceptor }); // FIXME: not nice way of defining interceptors
repositoryMapping.setJpaHelper(jpaHelper());
repositoryMapping.setApplicationContext(applicationContext);
repositoryMapping.afterPropertiesSet();
BasePathAwareHandlerMapping basePathMapping = new BasePathAwareHandlerMapping(config());
basePathMapping.setApplicationContext(applicationContext);
basePathMapping.afterPropertiesSet();
List<HandlerMapping> mappings = new ArrayList<HandlerMapping>();
mappings.add(basePathMapping);
mappings.add(repositoryMapping);
return new DelegatingHandlerMapping(mappings);
}
}
I had to override the restHandlerMapping method, copy-paste it's content and add a line repositoryMapping.setInterceptors for adding custom interceptor, in my case the UserInterceptor.
Is there any better way?

Resources