Search code examples
jax-rsjersey-2.0jersey-client

How to post raw data using JAX-RS 2.0 client API


I have a raw inputStream and a HttpServletRequest i need to send the whole inputStream recieved as well as the headers to another servlet(as it is) using JAX-RS client.

Client client = ClientBuilder.newClient();

WebTarget reTarget = client.target("http://localhost:8100/Server");
Invocation retargetInvocation = reTarget.request().??
Response.Response response = retargetInvocation.invoke();

How should my invocation be made for the post Request Invocation retargetInvocation = reTarget.request().post(Entity<T>).The inputStream may contain any Raw data


Solution

  • Use Entity.entity(inputStream, MediaType.YOUR_MEDIA_TYPE_TYPE)

    For the MediaType (and headers), I would inject @Context HttpHeaders into your resource class. It makes it easier to lookup specific headers. You could do

    Entity.entity(inputStream, httpHeaders.getMediaType());
    

    You could also iterate through the headers, in building the request

    Invocation.Builder builder = client.target(url).request();
    for (String header: headers.getRequestHeaders().keySet()) {
        builder.header(header, headers.getHeaderString(header));
    }
    Response response = builder.post(Entity.entity(is, headers.getMediaType()));
    

    So altogether, it might look something like

    @Context HttpHeaders headers;
    
    @POST
    public Response doForward(InputStream is) {
        Client client = ClientBuilder.newClient();
        String url = "http://localhost:8080/...";
        Invocation.Builder builder = client.target(url).request();
        for (String header: headers.getRequestHeaders().keySet()) {
            builder.header(header, headers.getHeaderString(header));
        }
        Response response = builder.post(Entity.entity(is, headers.getMediaType()));
        return Response.ok(response.getEntity()).build();
    }
    

    Do keep in mind though that the Client is an expensive object to create. You could reuse the same Client for different requests, as long as you don't mess with it's configurations after it is created.

    If you iterate through all the headers like I did above, you will get a warning in the log about allowing restricted headers. You can disable the warning with a System property

    System.setProperty("sun.net.http.allowRestrictedHeaders", "true");
    

    But honestly I am not sure about what the warning is for, and any security implications, so you may to look into that.