0

I don't understand why this curl invocation gives me a 400 bad request.

curl -v -XGET -H "Content-Type:application/json" -d '{"match":{"first":"james"}}' http://localhost:8080/geocon/search/

Considered that this is the code part who should handle everything

@Path(Paths.SEARCH)
public class SearchService {    

    @GET
    @Produces(MediaType.APPLICATION_JSON)
    @Consumes(MediaType.APPLICATION_JSON)
    public String search(@DefaultValue(NO_TYPE) @QueryParam("type") String type, String query) {
        // do interesting stuff with the query
        System.out.println(type);
        System.out.println(query);
      return //the result of the query
   }

Obviously, I don't see in the console the two print lines and the answer from the web service is 400 Bad request

If I change the verb in curl and in the code (POST instead of GET), the results are OK and everything works as it should.

Why?

Can't I use GET passing data? If you think about it, I am not modifying stuff, I'd just receive data so GET should be the most RESTful translation for it.

BlacK
  • 231
  • 5
  • 15

2 Answers2

1

You are allowed to send a body with a GET request, but it must not have any semantics; it should essentially be ignored. Not doing so violates the HTTP/1.1 specification. I suggest avoiding this practice because no one expects a request body with a GET request.

Now I'm not sure if the MVC framework you're using is stricter in the sense that it automatically rejects any GET request sent with a body, because in general a server can accept a GET request with a body, but is just supposed to ignore it.

Hence, what you're doing is not RESTful. The only way you can pass in data through a GET is through query parameters.

UPDATE

This is in response to your comment.

You could expose an explicit resource called searchResult or search. To create a searchResult or search resource instance, you pass in a body that is essentially a query. If you are using semantic media types (as you should for proper RESTfulness), your search-result resource could have the media type application/vnd.myservice.search-result+json and the query can have the media type application/vnd.myservice.search-query+json. Then, you can POST a request to /searchResults that has a request body that contains the complex query. The media-type of the response would be application/vnd.myservice.search-result+json and it can contain the search results.

So how does this play out? A search query comes in and you parse out the body and run the query. Then you should persist the results (not for ever; give it some sane TTL value). Once you have done that, you return a 303 See Other with a Location header that has a link to the search results (maybe something like /searchResults/4334, where 4334 is the id of this particular result). The client can then access this URI to retrieve the search results. If the client requests a search result that has expired (i.e., the server cleaned it up because the TTL expired), then the server should respond with a 410 Gone.

Also read this for more pointers.

Vivin Paliath
  • 87,975
  • 37
  • 202
  • 284
  • OK but if I want to model a research function inside my web service where queries are JSONs, POST doesn't sound really RESTful. Would you suggest to pass the whole JSON through a query parameter? – BlacK Mar 13 '15 at 21:20
  • @BlacK do you really need JSON to pass filter criteria? Are there fields you need to pass other than match? Otherwise I'd just say `?first=james`. – Alex Mar 13 '15 at 21:30
  • @BlacK You could simply pass in the fields `?firstName=james`, for example. However, if you want to deal with more complex queries, take a look at some of the solutions to [this question](http://stackoverflow.com/questions/13110147/rest-and-complex-search-queries). – Vivin Paliath Mar 13 '15 at 21:48
  • The thing is that this web service has to be able to handle Elasticsearch queries. Elasticsearch's power is that you can store your data schema-free. So if I'd use the JSON notation, I'd be able to have a good level of dynamism. – BlacK Mar 13 '15 at 21:52
  • @BlacK Check out my edit. – Vivin Paliath Mar 13 '15 at 22:04
0

It seems that syntax you are using has a typo.Try using the below ones for json and xml format. -XGET is wrong. it should be -X GET.

For xml curl -H "Accept: application/xml" -H "Content-Type: application/xml" -X GET http://hostname/resource

For JSON

curl -i -H "Accept: application/json" -H "Content-Type: application/json" -X GET http://hostname/resource
chetank
  • 394
  • 3
  • 13