1

I am using Dropwizard (v1.0.5) and I want to create a client to connect a post service that receives a multipart. However I obtain a "Bad Request" response.

Here the dependencies in my pom.xml

    <dependencies>
    <dependency>
        <groupId>io.dropwizard</groupId>
        <artifactId>dropwizard-core</artifactId>
        <version>${dropwizard.version}</version>
    </dependency>
    <dependency>
        <groupId>io.dropwizard</groupId>
        <artifactId>dropwizard-assets</artifactId>
        <version>${dropwizard.version}</version>
    </dependency>
    <dependency>
        <groupId>io.dropwizard</groupId>
        <artifactId>dropwizard-forms</artifactId>
        <version>${dropwizard.version}</version>
    </dependency>
    <dependency>
        <groupId>io.dropwizard</groupId>
        <artifactId>dropwizard-client</artifactId>
        <version>${dropwizard.version}</version>
    </dependency>

</dependencies>

Here my Dropwizard Application (Client2PostApplication.java):

public class Client2PostApplication extends Application<Client2PostConfiguration> {
public static void main(String[] args) throws Exception {
    new Client2PostApplication().run(args);
}

@Override
public void initialize(Bootstrap<Client2PostConfiguration> bootstrap) {
    bootstrap.addBundle(new MultiPartBundle());
}

@Override
public void run(Client2PostConfiguration configuration,
                Environment environment) throws Exception {

    environment.jersey().register(MultiPartFeature.class);

    final Client client = new JerseyClientBuilder(environment).using(configuration.getJerseyClientConfiguration()).build(getName());

    environment.jersey().register(new Client2Post(client));

    environment.jersey().register(new MyPostResource()); 

    }
}

Here my Configuration (Client2PostConfiguration.java):

public class Client2PostConfiguration extends Configuration {

    @Valid
    @NotNull
    private JerseyClientConfiguration jerseyClient = new JerseyClientConfiguration();

    @JsonProperty("jerseyClient")
    public JerseyClientConfiguration getJerseyClientConfiguration() {
        return jerseyClient;
    }
}

And now, the post web service (MyPostResource.java):

@Path("/testpost")

public class MyPostResource {

    public MyPostResource() {

    }

    @POST
    @Consumes(MediaType.MULTIPART_FORM_DATA)
    @Timed
    public String test(
        @FormDataParam("foo") String testData) throws IOException {
        return testData;
    }
}

And finally, the client (Client2Post.java):

@Produces(MediaType.TEXT_PLAIN)
@Path("/client")
public class Client2Post {

    private Client client;

    public Client2Post(Client client) {
        this.client = client;
    }

    @GET
    @Path("/test")
    public String testPost() {

    final Invocation.Builder request = client.target("http://localhost:8080/testpost").register(MultiPartFeature.class).request();

    final FormDataMultiPart entity = new FormDataMultiPart()
            .field("foo", "bar");

    final String response = request.post(Entity.entity(entity, entity.getMediaType()), String.class);

    return response;

    }
}

I want to be able to make a GET through http://localhost:8080/client/test and receive the response of http://localhost:8080/testpost that, in this case, would be "bar". However I am getting "HTTP 400 Bad Request".

What am I doing wrong?

How could I test the post service? Because I am using a firefox addon, the HttpRequester using this multipart content:

--l3iPy71otz
Content-Disposition: form-data; name="foo"
bar
--l3iPy71otz--

...and I get the same response.

impulso
  • 86
  • 3
  • 7
  • Are you seeing any exceptions? Is there any message to go with the response. It's hard to say what the problem is without more information. The code looks OK – Paul Samsotha Jun 01 '17 at 00:16
  • An empty line is missing after the Header `Content-Disposition`. Try `curl -F "foo=bar" localhost:8080` – Ôrel Jun 01 '17 at 05:07
  • @peeskillet I don't get any exceptions, I think it doesn't even enter the function testPost because some problem with the format of the multipart, but I don't know what to do anymore! – impulso Jun 06 '17 at 07:47
  • @Ôrel Executing the call from curl works just fine! I get an OK response and the content: "bar". So now, I don't understand why using the HttpRequester doesn't work (even inserting a blank line), and more importantly, why I can't make my client work... What am I missing? – impulso Jun 06 '17 at 07:54
  • Good the server is working. Can you do a tcpdump to see the difference between curl and the client ? – Ôrel Jun 06 '17 at 10:15
  • For your browser plugin, your payload should be like "3[\r][\n]" "bar[\r][\n]" "2b[\r][\n]"` – Ôrel Jun 06 '17 at 14:55
  • https://stackoverflow.com/questions/19668426/how-to-resolve-messagebodywriter-not-found-for-media-type-multipart-form-data-er can help – Ôrel Jun 06 '17 at 14:56
  • I don't have experience using tcpdump, however I run: sudo tcpdump -X -i lo And I got this output for the [call using curl](https://drive.google.com/open?id=0B4erkx-SQuKdakxVSzNOY1d4N0k), and this one for the [call using the client](https://drive.google.com/open?id=0B4erkx-SQuKdY3BtdThWOEdzZlE), I can see the size of the data sent is not the same, but I cannot figure out what to do with this information... I had already read that question linked, it helped a bit (I didn't have registered the multipart.class), but my client still doesn't work... – impulso Jun 08 '17 at 15:09
  • I uploaded the code to GitHub [here](https://github.com/esparig/dwclient2post), just in case someone wants to try it. – impulso Jun 08 '17 at 16:05

1 Answers1

1

I found the solution to my problem in https://github.com/dropwizard/dropwizard/issues/1094. It seems that chunked encoding should be disabled for requests in the Jersey Client to work with MIME Multipart.

So my Client2PostApplication.java is now:

public class Client2PostApplication extends Application<Client2PostConfiguration> {
    public static void main(String[] args) throws Exception {
        new Client2PostApplication().run(args);
    }

    @Override
    public void initialize(Bootstrap<Client2PostConfiguration> bootstrap) {
        bootstrap.addBundle(new MultiPartBundle());
    }

    @Override
    public void run(Client2PostConfiguration configuration,
                Environment environment) throws Exception {

        environment.jersey().register(MultiPartFeature.class);
        JerseyClientConfiguration conf = configuration.getJerseyClientConfiguration();

        conf.setChunkedEncodingEnabled(false); //This line is new!!!

        final Client client = new JerseyClientBuilder(environment).using(conf).build(getName());
        environment.jersey().register(new Client2Post(client));
        environment.jersey().register(new MyPostResource());       
    }
}

And it works pertectly. The code can be retrieved in https://github.com/esparig/dwclient2post

impulso
  • 86
  • 3
  • 7