8

I'm trying to consume a REST API that requires a body with a GET request. But as a GET usually doesn't have a body, I can't find a way to attach a body in my request. I am also building the REST API, but the professor won't allow us to change the method to POST (he gave us a list of the endpoints we are to create, no more, no less).

I'm trying to do it like this:

Response r = target.request().method(method, Entity.text(body));

Where I set the method to GET and the body to my get body. However, using this approach I get an exception:

javax.ws.rs.ProcessingException: RESTEASY004565: A GET request cannot have a body.

Is there any way to do this with JAX-RS? We learned to use JAX-RS so I would prefer a solution using this, as I'm not sure my professor would allow us to use any other REST client. I'm currently using RESTEasy, provided by the WildFly server.

(This is not a duplicate of HTTP GET with request body because I'm asking on how to create a GET request with body in JAX-RS, not if it should be done.)

Miguel Almeida
  • 204
  • 1
  • 4
  • 15
  • Possible duplicate of [HTTP GET with request body](https://stackoverflow.com/questions/978061/http-get-with-request-body) – Karol Dowbecki Mar 17 '18 at 19:05
  • 1
    It doesn't really makes sense to create a GET request with a body. What would you test, if the tested server is correctly skipping the invalid body? JAX-RS is correct in stopping you from creating an invalid request. – Karol Dowbecki Mar 17 '18 at 19:11
  • I know that but no matter what we say to our professor he still insists we make the REST API as he design it, and that includes GET requests with a body. – Miguel Almeida Mar 17 '18 at 19:18
  • 1
    In theory, the correct answer to your professor is that such an API violates the HTTP standard's recommendations. In practice, that doesn't stop people (e.g. Elasticsearch) from doing it. I'm not aware of a way to support this with JAX-RS though. – Oliver Charlesworth Mar 17 '18 at 19:25
  • When I was arguing with my professor whether a GET has a body or not he said that they could have and used the Elasticsearch example. Even after I pointed him to https://stackoverflow.com/questions/978061/http-get-with-request-body he still insisted that we don't change anything. – Miguel Almeida Mar 17 '18 at 19:33
  • Then you could also point him at the significant number of server (and client) libraries that don't support this, and ask if he intends for you to reimplement an HTTP library. The answer will not affect whether JAX supports this. – Oliver Charlesworth Mar 17 '18 at 19:59

1 Answers1

4

This depends on what is your JAX-RS implementation. This check can be disabled in Jersey 2.25 using SUPPRESS_HTTP_COMPLIANCE_VALIDATION property:

ClientConfig config = new ClientConfig();
config.property(ClientProperties.SUPPRESS_HTTP_COMPLIANCE_VALIDATION, true);
JerseyClient client = JerseyClientBuilder.createClient(config);
WebTarget target = client.target(URI.create("https://www.stackoverflow.com"));
Response response = target.request().method("GET", Entity.text("BODY HERE"));

Instead of exception you will get an INFO log

INFO: Detected non-empty entity on a HTTP GET request. The underlying HTTP transport connector may decide to change the request method to POST.

However in RESTEasy 3.5.0.Final there is a hardcoded check in both URLConnectionEngine and ApacheHttpClient4Engine:

if (request.getEntity() != null)
{
  if (request.getMethod().equals("GET")) throw new ProcessingException(Messages.MESSAGES.getRequestCannotHaveBody());

You would have to create your own implementation of the ClientHttpEngine to skip this. Then you need to supply it when building the client:

ClientHttpEngine engine = new MyEngine();
ResteasyClient client = new ResteasyClientBuilder().httpEngine(engine).build();
Karol Dowbecki
  • 43,645
  • 9
  • 78
  • 111
  • 1
    How does one actually form a GET request with a body, though? There is no appropriate overload on JerseyInvocation.Builder. – Oliver Charlesworth Mar 17 '18 at 20:08
  • @OliverCharlesworth added two more lines to create `target` and get `response`. – Karol Dowbecki Mar 17 '18 at 20:10
  • I'm using RESTEasy, as it is provided by WildFly, the server we must use. I tried using Configuration, which appears to be the equivalent, but doing `@Context private Configuration config;` is not working, so I can't even try to modify this. – Miguel Almeida Mar 17 '18 at 20:43
  • 2
    @MiguelAlmeida I've update my answer. Ther eis no good way to do this in RESTEasy. Your prof doesn't know what he is doing if he mandates a questionable endpoint and library that can't handle it. – Karol Dowbecki Mar 17 '18 at 21:09
  • Accepted this answer, as it proves it is impossible to solve my problem within the context of what I'm supposed to do. – Miguel Almeida Mar 17 '18 at 21:19