users@jersey.java.net

Re: [Jersey] GZIPContentEncodingFilter client and server side

From: Paul Sandoz <Paul.Sandoz_at_Sun.COM>
Date: Thu, 17 Jun 2010 18:13:17 +0200

On Jun 17, 2010, at 5:36 PM, Christopher Piggott wrote:
> Nuts, I didn't think of that. When I do .post(ClientResponse.class,
> new File(something)); the client library must be clever enough to
> relize that I'm sending it a File and send the correct content-length.
> I would assume that if I .post an InputStream, for example, that it
> doesn't set that header at all ...
>

That depends on the underlying HTTP library. The point is if Jersey
does not know what the length it does not tell the underlying HTTP
library so it can optimize. The HTTP library might buffer the request
to determine the length, or it may use chunked encoding to avoid
buffering, or if it is told the length it can avoid buffering or
chunked encoding.


> What's correct behavior if you're using Content-Encoding: gzip ...
> should Content-Length reflect the size of the uncompressed document?
>

No, it should reflect the size in bytes of the request entity.


>> uc.setFixedLengthStreamingMode((int)size);
>
> OK, so I get the file size myself and force its length?
>

No, for the moment do not use File and use InputStream as a workaround
or another workaround is to override Jersey's File message body writer
(see end of email for a modified version you can use and register).



> I'm still concerned about one thing ... isn't Content-Length part of
> what makes persistent HTTP/1.1 connections work correctly? Is that
> going to be screwed up now?
>

No. That is HTTP keep-alive. It works with Content-Length or chunked
encoding.


>> Can you log an issue?
>
> Absolutely. Will do.
>

Thanks!
Paul.


@Produces({"application/octet-stream", "*/*"})
@Consumes({"application/octet-stream", "*/*"})
public final class FileProvider extends
AbstractMessageReaderWriterProvider<File> {

     public boolean isReadable(Class<?> type, Type genericType,
Annotation[] annotations, MediaType mediaType) {
         return File.class == type;
     }

     public File readFrom(
             Class<File> type,
             Type genericType,
             Annotation annotations[],
             MediaType mediaType,
             MultivaluedMap<String, String> httpHeaders,
             InputStream entityStream) throws IOException {
         File f = File.createTempFile("rep","tmp");
         OutputStream out = new BufferedOutputStream(new
FileOutputStream(f));
         try {
             writeTo(entityStream, out);
         } finally {
             out.close();
         }
         return f;
     }

     public boolean isWriteable(Class<?> type, Type genericType,
Annotation[] annotations, MediaType mediaType) {
         return File.class.isAssignableFrom(type);
     }

     public void writeTo(
             File t,
             Class<?> type,
             Type genericType,
             Annotation annotations[],
             MediaType mediaType,
             MultivaluedMap<String, Object> httpHeaders,
             OutputStream entityStream) throws IOException {
         InputStream in = new BufferedInputStream(new
FileInputStream(t), ReaderWriter.BUFFER_SIZE);
         try {
             writeTo(in, entityStream);
         } finally {
             in.close();
         }
     }

     @Override
     public long getSize(File t, Class<?> type, Type genericType,
Annotation[] annotations, MediaType mediaType) {
         return -1;
     }
}