IllegalArgumentException: The HTTP header line does not conform to RFC 7230 when POST-accessing Spring Controller - spring

I want to implement a user registration functionality with Spring. When I try to POST the data to the spring controller, the exception above is thrown. Surprisingly, GET Requests work on the controller.
#RestController
#RequestMapping(RestApi.ANONYMOUS + "register")
public class RegisterController {
#PostMapping(value="/new", consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE)
public UserRegistrationResultDto registerUser(#RequestBody UserRegisterDto dto) {
UserRegistrationResultDto result = registerService.registerUser(dto.getMail(),
dto.getPassword(), dto.getRepeatedPassword());
return result;
}
#GetMapping("/test")
public String test() {
return "get success";
}
}
The request that fails with error code 400 is the following:
POST http://localhost:8080/api/anonymous/register/new
Content-Type:application/x-www-form-urlencoded
{
mail=data&password=data&passwordRepeated=data
}
It throws the following exception:
java.lang.IllegalArgumentException: The HTTP header line [{: ] does not conform to RFC 7230 and has been ignored.
This get request however works:
GET http://localhost:8080/api/anonymous/register/test
I am using Tomcat 9 as a server.

Not sure how the POST request is submitted...but a space after : is required for HTTP header fields:
Content-Type: application/x-www-form-urlencoded

Related

Request method 'POST' not supported in Postman

I have created this controller
#PostMapping(value = "/validate")
public ResponseEntity<GenericResponse> validate(#RequestBody #Valid FormulaDTO formulaDto) {
System.out.println(formulaDto);
String expression = formulaDto.getFormula();
service.validate(expression);
return new ResponseEntity<>(new GenericResponse(HttpStatus.CREATED.value(), "Expression Validated"),
HttpStatus.CREATED);
}
The FormulaDTO looks like
public class FormulaDTO {
private String formula;
}
I have created a PostRequest from postman whose body contains the formulaText.
The api call from postman looks like
https://localhost:8443/validate
with body as
{
"formula" :"M00212=curr_month:M00213-curr_month:M00211*100.00"
}
I am getting the following as output with 500 Internal Server Error
{
"timestamp": "2021-05-03",
"message": "Request method 'POST' not supported",
"details": "uri=/error"
}
How can i use PostMapping?
Use http instead of https in postman.
Instead of this: https://localhost:8443/validate
Use this: http://localhost:8443/validate
Looking at the comments
There is no root level mapping at #RestController .
Even if you don't have a root level mapping on controller it seems that spring boot always needs the following annotation on controller level
#RequestMapping
Add it and it will be fixed!

Zuul proxy server throwing Internal Server Error when request takes more time to process

Zuul Proxy Error
I am getting this error when the request takes more time to process in the service.But Zuul returns response of Internal Server Error
Using zuul 2.0.0.RC2 release
As far as I understand, in case of a service not responding, a missing route, etc. you can setup the /error endpoint to deliver a custom response to the user.
For example:
#Controller
public class CustomErrorController implements ErrorController {
#RequestMapping(value = "/error", produces = "application/json")
public #ResponseBody
ResponseEntity error(HttpServletRequest request) {
// consider putting these in a try catch
Integer statusCode = (Integer)request.getAttribute("javax.servlet.error.status_code");
Throwable exception = (Throwable)request.getAttribute("javax.servlet.error.exception");
// maybe add some error logging here, e.g. original status code, exception, traceid, etc.
// consider a better error to the user here
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("{'message':'some error happened', 'trace_id':'some-trace-id-here'}");
}
#Override
public String getErrorPath() {
return "/error";
}
}

Using Jersey's #BeanParam results in a 415 error

I am trying to use Jersey's #BeanParam annotation the following way:
This is my bean:
public class BeanParamModel {
#QueryParam(value = "param1")
private String param1;
public BeanParamModel(#QueryParam("param1") String param1) {
this.param1 = param1;
}
public String getParam1() {
return param1;
}
public void setParam1(String param1) {
this.param1 = param1;
}}
And this is the resource method that needs to use it:
#Consumes("*/*")
#Path("mypath")
#GET
public Response getUpgradeStatus(#QueryParam("param1") String param1, #BeanParam BeanParamModel user) {
return Response.ok().build();
}
Now I want to test this using a unit test which sends an http request to a test server with the following url:
GET http://path_to_resource?param1=1
My problem is that results in a 415 response with Jersey printing this message:
A message body reader for Java class BeanParamModel, and Java type class BeanParamModel, and MIME media type application/octet-stream was not found.
The registered message body readers compatible with the MIME media type are:...
I've trying adding a "application/x-www-form-urlencoded" header but the message repeats for that header type as well. I also tried using an application/json header, this results in EOF expection from the jackson mapper due to end of input.
Can anyone tell me what I'm not doing correctly? from the jersey documentation of #BeanParam it seems pretty simple.
With a #GET you should not have #Consumes.

get error HTTP Status 405 for rest web service POST method

I load at browser as
localhost:8080/picking/addPick get error HTTP Status 405 - Request method 'GET' not supported.
What wrong?Hope advice thanks
#Controller
#RequestMapping("/picking")
public class PickerController {
#RequestMapping(method = RequestMethod.GET)
public #ResponseBody ArrayList getAllPickingItems()throws SQLException, ClassNotFoundException{
//....
}
#RequestMapping(value="/addPick",method=RequestMethod.POST)
#ResponseStatus(HttpStatus.CREATED)
public Boolean add(#RequestBody PickingInfo pickingInfo,HttpServletResponse response){
try{
Boolean success = pickerMethod.addPickingInfo(pickingInfo);
response.setHeader("addPickingInfo", success+"");
return true;
}catch(Exception ex){
System.out.println(ex.getMessage());
}
return false;
}
}
You limited URI/picking/addPick to POST requests :
#RequestMapping(value="/addPick",method=RequestMethod.POST)
When you try to open that URI from your browser you're sending a GET request, not a POST. If you want to be able to access /picking/addPick from your browser you must either :
remove the restriction method=RequestMethod.POST
allow explicitely GET requests : method = { RequestMethod.POST, RequestMethod.GET }
If you just want to test a POST method, use SoapUI. Simply create a "New REST Project", paste your service URI, and send any type of HTTP Request you want.
You have mapped /addPick to the add method only for POST requests. Therefor GET is not mapped to anything (and in this case there is no point in mapping get to the method since you are also using #RequestBody)

Spring test-mvc PUT not supported

This is my Controller method:
#RequestMapping(method = RequestMethod.PUT,produces="application/json", headers = "content-type=application/json")
public #ResponseBody User updateUser(#RequestBody User user) throws PropertyErrorException, ItemNotFoundException {
return service.UpdateUser(user);
}
Using Spring test-mvc I would like to write a unit test case:
#Test
public void UpdateUser() throws Exception {
mockMvc.perform(put("/r01/users").body(userJsonString.getBytes())
.accept(MediaType.APPLICATION_JSON))
.andExpect(status().isOk())
.andExpect(content().type(MediaType.APPLICATION_JSON))
.andExpect(content().string(userString));
}
Running this test case generates:
WARN org.springframework.web.servlet.PageNotFound - Request method 'PUT' not supported
Also, updateUser method is never called and the response code is 405.
I have written a lot of tests, all GET requests, and they are working correctly. This means that I am confident in ContextConfiguration. What have I missed?
You are explicitly expecting a header of content-type in your #RequestMapping method but not sending the content type in your request, I think that is the reason why the request is failing..try this.
mockMvc.perform(put("/r01/users").contentType(MediaType.APPLICATION_JSON).body(userJsonString.getBytes())
.accept(MediaType.APPLICATION_JSON))
.andExpect(status().isOk())
.andExpect(content().type(MediaType.APPLICATION_JSON))
.andExpect(content().string(userString));

Resources