Настройка размера загрузки Apache CXF

Я использую cxf 2.4.4 для создания веб-сервисов RESTful.

У меня есть эта услуга:

@WebService
public interface Remote {
    @POST
    @Path("/create")
    @Consumes(MediaType.MULTIPART_FORM_DATA)
    @Produces(MediaType.APPLICATION_XML)
    public CustomXML makerService(); 
}

который потребляет MULTIPART_FORM_DATA.

Я хочу ограничить размер вложений. Я нашел эту документацию, и она работает, за исключением того, что он возвращает HTTP 500 status.

Пожалуйста, я хочу знать, как вернуть другой статус (HTTP 413 status как и ожидалось) или, может быть, поймать это исключение и повторно выдать его.

EDIT
Мне удалось сделать это через перехватчики, вот так

@Service("remote")
@InInterceptors(interceptors = {"myCompany.AttachmentInInterceptor"})
public class RemoteImpl implements Remote {
    ...
}

и перехватчик:

public class AttachmentInInterceptor extends AbstractPhaseInterceptor<Message> {

    public AttachmentInInterceptor() {
        super(Phase.RECEIVE);
    }

    public void handleMessage(Message message) {
        String contentType = (String) message.get(Message.CONTENT_TYPE);
        Map<String, List<String>> headers;

        if (contentType != null && contentType.toLowerCase().indexOf("multipart/form-data") >= 0) {
            AttachmentDeserializer ad = new AttachmentDeserializer(message);

            headers = (Map<String, List<String>>) message.get(Message.PROTOCOL_HEADERS);
            String len = headers.get("Content-Length").toString();
            len = len.replaceAll("\\[", "");
            len = len.replaceAll("\\]", "");

            Long length = Long.valueOf(len);
            if (length > 100000000) {
                throw new Fault(new CustomException("Archivo grande", ErrorCode.ERROR.getCode()));
            }
            try {
                ad.initializeAttachments();
            } catch (IOException e) {
                throw new Fault(e);
            }
        }
    }

    @Override
    public void handleFault(Message message) {
    }
}

но я все еще не могу отправить требуемый ответ (HTTP 413 status)

Я благодарю любую помощь заранее


person Marco Aviles    schedule 02.12.2011    source источник


Ответы (2)


Изучение исходный код CXF указывает, что результаты, отличные от 500, возвращаются путем создания javax.ws.rs.WebApplicationException; это подкласс RuntimeException — поэтому вам не нужно его объявлять — и у него есть конструктор с одним аргументом, который принимает код ответа (или вы можете создать полный Response или что-то еще, что вам действительно нравится).

person Donal Fellows    schedule 04.12.2011
comment
привет, спасибо за ваш ответ. Я попробовал то, что вы сказали, но я все равно получаю 500, когда выполняю http-запрос от клиента. Не знаю, что я делаю неправильно - person Marco Aviles; 06.12.2011
comment
@MHero: Это очень странно; возможно, вам следует поднять ошибку против CXF, учитывая, что это должно работать (также, предполагая, что вы не установили другой фильтр, который вызывает преобразование в 500; я делал подобные глупости в прошлом)… - person Donal Fellows; 06.12.2011

приведенный ниже код возвращает 413

import java.io.IOException;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.util.List;
import java.util.Map;

import org.apache.cxf.endpoint.Endpoint;
import org.apache.cxf.helpers.CastUtils;
import org.apache.cxf.message.Exchange;
import org.apache.cxf.message.Message;
import org.apache.cxf.message.MessageImpl;
import org.apache.cxf.phase.AbstractPhaseInterceptor;
import org.apache.cxf.phase.Phase;
import org.apache.cxf.transport.Conduit;
import org.apache.cxf.ws.addressing.EndpointReferenceType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class AttachmentInInterceptor extends AbstractPhaseInterceptor<Message> {

private static final Long MAX_SIZE = 2048L * 1024L;
private static final Logger LOGGER = LoggerFactory.getLogger(BaseCxfInterceptor.class);

public AttachmentInInterceptor() {
    super(Phase.RECEIVE);
}

public void handleMessage(Message message) {
    String contentType = (String) message.get(Message.CONTENT_TYPE);
    if (contentType != null && contentType.toLowerCase().indexOf("multipart/form-data") >= 0) {
        Map<String, List<String>> headers = CastUtils.cast((Map<?,?>)message.get(Message.PROTOCOL_HEADERS));
        String len = headers.get("Content-Length").toString();
        len = len.replaceAll("\\[", "");
        len = len.replaceAll("\\]", "");
        Long length = Long.valueOf(len);
        if (length > MAX_SIZE) {
            replyEntityTooLarge(message);
        }
    }
}

private void replyEntityTooLarge(Message message) {
    Message outMessage = getOutMessage(message);
    outMessage.put(Message.RESPONSE_CODE, 
            HttpURLConnection.HTTP_ENTITY_TOO_LARGE);

    message.getInterceptorChain().abort();
    try {
        getConduit(message).prepare(outMessage);
        OutputStream os = message.getContent(OutputStream.class);
        os.flush();
        os.close();
    } catch (IOException e) {
        LOGGER.error("Erro no interceptor do cxf {}",e);
        throw new RuntimeException(e);
    }   
}

private Message getOutMessage(Message message) {
    Exchange exchange = message.getExchange();
    Message outMessage = exchange.getOutMessage();
    if (outMessage == null) {
        Endpoint endpoint = exchange.get(Endpoint.class);
        outMessage = new MessageImpl();
        outMessage.setExchange(exchange);
        outMessage = endpoint.getBinding().createMessage(outMessage);
        exchange.setOutMessage(outMessage);
    }
    outMessage.putAll(message);
    return outMessage;
}

private Conduit getConduit(Message message) throws IOException {
    Exchange exchange = message.getExchange();
    EndpointReferenceType target = 
        exchange.get(EndpointReferenceType.class);
    Conduit conduit =
        exchange.getDestination().getBackChannel(message, null, target);
    exchange.setConduit(conduit);
    return conduit;
}
}
person user2215355    schedule 05.12.2013
comment
Это дает исключение java.lang.NullPointerException: null at os.flush(); - person Eduardo; 16.09.2016