eclipse-ee4j / jersey

Eclipse Jersey Project - Read our Wiki:
https://github.com/eclipse-ee4j/jersey/wiki
Other
692 stars 355 forks source link

Jersey-client: No way to put non-retryable with digest auth #3154

Open jerseyrobot opened 9 years ago

jerseyrobot commented 9 years ago

I see no way to put a stream or other non-retryable payload while using DIGEST auth. This is something we could do with Jersey 1.17 client.

Since digest requires a challenge-response, we have two choices for non-retryable payloads: 1) buffer the stream and send it with both the first and second request 2) make a separate auth-only request first to get the Authorization token then use it to put the non-retryable payload

I see no way to do either using Jersey/Jax-RS 2.17, even when using httpclient as the connector. httpclient offers AuthCache but I see no way to access that via Jersey/JAX-RS.

Am I right to consider it a MUST requirement for Jersey/JAX-RS to support digest auth and non-retryable payloads (such as InputStream)?

Here's the code that fails with "IOException: Stream closed". I'm testing it against MarkLogic server but any web service which supports digest would have the same problem.

import javax.ws.rs.client.Client;
import javax.ws.rs.client.ClientBuilder;
import javax.ws.rs.client.Entity;
import javax.ws.rs.client.WebTarget;
import javax.ws.rs.core.Response;

import org.glassfish.jersey.client.authentication.HttpAuthenticationFeature;
import org.glassfish.jersey.client.ClientConfig;
import org.glassfish.jersey.client.ClientProperties;
import org.glassfish.jersey.client.RequestEntityProcessing;

import java.io.StringReader;

public class Jersey217Test {
    public static void main(String[] args) {
        String user = "admin";
        String pass = "admin";
        ClientConfig clientConfig = new ClientConfig();
        clientConfig.property(ClientProperties.REQUEST_ENTITY_PROCESSING,  RequestEntityProcessing.BUFFERED);
        Client client = ClientBuilder.newClient(clientConfig);
        client.register(HttpAuthenticationFeature.digest(user, pass));
        StringReader reader = new StringReader("test");
        WebTarget connection = client.target("http://localhost:8000/v1/documents");
        connection
            .queryParam("uri", "test.txt")
            .request((String) null)
            .put(Entity.entity(reader, "text/plain"));
        Response response = connection
            .queryParam("uri", "test.txt")
            .request("text/plain").get();
        String body = response.readEntity(String.class);
        System.out.println("Body=[" + body + "]");
    }
}

Environment

java 1.8, Win8.1

Affected Versions

[2.17]

jerseyrobot commented 6 years ago
jerseyrobot commented 9 years ago

@glassfishrobot Commented Reported by sammefford

jerseyrobot commented 9 years ago

@glassfishrobot Commented sammefford said: Here's a follow-up. I found a work-around but it's not what I need. If I use the same WebTarget it looks like follow-up requests are authenticated:

public class Jersey217Test {
    public static void main(String[] args) {
        String user = "admin";
        String pass = "admin";
        String baseUri = "http://localhost:8000/v1/"; 
        ClientConfig clientConfig = new ClientConfig();

        Client client = ClientBuilder.newClient(clientConfig);
        client.register(HttpAuthenticationFeature.digest(user, pass));
        StringReader reader = new StringReader("test");
        WebTarget base = client.target(baseUri).path("documents")
            .queryParam("uri", "test.txt");
        Response response = base
            .request(MediaType.MEDIA_TYPE_WILDCARD)
            .head();
        response.close();
        response = base
            .request(MediaType.MEDIA_TYPE_WILDCARD)
            .put(Entity.entity(reader, "text/plain"));
        response.close();
        response = base
            .request("text/plain").get();
        String body = response.readEntity(String.class);
        System.out.println("Body=[" + body + "]");
    }
}

The problem is that any method that generates a new WebTarget (such as queryParam) loses the authentication. So I'm seeing no viable way to authenticate once then make multiple requests with the same authentication. More specifically, I see no way to make an auth-only request prior to a non-retryable put method request unless the auth-only request can match exactly the url of the non-retryable request which is not always going to work in my scenario.

jerseyrobot commented 9 years ago

@glassfishrobot Commented sammefford said: Ping. Is there anyone that can look at this? This bug is a blocker for us. It is preventing us from upgrading to Jersey 2.

jerseyrobot commented 9 years ago

@glassfishrobot Commented @AdamLindenthal said: Hi, thanks for reporting the issue. I am moving it to backlog, so that we can take a look at it in one of the future sprints.

Regards, Adam

jerseyrobot commented 9 years ago

@glassfishrobot Commented sammefford said: I wanted to check in and see if any progress can be made on this issue. We have users that want us to upgrade to Jersey 2, but I can't see how without resolving this issue.

jerseyrobot commented 8 years ago

@glassfishrobot Commented alexisbocquet said: Hi, I would like to report also my issue which is very similar to the one described above. I am invoking a post request trying to send data through an inputstream (a PipedInputStream) using the Digest authentication method. And as sammefford said I receive a IOException : pipe closed. The reason is that the pipedinputstream has been closed after the first connection attempt. I am also trying to update from Jersey 1 to Jersey 2 using version 2.22.1. Regards, Alexis.

jerseyrobot commented 7 years ago

@glassfishrobot Commented This issue was imported from java.net JIRA JERSEY-2882