CXF: добавление неявных заголовков в ответы WSDL и WADL для веб-службы SOAP/REST CXF

Я пытаюсь добавить неявные заголовки в ответы WSDL и WADL для веб-службы SOAP/REST CXF (которой управляет Camel).

(Это не обязательно заголовки безопасности....)

Под "неявным заголовком" я подразумеваю, что попадание URL-адреса WSDL/WADL в службу покажет, что ожидается, что клиент предоставит заголовок в запросе.

Но я не хочу явно указывать заголовок в сигнатуре веб-службы.

У меня есть перехватчик CXF, который добавляет неявный заголовок для каждого ответа SOAP/REST.

Итак, поскольку WSDL/WADL-документ отправляется как ответ на некоторый запрос GET, я думал каким-то образом использовать аналогичный перехватчик, чтобы добавить данные заголовка в ответ WSDL/WADL. Как я мог выполнить такой чудесный подвиг?

Вот перехватчик CXF, который добавляет неявный заголовок для каждого ответа SOAP/REST:

public class MyInterceptor extends AbstractPhaseInterceptor<Message> {

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

    @Override
    public void handleMessage(Message message)
    {   
        try
        {
            //soap
            if (message instanceof SoapMessage)
            {               
                List<Header> headers = ((SoapMessage)message).getHeaders();

                Header dummyHeader = new Header(new QName("uri:org.apache.cxf", "dummy"), "decapitated", new JAXBDataBinding(String.class));

                headers.add(dummyHeader);
            }
            //rest
            else
            {
                Map<String, List> headers = (Map<String, List>) message.get(Message.PROTOCOL_HEADERS);

                String dummyHeader = "decapitated";

                headers.put("dummy", Collections.singletonList(dummyHeader));
            }

        }
        catch (JAXBException e)
        {
            throw new Fault(e);
        }
    }

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

Ответ 1

CXF 2.7.4

В CXF WSDL генерируется через Interceptor в цепочке, называемой WSDLGetInterceptor, которая помещается в цепочку READ.

Основной дизайн

  • проверьте, является ли вызов HTTP GET
  • подготовить выходное сообщение для возврата
  • доступ к wsdl (из Java или из статического источника)
  • записать wsdl в выходное сообщение
  • прервать цепочку перехватчиков, чтобы обеспечить выходное сообщение

Самый простой способ действовать в этом процессе - упредить этот перехватчик от выполнения своей работы, либо зарегистрировав свою собственную реализацию раньше.

Удаление стандартных перехватчиков CXF - это "трудная задача" на шине по умолчанию (самый простой способ - зарегистрировать свой собственный перехватчик, перенести его первым в цепочку и сделать так, чтобы он удалял другие перехватчики таким образом message.getInterceptorChain().remove(removeInterceptor);

Но добавление ваших собственных непосредственно перед тем, как стандартный перехватчик WSDL прост:

public MyWSDLGetInterceptor() {
    super(Phase.READ);
    addBefore(WSDLGetInterceptor.class.getName());
}

MyWSDLGetInterceptor будет расширять стандартный WSDLGetInterceptor, и вы только переопределяете:

public Document getDocument(Message message,
                            String base,
                            Map<String, String> params,
                            String ctxUri,
                            EndpointInfo endpointInfo) {
    Document domDocument = super.getDocument(message, base, params, ctxUri, endpointInfo);
    domDocument.getChildNodes(); // Whatever you need to add remove
    return domDocument; // Once modified
}

Вы можете изменить полученный DOM-документ на лету (добавить/создать узлы DOM) или через XSLT, что вам больше подходит, вы вернетесь к стандартному XML-стандарту через стандартный API.

CXF 2.7.x(где x находится где-то > 4 и < 10)

Принцип тот же, но перехватчик работает по-разному.

  • Он (в частном методе) помещает WSDL в качестве документа DOM как свойство исходящего сообщения
  • Он очищает цепочку выходных перехватчиков всех перехватчиков (за исключением абсолютной необходимости)
  • Он регистрирует WSDLGetOutInterceptor в цепочке вывода
  • Он останавливает цепочку IN и переходит к цепочке останова
  • WSDLGetOutInterceptor выполняет сериализацию

Так что это немного сложнее/менее чисто. Но используя тот же принцип предотвращения базового перехватчика (зарегистрировавшись непосредственно перед этим), вы можете переопределить cleanUpOutInteceptors, чтобы манипулировать сообщением, как и в случае 2.7.4, путем доступа к WSDL через outMessage.get(DOCUMENT_HOLDER)

WADL

Извините, у меня нет опыта, но я думаю, что CXF имеет такую ​​же архитектуру для обоих...