Content-MD5 в клиентском API Джерси - PullRequest
2 голосов
/ 08 июня 2011

Я пытаюсь установить заголовок Content-MD5 для запроса, созданного с помощью клиентского API Jersey. Я создал ClientFilter, который реализует другой адаптер (аналогично тому, как работает GZipFilter). Как это:

public class ContentMD5Filter extends ClientFilter {

    private static final class ContentMD5Adapter extends AbstractClientRequestAdapter {
        ContentMD5Adapter(final ClientRequestAdapter cra) {
            super(cra);
        }

        @Override
        public OutputStream adapt(final ClientRequest request, final OutputStream out) throws IOException {
            try {
                MessageDigest instance = MessageDigest.getInstance("MD5");
                request.getHeaders().add("Content-MD5", instance);
                return new DigestOutputStream(out, instance);
            } catch (NoSuchAlgorithmException e) {
                throw new WebApplicationException();
            }
        }
    }

    @Override
    public ClientResponse handle(final ClientRequest cr) throws ClientHandlerException {
        cr.setAdapter(new ContentMD5Adapter(cr.getAdapter()));
        return getNext().handle(cr);
    }
}

Это не работает, так как дайджест читается раньше (т. Е. До того, как весь контент написан.

Есть идеи, как это сделать? Помимо настройки заголовка, мне нужно получить доступ к нему в другом фильтре (для реализации механизма безопасности)

1 Ответ

0 голосов
/ 14 июня 2011

Я нашел решение. Это довольно сложный способ сделать это, так как мне нужно временно сохранить выходной поток, но я думаю, вы можете понять это, если вам это нужно самостоятельно:)

Код для фильтра:

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

import org.apache.commons.codec.binary.Base64;
import org.apache.commons.io.IOUtils;

import com.sun.jersey.api.client.AbstractClientRequestAdapter;
import com.sun.jersey.api.client.ClientHandlerException;
import com.sun.jersey.api.client.ClientRequest;
import com.sun.jersey.api.client.ClientRequestAdapter;
import com.sun.jersey.api.client.ClientResponse;
import com.sun.jersey.api.client.filter.ClientFilter;

public class ContentMD5Filter extends ClientFilter {

    @Override
    public ClientResponse handle(final ClientRequest cr) throws ClientHandlerException {
        cr.setAdapter(new ContentMD5Adapter(cr.getAdapter()));
        return getNext().handle(cr);
    }

    private static final class ContentMD5Adapter extends AbstractClientRequestAdapter {
        ContentMD5Adapter(final ClientRequestAdapter cra) {
            super(cra);
        }

        @Override
        public OutputStream adapt(final ClientRequest request, final OutputStream out) throws IOException {
            return new ContentMD5OutputStream(request, getAdapter().adapt(request, out));
        }
    }

    private static final class ContentMD5OutputStream extends OutputStream {

        private final ByteArrayOutputStream byteArrayOutputStream;
        private final OutputStream jerseyStream;
        private final ClientRequest request;

        public ContentMD5OutputStream(final ClientRequest request, final OutputStream jerseyStream) {
            this.jerseyStream = jerseyStream;
            this.request = request;

            byteArrayOutputStream = new ByteArrayOutputStream();
        }

        @Override
        public void write(final int b) throws IOException {
            byteArrayOutputStream.write(b);
        }

        @Override
        public void close() throws IOException {
            byteArrayOutputStream.close();
            byte[] byteArray = byteArrayOutputStream.toByteArray();
            setContentMD5Header(byteArray);
            IOUtils.write(byteArray, jerseyStream);
            jerseyStream.close();
        }

        private void setContentMD5Header(final byte[] data) {
            try {
                MessageDigest instance = MessageDigest.getInstance("MD5");
                String contentMD5 = new String(Base64.encodeBase64(instance.digest(data)));
                request.getHeaders().add("Content-MD5", contentMD5);
            } catch (NoSuchAlgorithmException e) {
                // Errorhandling. Should not happen though!
            }
        }
    }
}

Чтобы использовать этот фильтр:

Client client = Client.create();
webResource = client.resource("http://localhost:8080/pathToYourResource");

contentMD5filter = new ContentMD5Filter();
webResource.addFilter(contentMD5filter);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...