Camel
  1. Camel
  2. CAMEL-3806

SOAPAction HTTP header value not copied correctly to from CXF message to Camel message header

    Details

    • Type: Bug Bug
    • Status: Closed
    • Priority: Major Major
    • Resolution: Fixed
    • Affects Version/s: 2.6.0
    • Fix Version/s: 2.7.3, 2.8.0
    • Component/s: camel-cxf
    • Environment:

      camel-cxf, CXF consumer endpoint with PAYLOAD data format

      Description

      When using camel-cxf consumer endpoint with PAYLOAD data format, the SoapActionInInterceptor correctly strips off any double quotes surrounding the SOAPAction header value, e.g:

      SOAPAction: "http://apache.org/hello_world_soap_http/greetMe"
      

      and then sets this header on the message again:

      SoapActionInInterceptor.java
      public void handleMessage(SoapMessage message) throws Fault {
              String action = getSoapAction(message);
              if (!StringUtils.isEmpty(action)) {
                  getAndSetOperation(message, action);
              }
          }
      

      After the execution of getAndSetOperation(message, action), there are two SOAPAction headers set on the message. The original SOAPAction header value (with surrounding quotes) is part of the org.apache.cxf.message.Message.PROTOCOL_HEADERS. In addition the getAndSetOperation() method also adds
      SOAPAction=http://apache.org/hello_world_soap_http/greetMe header (without surrounding quotes).

      Later in org.apache.camel.component.cxf.DefaultCxfBinding.propagateHeadersFromCxfToCamel(), when the CXF message headers get copied to the Camel message, it only retrieves the org.apache.cxf.message.Message.PROTOCOL_HEADERS:

      Map<String, List<String>> cxfHeaders = (Map)cxfMessage.get(Message.PROTOCOL_HEADERS);
      

      The SOAPAction header in PROTOCOL_HEADERS wasn't changed by the SoapActionInInterceptor and hence still has enclosed double quotes. These headers then get copied to the Camel In message headers. The header that was set by the SoapActionInInterceptor SOAPAction=http://apache.org/hello_world_soap_http/greetMe does not get copied!

      If later in a Camel route a custom Camel Processor tries to resolve this SOAPAction header, it gets the the value with surrounding double quotes, but these should actually have been stripped off.

      This behavior is a bug.

      1. testcase.zip
        10 kB
        Torsten Mielke

        Activity

        Hide
        Torsten Mielke added a comment -

        Attaching JUnit test. It currently fails but will succeed if the SOAPAction header value is not enclosed by double quotes.

        Show
        Torsten Mielke added a comment - Attaching JUnit test. It currently fails but will succeed if the SOAPAction header value is not enclosed by double quotes.
        Hide
        Torsten Mielke added a comment -

        I see two solutions:

        1) copy all CXF headers into Camel in message headers:

        org.apache.camel.component.cxf.DefaultCxfBinding.java
        // pseudo code
        protected void propagateHeadersFromCxfToCamel(Message cxfMessage,
                    org.apache.camel.Message camelMessage, Exchange exchange) {
                Map<String, List<String>> cxfHeaders = (Map)cxfMessage.getHeaders()
                Map<String, Object> camelHeaders = camelMessage.getHeaders();
                camelHeaders.put(CxfConstants.CAMEL_CXF_MESSAGE, cxfMessage);
        ...
        

        This should also copy the SOAPAction header that the SoapActionInInterceptor added to the message.

        2) Have the SoapActionInInterceptor strip off the surrounding double quote from the SOAPAction header (which it does already) and replace the SOAPAction header in the already populated org.apache.cxf.message.Message.PROTOCOL_HEADERS with the modified (stripped off) value.
        That way org.apache.camel.component.cxf.DefaultCxfBinding.java does not need to be changed.

        I personally kinda prefer the second option.

        Show
        Torsten Mielke added a comment - I see two solutions: 1) copy all CXF headers into Camel in message headers: org.apache.camel.component.cxf.DefaultCxfBinding.java // pseudo code protected void propagateHeadersFromCxfToCamel(Message cxfMessage, org.apache.camel.Message camelMessage, Exchange exchange) { Map< String , List< String >> cxfHeaders = (Map)cxfMessage.getHeaders() Map< String , Object > camelHeaders = camelMessage.getHeaders(); camelHeaders.put(CxfConstants.CAMEL_CXF_MESSAGE, cxfMessage); ... This should also copy the SOAPAction header that the SoapActionInInterceptor added to the message. 2) Have the SoapActionInInterceptor strip off the surrounding double quote from the SOAPAction header (which it does already) and replace the SOAPAction header in the already populated org.apache.cxf.message.Message.PROTOCOL_HEADERS with the modified (stripped off) value. That way org.apache.camel.component.cxf.DefaultCxfBinding.java does not need to be changed. I personally kinda prefer the second option.
        Hide
        Claus Ibsen added a comment -

        Willem can you take a look? We should strip off double quotes from the value IMHO

        Show
        Claus Ibsen added a comment - Willem can you take a look? We should strip off double quotes from the value IMHO
        Hide
        Claus Ibsen added a comment -

        Btw which client put quotes in the value? I actually wonder if that's really best practice, and allowed to do?

        Show
        Claus Ibsen added a comment - Btw which client put quotes in the value? I actually wonder if that's really best practice, and allowed to do?
        Hide
        Willem Jiang added a comment - - edited

        Because SOAP11 and SOAP12 send the SOAPAction with different protocol:
        SOAP11 uses SOAPAction="xxx" http header,
        SOAP12 uses action="xxx" as a part of content-type
        If we want to provides the user with consistence result, we need to store the result with key of "SOAPAction" for common using, CXF SOAPActionInterceptor takes care of it and strip the "/"" for using. In camel-cxf we copy the PROTOCOL_HEADER directly into the Camel message header, if the user using SOAP11 binding, the SOAPAction is also a part of the PROTOOL_HEADER. If the user want to get the message header of SOAPAction, he will get.
        If the user using SOAP12 binding, he can't get any value with the message header of SOAPAction.

        SO my suggestion is we just put the SOAPAction header from CXF message into camel message, in this way the user can get this kind of the message header directly from the camel message whatever the soap binding is.

        Willem

        Show
        Willem Jiang added a comment - - edited Because SOAP11 and SOAP12 send the SOAPAction with different protocol: SOAP11 uses SOAPAction="xxx" http header, SOAP12 uses action="xxx" as a part of content-type If we want to provides the user with consistence result, we need to store the result with key of "SOAPAction" for common using, CXF SOAPActionInterceptor takes care of it and strip the "/"" for using. In camel-cxf we copy the PROTOCOL_HEADER directly into the Camel message header, if the user using SOAP11 binding, the SOAPAction is also a part of the PROTOOL_HEADER. If the user want to get the message header of SOAPAction, he will get. If the user using SOAP12 binding, he can't get any value with the message header of SOAPAction. SO my suggestion is we just put the SOAPAction header from CXF message into camel message, in this way the user can get this kind of the message header directly from the camel message whatever the soap binding is. Willem
        Hide
        Torsten Mielke added a comment -

        Btw which client put quotes in the value? I actually wonder if that's really best practice, and allowed to do?

        According to the SOAP 1.1 spec, the SOAPAction header value needs to be enclosed by double quotes. Here an extract of the grammar defining the SOAPAction header:

        soapaction = "SOAPAction" ":" [ <"> URI-reference <"> ]
        URI-reference = <as defined in RFC 2396 [4]>

        CXF also generates double quotes around the SOAPAction header value.

        Show
        Torsten Mielke added a comment - Btw which client put quotes in the value? I actually wonder if that's really best practice, and allowed to do? According to the SOAP 1.1 spec , the SOAPAction header value needs to be enclosed by double quotes. Here an extract of the grammar defining the SOAPAction header: soapaction = "SOAPAction" ":" [ <"> URI-reference <"> ] URI-reference = <as defined in RFC 2396 [4] > CXF also generates double quotes around the SOAPAction header value.
        Hide
        Willem Jiang added a comment -

        Committed a patch to fix this issue.
        For the Message data formate, as the SOAPActionInInterceptor is not installed, the use can still get the SOAPAction header with double quotes surrounding.

        Show
        Willem Jiang added a comment - Committed a patch to fix this issue. For the Message data formate, as the SOAPActionInInterceptor is not installed, the use can still get the SOAPAction header with double quotes surrounding.

          People

          • Assignee:
            Willem Jiang
            Reporter:
            Torsten Mielke
          • Votes:
            1 Vote for this issue
            Watchers:
            1 Start watching this issue

            Dates

            • Created:
              Updated:
              Resolved:

              Development