Url in a path variable spring restful service - spring

When I am passing email address as path variable it is throwing following error
Console --> 2015-02-09 16:30:06,634 WARN - GET request for "http://localhost:8181/abc/users/testabghtmail#gmail.com" resulted in 406 (Not Acceptable); invoking error handler
Exception in thread "main" org.springframework.web.client.HttpClientErrorException: 406 Not Acceptable
at org.springframework.web.client.DefaultResponseErrorHandler.handleError(DefaultResponseErrorHandler.java:91)
at org.springframework.web.client.RestTemplate.handleResponseError(RestTemplate.java:607)
at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:565)
at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:521)
at org.springframework.web.client.RestTemplate.exchange(RestTemplate.java:439)
at RestClient.main(RestClient.java:35)
I have tried lots of cases, so I finally found the problem with last domain like .com and .org which are internationalize domains. So instead of "testabghtmail#gmail.com" if I pass "testabghtmail#gmail.dom" it will work perfectly fine.
My code is
#RequestMapping(value = "users/{emailId:.*}", method = RequestMethod.GET)
public Object searchUser(#PathVariable("emailId") String emailId){
logger.info("Inside search user --> emailId " + emailId);
return userService.findUserByuserId(emailId);
}

I found no answer to this. I think it's an http rule we can't have domains at last in prameters and can make a request.
So work around to this is just pass a slash at the end of the url and there you go.
Like modify "http://localhost:8181/abc/users/testabghtmail#gmail.com/" with "http://localhost:8181/abc/users/testabghtmail#gmail.com". And thanks to spring rest architecture, it will automatically omit the last slash and you will get "testabghtmail#gmail.com" as a parameter value.
Let me know if you guys find something else.

Related

How to handle invalid/extra special characters & = in request url-SpringBoot?

I have a Rest service where get call if I send multiple invalid/extra & and = characters then also my endpoint does not throw any error. I would like to throw back invalid request error if url contains any extra special character like & or =.
for example:
http://localhost:8080/myservice?rollNo=03456789321&school=Myschool //This is Okay for me
http://localhost:8080/myservice?rollNo=03456789321&school= //should throw error as school is not having value
http://localhost:8080/myservice?rollNo=03456789321&&&&school=Myschool
//should throw error as &&&& is multiple where it should only one
http://localhost:8080/myservice?rollNo=03456789321&= //should throw error as &= is there at end having no sence.
Note that , I am hitting these request from postman , and I have doubt that postman do something with these parameters, cause I am not able to find these extra characters in spring boot while debugging.
Any way through which i can get whole request url in my controller so that I can find out for these charecters comming?
Any built in springboot annotation is there to handle such a cases?
I got my problem solved.
After lot of research , and some observation I came to know that when you pass any number of characters among & and = in request url, the rest client tools like postman , or advanced rest client will refine the url before hitting actual server and remove those extra un-necessary characters. SO if you write multiple &&&& or == charecters in url , it will consider each extra & as blank parameter and will ignore while sending final request, only of those characters which has parameter names besides it it will taken as part of refined request.
you can see in screenshot bellow:
You can Use #RequestParam in your Spring Boot rest Controller
Something of the following
#GetMapping(value = "/myservice")
public boolean doSomething(#RequestParam("rollNo") Integer rollNo , #RequestParam("school") String school) {
doValidation(rollNo,school);
// Do Something
return true;
}
#RequestParam will make sure that your Url need to have these Params rollNo & school. Without it it will throw error.
But if you were to pass an empty string like &school= in your second example. The controller will get an empty String.
You can add a basic validation layer right before you do anything in you controller to handle this condition.

How to get the current Request Mapping URL configured at Controller layer when request is executed?

