Request mapping in Spring boot with url-encoded characters - spring-boot

In my Spring Boot application I have an URL concatenated from values that go from client side, for example:
/api/foo/{client-defined-value}/bar/
and the real URL can be something like this:
/api/foo/OBCH.%20Z%C3%81STUPCI/bar/
(not url encoded value is "OBCH. ZÁSTUPCI")
In a controller I have definition of GET request mapping:
#GetMapping(value = "/foo/{value:[^\\/]+}/bar/")
but the mapping is not found:
No mapping found for HTTP request with URI...
What am I doing wrong?

You can acces the URL variable by using the annotation #Pathvariable("client-defined-value") as a method argument.
Like so:
#RequestMapping(value = "/api/foo/{client-defined-value}/bar/")
public void foo(#PathVariable("client-defined-value") String value) {
doSomething…
}

Related

How can i explicitly check request content-type is matching with actual content in Spring boot?

I want to validate my request content-type is matching with my request body or not?
I am trying to implement the OWASP Rest security standard.
Which says :
13.2.5 Verify that REST services explicitly check the incoming Content-Type to be the expected one, such as application/XML or application/JSON.
In the below image the content type is JSON but the request is in XML.Still it's working fine.
My Controller code:-
#RestController
public class TestController {
#PostMapping(path="/hello",consumes = "application/json")
public Map<String,String> hello(Master ecm){
Map<String,String> m=new HashMap<>() ;
m.put("message", "hello!");
return m;
}
}
Spring annotations provide a specific attribute for that. It is called consumes.
Here is an example
#PostMapping(consumes = MediaType.SELECT_TYPE_HERE)
specific example
#PostMapping(consumes = MediaType.APPLICATION_JSON_VALUE)

How to capture a common request parameter for all requests in spring BOOT REST

In Jersey Rest API
if any common request parameters are there then we can capture that value at RootResource level using the below code.
#QueryParam("q")
private String qQueryParams
Is there any similar approach in Spring Rest API.
In other words, all my endpoint URL will contain the query parameter "q". How to capture this data at class level instead of every request.
Thanks, Vijay
you can use #RequestMapping({q}/test) above controller and pass #PathVariable String q as method argument.
#Controller
#RequestMapping(value = "{q}/test")
class TestController {
#RequestMapping(value="/abc")
public ModelAndView doSomething(#PathVariable String q) {
// do something with q...
}
}

Using Swagger(2.9.2) in GET operation in a SpringBoot #RestController that takes a #queryParam(optional parameter)

#ApiOperation(value = "Get list of Emp", response = ResponseEntity.class)
#GetMapping(path = "/getEmployees")
public ResponseEntity<Set<Employees>> getEmployees(#QueryParam("emp") String lastName) {}
**I have a GET operation in a SpringBoot #RestController that takes a query param. If I use Swagger UI, it throws an error that TypeError: Request has method 'GET' and cannot have a body. But if I change it to post it works considering the body is allowed in POST calls. How should I access query param in GET inside swagger? Not using curl. if I use Use Spring's RequestParam instead of Jersey QueryParam, it's no more optional, which I do not want **

REST API endpoint selection in Spring Boot

Given a controller like this:
#RestController
#RequestMapping("/cars") {
public class CarController{
#RequestMapping(method = RequestMethod.GET)
public ResponseEntity<List<Cars>> getCars() { //logic }
#RequestMapping(method = RequestMethod.GET")
public ResponseEntity<List<Cars>> searchCar(#RequestParam("name") String name, #RequestParam("value") String value) { //logic}
}
If the url is like this localhost/cars I would like to access the getCars() method.
But if the url is :
localhost/cars?name=something&value=100 or
localhost/cars?name=something or
localhost/cars?value=100
I would like the second method to be accessed.
Is this possible to do?
You are still asking for the same list of resources, cars, only thing is that you are adding a filter or search / query criteria.
It would be beneficial to develop a query filter / criteria to support something like:
/cars?q=make+eq+acura (meaning make=acura)
/cars?q=price+lt+25000 (meaning price <25000)
and so on.
No it is not possible. because when a request comes to container then it will 1st scan all the URL and check uniqueness of the URL. If there is duplicate URL present then container will throws exception.
In your case you are using class level URL mapping, but you are not using method level URL mapping.
To access your getCars() method you need to use some URL like below
#RequestMapping(value = "/", method = RequestMethod.GET)
To access your 2nd method you need to use another mapping URL
#RequestMapping(values="/test", method = RequestMethod.GET")
You can't access
localhost/cars?name=something&value=100 or
localhost/cars?name=something or
localhost/cars?value=100
as you are using 2 parameters like #RequestParam("name") String name, #RequestParam("value") String value
you need to pass two parameter in your url like below
localhost/cars/test?name=something&value=100
if you don't want to pass any of two parameter then just pass it as null and check it inside your method

Spring Boot MVC request mapping overrides static resources

I want to have rest controller in Spring Boot to handle all requests like this: "/{arg}", EXCEPT "/sitemap.xml". How can I achieve that?
You could specify your request mapping on the controller level via regex and exclude some resources (e.g. 'excludeResourceA' and 'excludeResourceB') with:
#RestController
#RequestMapping(value = "/{arg:(?!sitemap.xml|excludeResourceA|excludeResourceB).*$}")
public class YourRestController {
// your implementation
}
Of course you can also specify the request mapping on the method level with the same regex relative to your controller path matching and you can pass the argument with #PathVariable("arg") String arg in your method signature to your method body if you need it.

Resources