I have a dropwizard application where the client request body content is gzipped content. I need to decompress the content in dropwizard app. I have the following code, but I am getting an exception java.io.EOFException at the line GZIPInputStream is = new GZIPInputStream(new ByteArrayInputStream(gzipBody))
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Response;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.nio.charset.Charset;
import java.util.zip.GZIPInputStream;
import static javax.ws.rs.core.Response.Status.INTERNAL_SERVER_ERROR;
@Path("/")
public class UserEventResource {
@POST
@Path("/save")
@Produces("application/json;charset=utf-8")
public Response save(byte[] gzipBody) {
try {
try (GZIPInputStream is = new GZIPInputStream(new ByteArrayInputStream(gzipBody))) {
try (ByteArrayOutputStream os = new ByteArrayOutputStream()) {
byte[] buffer = new byte[4096];
int length;
while ((length = is.read(buffer)) > 0) {
os.write(buffer, 0, length);
}
String body = new String(os.toByteArray(), Charset.forName("UTF-8"));
}
}
return Response.status(OK).build();
} catch (Exception exception) {
return Response.status(INTERNAL_SERVER_ERROR).build();
}
}
}
Client is sending the following request,
curl -XPOST -d @test.gz http://localhost:8080/save
test.gz is created by following step,
echo "hello world" > test
gzip test
The code itself works. The problem in this question is the cURL request. If you add the -v (verbose) flag, you'll see the problem.
$ curl -XPOST -v -d @test.gz http://localhost:8080/api/gzip/save
Note: Unnecessary use of -X or --request, POST is already inferred.
* Trying ::1...
* TCP_NODELAY set
* Connected to localhost (::1) port 8080 (#0)
> POST /api/gzip/save HTTP/1.1
> Host: localhost:8080
> User-Agent: curl/7.54.0
> Accept: */*
> Content-Length: 8
> Content-Type: application/x-www-form-urlencoded
The problem is in the last line: the Content-Type is application/x-www-form-urlencoded. Not just this though, but the data in the file isn't sent either. I don't know the specifics, but it has something to do with the -d flag. The default to cURL is to send application/x-www-form-urlencoded data when using the -d flag.
What we should be doing is using the --data-binary option instead of -d and also set the Content-Type to application/octet-stream. This will also cause the correct provider to be called on the server side.
curl -XPOST -v \
-H 'Content-Type:application/octet-stream' \
--data-binary @test.gz \
http://localhost:8080/api/gzip/save
And just to be sure that our endpoint only accepts application/octet-stream, we should add the @Consumes annotation. This is important, as we don't want random providers to be called, which can lead to weird error messages.
@POST
@Path("/save")
@Produces("application/json;charset=utf-8")
@Consumes("application/octet-stream")
public Response save(byte[] gzipBody) {
}
I wouldn't use a byte[] parameter for the method. You don't really want the entire file to be read into memory. Sure the example already reads it to get the String. But most likely in a real application, you are going to saving the file somewhere. So instead of a byte[] parameter, just use an InputStream. You can pass that InputStream to the GZIPInputStream constructor.
For uploading files, consider using multipart instead. With multipart you can not just send more than one file at a time, but you can also add meta data to the files. See Jersey support and Dropwizard support (which isn't much just a bundle wrapper around the Jersey feature.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With