I am trying to do a get call with request body(JSON) as the request parameter list exceeds the limit. I am able to send the request via postman/insomnia and request is reaching till controller without any error. But the "requstBody" is empty at controller. What i am missing here?
#GET
#Path("\path")
#Consumes(APPLICATION_JSON)
#Produces(APPLICATION_JSON)
public Response getResponse(String requestBody) throws IOException { }
When I replaced #GET with #POST, requestBody has value. For GET call do we need to add anything more?
I am trying to do a get call with request body(JSON) as the request parameter list exceeds the limit. I am able to send the request via postman/insomnia and request is reaching till controller without any error. But the "requstBody" is empty at controller. What i am missing here?
One thing you are missing is the fact that the semantics of a request body with GET are not well defined.
RFC 7231, Section 4.3.1:
A payload within a GET request message has no defined semantics; sending a payload body on a GET request might cause some existing implementations to reject the request.
There are two ways for sending parameters in an Http Get method. PathVariable and RequestParam. In this way, sent parameters are visible in the request URL. for example:
www.sampleAddress.com/countries/{parameter1}/get-time?city=someValues
In the above request, parameter1 is a path variable and parameter2 is a request parameter. So an example of a valid URL would be:
www.sampleAddress.com/countries/Germany/get-time?city=berlin
To access these parameters in a java controller, you need to define a specific name for the parameters. For example the following controller will receive this type of requests:
#GetMapping(value = "/countries/{parameter1}/get-time", produces = "application/json; charset=utf-8")
public String getTimeOfCities(
#PathVariable(value = "parameter1") String country,
#RequestParam(value = "city") String city
){
return "the method is not implemented yet";
}
You are able to send RequestBody through a Get request but it is not recommended according to this link.
yes, you can send a body with GET, and no, it is never useful
to do so.
This elaboration in elasticsearch website is nice too:
The HTTP libraries of certain languages (notably JavaScript) don’t allow GET requests to have a request body. In fact, some users are suprised that GET requests are ever allowed to have a body.
The truth is that RFC 7231—the RFC that deals with HTTP semantics and
content—does not define what should happen to a GET request with a
body! As a result, some HTTP servers allow it, and some—especially
caching proxies—don’t.
If you want to use Post method, you are able to have RequestBody too. In the case you want to send data by a post request, an appropriate controller would be like this:
#PostMapping(value = "/countries/{parameter1}/get-time", produces = "application/json; charset=utf-8")
public String getTimeOfCitiesByPost(
#PathVariable(value = "parameter1") String country,
#RequestParam(value = "city") String city,
#RequestBody Object myCustomObject
){
return "the method is not implemented yet";
}
myCustomObject could have any type of data you defined in your code. Note that in this way, you should send request body as a Json string.
put #RequestBody on String requestBody parameter
#RequestMapping("/path/{requestBody}")
public Response getResponse(#PathVariable String requestBody) throws IOException { }
Related
I want to make a GET request to my server that receives two parameters, uniqueConfig and commitHash. The code for this operation in my Controller class is as follows:
#GetMapping("/statsUnique")
public ResponseEntity<Object> hasEntry(#RequestParam("uniqueConfig") String uniqueConfig,
#RequestParam("commitHash") String commitHash) {
Optional<Stats> statsOptional =
codecService.findByUniqueConfigAndCommitHash(uniqueConfig, commitHash);
if (statsOptional.isPresent()) {
return ResponseEntity.status(HttpStatus.OK).body(true);
}
return ResponseEntity.status(HttpStatus.OK).body(false);
}
The issue is, when I try to make the GET request using Postman, the server returns a 400 - Bad Request with the following error message:
MissingServletRequestParameterException: Required request parameter 'uniqueConfig' for method parameter type String is not present]
my JSON on Postman looks like this:
{
"commitHash": "ec44ee022959410f9596175b9424d9fe1ece9bc8",
"uniqueConfig": "bowing_22qp_30fr_29.97fps_fast-preset"
}
Please note that those aren't the only attributes and I've tried making the same request with all of them on the JSON. Nonetheless, I receive the same error.
What am I doing wrong here?
A GET request doesn't (or at least shouldn't) have a body. Parameters defined by the #RequestParam annotations should be sent in the query string, not a JSON body, i.e., the request should be something like
http://myhost/statsUnique?commitHash=commitHash&uniqueConfig=bowing_22qp_30fr_29.97fps_fast-preset
I have designed a REST based post Service using Spring 3.
The service method consumes parameter as String and responds data as String. The param and response can be json or string
#RequestMapping(value = "/service", method = RequestMethod.POST)
public #ResponseBody String Service(#RequestParam("param") String param) {
Sample POST Request:
http://IP:PORT/test-project/service
param={"name":"John"}
Sample response to above request:
{"age":"31"}
Is there a way to safeguard this request against Cross Site Scripting?
If yes then how can I achieve XSS support once I receive request on param parameter??
If you aren't returning the parameter value (or any manipulation of it) in the response, you don't have an XSS vulnerability.
Not that it means that your service is completely secure, of course.
I've used Matlab's webwrite() to make calls to a REST API, providing the requset params. However, I need to now make a call where the Request Body must be specified. Is there a way to do this?
The REST API is defined by a Java Spring controller, e.g.:
#PostMapping(value = "post")
public ResponseEntity<?> setMySTuff(
#RequestParam(name = "myId") int myId,
#RequestBody Collection<MyCustomObject> myObjList) {
THe data paramemter for webwrite seems intended for being a set of key/value request param pairs, and not a means of setting the request body.
If I remember correctly, #RequestParam is used for mapping values as query parameters, while #RequestBody defines the content of the response. If my assumptions are valid, the Matlab equivalent should be:
url = ['http://mywebsite.net/service/?myId=' num2str(5778)];
body = struct('Item1','Hello','Item2','World');
opts = weboptions('MediaType','application/json','RequestMethod','post');
response = webwrite(url,body,opts);
It could be very simple but it will be very helpful for me to understand...
I used #ResponseBody in my restcontroller to return String value to browser. The response string is successfully received in browser.
ie:
#RequestMapping(value="/foo", method=RequestMethod.GET)
#ResponseBody
public String foo() {
return "bar";
}
What is the content-type of above response? If this is going to be like writing setAttribute in servlet response what could the attribute name?
If the browser accept only "application/json" how spring will treat the response?
Submitted code produces text/html, as do all mapped Controller methods by default. If you want to produce application/json, you have to change your RequestMapping to
#RequestMapping(value="/foo", method=RequestMethod.GET, produces = "application/json")
However this is not a valid Json String, you would have to change it because the method you submitted would return empty body. The submitted example would be valid text/plain.
When the request contains header "Accept: application/json" and other content type is returned, Spring returns Json-type response explaining that HttpMediaTypeNotAcceptableException was thrown.
Regarding the servlet analogy - please explain, I don't fully understand what you mean. The String is returned as response body, it's very different from request attributes. What would you like to achieve?
I assume the content type will be plain/text. If the request sets accept to "application/json" it depends on your browser/tool. Most rest clients won't display it as it is not application/json. If you invoke the API directly I would assume it is displayed due to browser content sniffing (can be disabled via a header).
I've got a method that looks something like this:
#RestController
#org.springframework.context.annotation.Scope("request")
#RequestMapping(value = "/path/to", produces = "application/json; charset=utf-8")
public class MyController {
Thing thing;
#RequestMapping("/myMethod")
#ResponseBody
public String myMethod(
#RequestParam(value="storeIds", required=false) List<String> storeIds,
#RequestParam(value="startDate") Date startDate,
#RequestParam(value="endDate") Date endDate
) throws Exception {
JSONObject json = thing.getJson(startDate, endDate, storeIds);
return json.toString();
}
}
Right now this accepts three parameters, as you can see, and they all come in as GET variables. What I'd like to do is have the startDate and endDate parameters still come in as GET variables, but the storeIds parameters come in as a POST variable. I'm concerned that if I just change the #RequestMapping annotation to the POST method, then it will expect all three parameters to be POST variables instead.
Is there any way to accomplish what I'm asking for?
The difference between a GET request and a POST request, aside from the implied semantics of "getting" vs. "posting" (and associated likely consequences with respect to caching, reloading, etc.), is simply that a POST request has a body, while a GET request does not. (And even with a POST request, the body can be empty: a zero-length body is valid.) This means that a GET request can only take parameters via the URL, whereas a POST request can take parameters either via the URL or via the body (or some via the one and some via the other).
From the comments above, I gather that you use the term "GET variable" to mean a URL parameter, even in a POST request; but the reality is that URL parameters work for both request methods.