I went through so many links like How to show all controllers and mappings in a view and How to configure a default #RestController URI prefix for all controllers? and so on.
I want to get the Request Mapping URL at Filter interceptor
Ex: This URL I configured at REST controller method, and naturally we will pass /employees/employee-names/John to get the Employee John.
/employees/employee-names/{employee_name}
Now, when somebody hit /employees/employee-names/John I want to get the value of actual mapping url if REST controller /employees/employee-names/{employee_name},
Any pointers how to get that ?
Spring MVC sets the attribute HandlerMapping.BEST_MATCHING_PATTERN_ATTRIBUTE, which you can use to get the pattern that was used to match the incoming request:
String matchingPattern = (String) request.getAttribute(HandlerMapping.BEST_MATCHING_PATTERN_ATTRIBUTE)
That would return /employees/employee-names/{employee_name} in your case.
I was able to solve this issue using below code. AntPathMatcher is the perfect way to identify if the incoming request and URL you configured in the property file matches exactly. This solution works greatly for me.
AntPathMatcher springMatcher = new AntPathMatcher();
Optional<String> antMatch = props.getMapping().stream()
.filter(//Perform Some Filter as per need)
.map(Mapping::getVersion)
.findFirst();
return antMatch.isPresent() ? antMatch.get() : null;

Mapping of missing URI variables to Request Mapping

I've developed a Spring API /getFileData, which accepts three URI parameters viz. businessDate/fileName/recordId. It is possible to have any of them can be passed as null. But I still want my API to be working in this case also. How can I achieve this?
I've tried using #GetMapping("getFileData/{businessDate}/{fileName}/{recordId}", "getFileData/{businessDate}//", "getFileData/{businessDate}/{fileName}/")..so on like this for all possible combinations.
#RequestMapping(value = "/getFileData/{businessDate}/{fileName}/{recordId}", method = RequestMethod.GET)
I want this API to be working for all the combination of URI parameters if something get missed out. for example someone requested,
/getFileData///22 or
/getFileData/22Dec2018/ or
/getFileData//treasure/22
You can do that with a #RequestParam of type java.util.Map.
With your design, you will have various #PathVariable params in the controller method as well as the order of path variables /{var1}/{var2}... constructs the url so I don't think it would be possible to skip a path variable in the url and still call the same controller method.

How to get URL before redirect to error page?

I have been trying to get the URL which was typed wrongly by user before redirection to the custom error page.
Below is what I have but I don't see a way to get the wrong URL from the request variable
#RequestMapping(value = "/errors/404.html")
private String defaultPage(HttpServletRequest request,Exception e){
request.getRequestURL().toString(); // this prints /error/404.html
...
...
}
I expect to see URL something like www.example.com/home2 which was keyed in by the user. However when I debug I can see the following
How do I retrieve the /home2 from the request ?
You can use a RequestContextListener to get the request bound to the current Thread.
Check this answer:
What's the best way to get the current URL in Spring MVC?

Spring MVC - HTTP status code 400 (Bad Request) for missing field which is defined as being not required

I have Spring MVC application with this controller method.
#RequestMapping(value = "/add", method = RequestMethod.POST)
public String addNumber(#RequestParam(value="number", required=false) Long number) {
...
return "redirect:/showAll/";
}
In my JSP I have a standard HTML form which is posting a value named "number" to the controller method above. However, if I leave out the value (do not enter anything into the text field) and POST the data to the controller, before the controller method is called my browser shows
HTTP Status 400 - Required Long parameter 'number' is not present
although the controller method annotation clearly defines the "number"-parameter as not required.
Does anyone have a slight idea of what could be going on?
Thank you.
PS: The exception that is being thrown is as follows:
org.springframework.web.bind.MissingServletRequestParameterException: Required Long parameter 'number' is not present
EDIT: This is a Spring 3.2.3.RELEASE bug ( see here). With version 3.1.4.RELEASE I do not have this problem anymore.
I came across the same situation, and this happens when your parameter is present in the request with an empty value.
That is, if your POST body contains "number=" (with empty value), then Spring throws this exception. However, if the parameter is not present at all in the request, it should work without any errors.
My problem was that some of the headers in a request I was sending with Postman were not present (were unchecked):
When I checked back the Content-Length header, the request worked fine (200 OK response).

Resources