I have a problem with processing params from curl request to my spring-boot app.
My controller post method:
#RequestMapping(value = "/cat", method = RequestMethod.POST, consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE)
public ResponseEntity addCat(#Valid #ModelAttribute NewCatRequest newCatRequest, BindingResult bindingResult) {
System.out.println( newCatRequest);
if (bindingResult.hasErrors()) {
return ResponseEntity.badRequest().body(bindingResult.getFieldError().getDefaultMessage());
}
int rowsAffected = catsRepository.saveCat(newCatRequest.getName(), newCatRequest.getColor(), newCatRequest.getTail_length(), newCatRequest.getWhiskers_length());
if (rowsAffected == 1) {
return ResponseEntity.ok().body(newCatRequest);
} else {
return ResponseEntity.badRequest().body("There was an unexpected error while trying to create cat for you :(");
}
}
And the problem is: when i'm trying to send this with curl:
curl -X POST http://localhost:8080/cat \
-d "{\"name\": \"Tihon\", \"color\": \"red & white\", \"tail_length\": 15, \"whiskers_length\": 12}"
I have all null params in 'newCatRequest':
NewCatRequest{name='null', color='null', tail_length=0, whiskers_length=0}
BUT when i'm trying to do the same with Postman (POST method, x-www-form-urlencoded in body with my params) i have a valid result:
Result from Postman
Help me pls to understand what's the problem.
curl -X POST http://localhost:8080/cat \
-d "{\"name\": \"Tihon\", \"color\": \"red & white\", \"tail_length\": 15, \"whiskers_length\": 12}"
The above curl request has a JSON body, whereas your request processing method
#RequestMapping(value = "/cat", method = RequestMethod.POST, consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE)
consumes/accepts: application/x-www-form-urlencoded. Therefore, you should either convert your method to consume/accept application/json or change your curl request to:
curl -X POST http://localhost:8080/cat \
-d 'name=Tihon&color=red%20%26%20white&tail_length=15&whiskers_length= 12' \
-H 'Content-Type: application/x-www-form-urlencoded'
EDIT 1
Please note that the default Content-Type for curl is application/x-www-form-urlencoded. To use JSON, change your request to:
curl -X POST http://localhost:8080/cat \
-d "{\"name\": \"Tihon\", \"color\": \"red & white\", \"tail_length\": 15, \"whiskers_length\": 12}" \
-H 'Content-Type: application/json'
Try this:
curl -X POST \
http://localhost:8080/cat \
-H 'Content-Type: application/x-www-form-urlencoded' \
-d 'name=Thidon&color=red%20%26%20white&tail_length=15&whiskers_length=12'
You forgot the header application/x-www-form-urlencodedand the body should not be in json format.
you can use the code option below send button in postman to generate the exact curl request which will work for you https://i.stack.imgur.com/hbk8M.png
in code drop down menu search for curl and it will generate a neat and clean curl request for you .
Hope this helps
Related
While doing a post request to the Spring Boot Rest API it is throwing Servlet Request Binding Exception with error message "Missing request header 'client_id' for method parameter of type String". Even after passing the client_id field in header.
It is happening in only one of our testing env. where request header is containing "_" underscore in its name. Same code is working in local. What could be the issue here. Is it something related to deployment file or code related issue.
curl --location --request POST 'http://localhost:7087/test' \
--header 'accept: application/json' \
--header 'client_id: test' \
--header 'Content-Type: application/json' \
--data-raw '{
"data": "test"
}'
#PostMapping(path = "/test", consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)
public Object pushMsg(#Valid #RequestBody String data,
#RequestHeader("client_id") String clientId) {
return null;
}
I'm trying to create a method that either receives a JSON or a .csv file in order to populate a database. It goes like:
#RequestMapping(method = RequestMethod.POST,
consumes = {"multipart/form-data","application/json"})
public ResponseEntity<PeopleResponse> create(
#RequestBody People PeopleDTO,
#RequestParam(name = "csvFile", required = false) MultipartFile csvFile,
HttpServletRequest request)
When I try it with Postman with a json sending:
curl --location --request POST 'localhost:9001/people' \
--header 'Authorization: Bearer eyJhbGciOiJIUzUxMiJ9.eyJzdWIiOiJtcmVnYWxhZG8iLCJhdXRob3JpdGllcyI6eyJsb2dpbiI6IjEiLCJnb2RNb2RlIjoiMSIsInJlZ2lzdGVyIjoiMSJ9LCJzYWx0IjoxNTg5NTg2ODgwMzI1LCJzb3VyY2UiOiJsb2NhbGhvc3QifQ.DrdUC7JN-Db0-_6qNGn9i5n3YzVopGNisecLy08SvMCudmveZnwATRwMftf2VKBZqhUKdQIrJGsNXudU1uwTgA' \
--header 'Content-Type: application/json' \
--data-raw '{
"name": "Homer",
"age": 25
}'
It works, but when I try it sending a csv file with Postman, it fails:
curl --location --request POST 'localhost:9001/people' \
--header 'Authorization: Bearer eyJhbGciOiJIUzUxMiJ9.eyJzdWIiOiJtcmVnYWxhZG8iLCJhdXRob3JpdGllcyI6eyJsb2dpbiI6IjEiLCJnb2RNb2RlIjoiMSIsInJlZ2lzdGVyIjoiMSJ9LCJzYWx0IjoxNTg5NTg2ODgwMzI1LCJzb3VyY2UiOiJsb2NhbGhvc3QifQ.DrdUC7JN-Db0-_6qNGn9i5n3YzVopGNisecLy08SvMCudmveZnwATRwMftf2VKBZqhUKdQIrJGsNXudU1uwTgA' \
--form 'csvFile=#/home/myself/Downloads/people.csv' \
It gives me the following error:
2020-10-05 15:09:20.602 WARN 13086 - [nio-9001-exec-3] s.w.s.h.AbstractHandlerExceptionResolver | Resolved [org.springframework.web.HttpMediaTypeNotSupportedException: Content type 'multipart/form-data;boundary=--------------------------276557520366487467828532;charset=UTF-8' not supported]
I'd like to know if it's possible to have either application/json or multipart/form-data in one method or if the only way is to make two separates methods (Though it ruins a little the naming, because second method would be like "POST people/by-file"
I am testing some code that has an annotation I haven't used before and reading the documentation seems like I should not even send any parameter to call it, but I might.
The endpoint looks like this:
#POST
#Path("/hello")
#Produces(MediaType.APPLICATION_JSON)
#Consumes(MediaType.APPLICATION_JSON)
public void postHello(
#Suspended final AsyncResponse asyncResponse,#QueryParam("dtd") String name, String obj) {
...
}
So by now I am using Postman or cURL and sending this:
curl -X POST \
'http://localhost:9000/hello?name=John' \
-H 'Accept: */*' \
-H 'Content-Type: application/json' \
-H 'Host: localhost:8080' \
-d '{}'
Unfortunately, I get an error 400 Bad Request
Any idea what header I am missing? or might be #Produces/#Consumes?
I'm using Spring boot 2.1.3-RELEASE. In my RestController I'm trying to set up a PUT method with one PathVariable and a RequestParam (application/x-www-form-urlencoded).
However when I call it the response is a bad request because the required RequestParam is not present.
I tried changing PutMapping to RequestMapping, swapping parameters position and using the syntax #RequestParam(value="param2", required=false) but nothing changes.
Curiously using PostMapping works. Also removing PathVariable works.
Here is the RestController code:
#PutMapping(value="/myurl/{param1}", consumes=MediaType.APPLICATION_FORM_URLENCODED_VALUE)
public String myMethod( #PathVariable("param1") Integer param1, #RequestParam("param2") String param2);
I call the method in this way:
curl -X PUT \
http://localhost:8080/myurl/42 \
-H 'Accept: application/json' \
-H 'Content-Type: application/x-www-form-urlencoded' \
-d 'param2=myparam2value'
The response is:
{
"timestamp": 1553613278534,
"status": 400,
"error": "Bad Request",
"message": "Required String parameter 'param2' is not present",
"path": "/myurl/42"
}
I expect that PUT works just like POST, but it seems not to.
Unfortunately I cannot send parameters as QueryParam, so I should maintain the same request call because I am refactoring an existing endpoint that works exactly this way.
Thanks
EDIT
I found this is caused by using an HandlerInterceptorAdapter (via WebMvcConfigurer).
For some reason, around
org.springframework.web.util.ContentCachingRequestWrapper.getParameterValues
org.apache.coyote.Request.parameters has no content and an exception is thrown, so it works only for POST and not for PUT (GET are handled differently).
I appreciate if someone can suggest if this can be reported as a bug considering that removing the interceptor made it work.
Regards
Use -G along with --data-urlencode:
curl -G -X PUT \
http://localhost:8080/myurl/42 \
-H 'Accept: application/json' \
-H 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'param2=myparam2value'
From the documentation:
-G, --get
When used, this option will make all data specified with -d, --data, --data-binary or --data-urlencode to be used in an HTTP GET request instead of the POST request that otherwise would be used. The data will be appended to the URL with a ? separator. [...]
--data-urlencode <data>
(HTTP) This posts data, similar to the other -d, --data options with the exception that this performs URL-encoding. [...]
The backend is coded like this:
#POST
#Path("/resource")
#Produces(MediaType.APPLICATION_JSON)
#Consumes(MediaType.APPLICATION_JSON)
public Response dailyBilling(
final List<String> students)
throws Exception {
....
}
How should I send curl data, which would me accepted as a List on backend ?
Using the following curl i get 400:
curl --digest -u ameya379+beet#gmail.com:credentials\
-H 'Content-Type: application/json'\
-X POST -d '{"student1", "student2"}'\
http://localhost:8080/api/somepath/resource
Error:
{
"detail":"Received JSON does not match expected format.",
"error":400,
"errorCode":"INVALID_JSON",
"parameters":[],
"reason":"Bad Request"
}
Arrays are encoded between [] in JSON.
curl --digest -u ameya379+beet#gmail.com:credentials -H 'Content-Type: application/json' -X POST -d '["student1", "student2"]' http://localhost:8080/api/somepath/resource