Как читать полезную нагрузку в Jersey Client - PullRequest
0 голосов
/ 30 ноября 2018

У меня есть небольшая проблема здесь.При создании запроса я хочу подписать все сообщение с помощью HMAC и добавить полученную подпись к заголовкам.

Итак, я реализовал

javax.ws.rs.ext.WriterInterceptorContext

В

public void aroundWriteTo(WriterInterceptorContext context) throws IOException, WebApplicationException

метод я не могу получить доступ к строковому представлению объекта.Всегда возвращает пустую строку.Кажется, причиной является MessageBodyWriter, который выполняется ПОСЛЕ WriterInterceptor.

В основном у меня следующие два сценария сбоя:

public void aroundWriteTo(WriterInterceptorContext context) throws IOException, WebApplicationException {
    try {
        final ClientOutputStream stream = (ClientOutputStream) requestContext.getProperty(HTTPCLIENT_ENTITY_STREAM);
        String payload = stream.getString(Charset.forName("UTF-8")); // returns alway empty String
        String signature = doSomeSuffWithPayload(payload);

        MultivaluedMap<String, Object> headers = context.getHeaders();
        headers.add(HmacHeaderValue.X_SIGNATURE.headerName(), signature);
        context.proceed();
    } catch (IllegalArgumentException | ParseException | InvalidKeyException | NoSuchAlgorithmException ex) {
        LOGGER.error(ex.getMessage());
    } catch (UnsupportedEncodingException ex) {
        LOGGER.error(ex.getMessage());
    } catch (IOException ex) {
        LOGGER.error(ex.getMessage());
    }
}

Здесь метод doSomeSuffWithPayload (payload) не работает, потому чтополезная нагрузка всегда пуста.

Я думал, что уловка сделает это, поэтому я переключил вызов context.proceed () на любое другое место:

public void aroundWriteTo(WriterInterceptorContext context) throws IOException, WebApplicationException {
    try {
        context.proceed();
        final ClientOutputStream stream = (ClientOutputStream) requestContext.getProperty(HTTPCLIENT_ENTITY_STREAM);
        String payload = stream.getString(Charset.forName("UTF-8")); // returns the right string representation
        String signature = doSomeSuffWithPayload(payload);

        MultivaluedMap<String, Object> headers = context.getHeaders();
        headers.add(HmacHeaderValue.X_SIGNATURE.headerName(), signature); // doesn't add the header
    } catch (IllegalArgumentException | ParseException | InvalidKeyException | NoSuchAlgorithmException ex) {
        LOGGER.error(ex.getMessage());
    } catch (UnsupportedEncodingException ex) {
        LOGGER.error(ex.getMessage());
    } catch (IOException ex) {
        LOGGER.error(ex.getMessage());
    }
}

В этом случае строковое представлениесущность в порядке.Но добавление заголовка к запросу не работает.

Таким образом, я могу добавить (неверную) подпись в заголовки и всегда пустую сущность ИЛИ правильную подпись с правильной сущностью, но заголовокне добавлено.

Мой вопрос: кто-нибудь знает способ получить строковое представление сущности с помощью WriterInterceptor?

EDITH сказал:

Мы используем версию2.25.1 Джерси клиента.2.27 тоже не решила проблему.

1 Ответ

0 голосов
/ 03 декабря 2018

После глубокого поиска в API я обнаружил, что сущность действительно записывается после WriterInterceptor в MessageBodyWriter.Кроме того, заголовки также добавляются во время процесса в MessageBodyWriter.Вот почему оба вышеприведенных подхода не работают.

Мое решение состоит в том, чтобы создать правильный MessageBodyWriter и позволить ему сериализовать сущность, как это было бы в MessageBodyWriter, который выполняется после WriterInterceptor.В этом случае WriterInterceptor больше не нужен, реализация ClientRequestFilter сделает свое дело.

import javax.ws.rs.ext.MessageBodyWriter;
import javax.ws.rs.ext.Providers;

@Context
private Providers providers;

private String getPayloadFromRequest(ClientRequestContext requestContext) throws IOException {
    Object object = requestContext.getEntity();
    if (object != null) {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        try {
            // buffer into which myBean will be serialized
            Class<Object> type = (Class<Object>) requestContext
                    .getEntityClass();
            GenericType<Object> genericType = new GenericType<Object>(type) {
            };

            // get most appropriate MBW
            final MessageBodyWriter<Object> messageBodyWriter = providers
                    .getMessageBodyWriter(type, type, new Annotation[]{},
                            MediaType.APPLICATION_JSON_TYPE);

            try {
                // use the MBW to serialize myBean into baos
                messageBodyWriter.writeTo(object, object.getClass(),
                        genericType.getType(), new Annotation[]{},
                        MediaType.APPLICATION_JSON_TYPE,
                        new MultivaluedHashMap<String, Object>(), baos);
            } catch (IOException e) {
                throw new RuntimeException(
                        "Error while serializing MyBean.", e);
            }

            return baos.toString();
        } finally {
            baos.close();
        }

    } else {
        return "";
    }
}

Код не мой, но, к сожалению, я потерял источник.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...