Dropwizard解压请求过滤器

3

我有一个 Dropwizard 应用程序,其中客户端请求正文内容是压缩的内容。我需要在 Dropwizard 应用程序中解压缩内容。我有以下代码,但是我在该行收到了异常 java.io.EOFExceptionGZIPInputStream 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();
        }
    }
}

客户端正在发送以下请求:
curl -XPOST -d @test.gz http://localhost:8080/save

test.gz是按照以下步骤创建的:

echo "hello world" > test
gzip test
1个回答

3

代码本身可以正常运行。在这个问题中的问题是cURL请求。如果添加-v(详细)标志,您将看到问题。

$ 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

问题在于最后一行: Content-Typeapplication/x-www-form-urlencoded。不仅如此,文件中的数据也没有被发送。我不知道具体原因,但与-d标志有关。cURL的默认设置是在使用-d标志时发送application/x-www-form-urlencoded数据。
我们应该使用--data-binary选项代替-d并将Content-Type设置为application/octet-stream。这也会导致服务器端调用正确的提供程序。
curl -XPOST -v \
     -H 'Content-Type:application/octet-stream' \
     --data-binary @test.gz \
     http://localhost:8080/api/gzip/save

为了确保我们的端点只接受 application/octet-stream,我们应该添加 @Consumes 注释。这很重要,因为我们不希望调用随机提供者,这可能会导致奇怪的错误消息。

@POST
@Path("/save")
@Produces("application/json;charset=utf-8")
@Consumes("application/octet-stream")
public Response save(byte[] gzipBody) {

}

侧记

  • 我不会为这个方法使用 byte[] 参数。你不需要把整个文件都读到内存中。当然,这个例子已经读取了文件以获取字符串。但在实际应用中,您很可能会将文件保存在某个地方。因此,不要使用 byte[] 参数,而是使用 InputStream。您可以将该 InputStream 传递给 GZIPInputStream 构造函数。

  • 对于上传文件,请考虑使用多部分表单。使用多部分表单,您不仅可以一次发送多个文件,还可以向文件添加元数据。请参见 Jersey 支持Dropwizard 支持(后者只是 Jersey 特性的捆绑包装器)。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接