Uploaded image for project: 'XML-RPC'
  1. XML-RPC
  2. XMLRPC-188

XmlRpcCommonsTransportFactory ignores httpclient HostConfiguration while creating PostMethod object

    XMLWordPrintableJSON

Details

    • Bug
    • Status: Open
    • Major
    • Resolution: Unresolved
    • 3.1.3
    • None
    • Source
    • None

    Description

      I am trying to connect to XmlRpc server through SSL using a self signed certificate.
      For that I am using commons httpclient transport together with AuthSSLProtocolSocketFactory from httpclient 3.1 contrib section.

      Here's my setup code:

      XmlRpcClientConfigImpl xmlRpcConfig = new XmlRpcClientConfigImpl();
      xmlRpcConfig.setServerURL(serverUrl);
      
      XmlRpcClient xmlRpcClient = new XmlRpcClient();
      xmlRpcClient.setConfig(xmlRpcConfig);
      
      ProtocolSocketFactory sslSocketFactory = new AuthSSLProtocolSocketFactory(null,  null, keyStoreUrl, keyStorePass);
      Protocol protocol = new Protocol("https", sslSocketFactory, serverUrl.getPort());
      
      HttpClient httpClient = new HttpClient();
      httpClient.getHostConfiguration().setHost(serverUrl.getHost(), serverUrl.getPort(), protocol);
      
      XmlRpcCommonsTransportFactory transportFactory = new XmlRpcCommonsTransportFactory(xmlRpcClient);
      transportFactory.setHttpClient(httpClient);
      xmlRpcClient.setTransportFactory(transportFactory);
      

      Unfortunately, when the request is being made, XmlRpcCommonsTransport.newPostMethod(XmlRpcHttpClientConfig pConfig) is executed and it creates the PostMethod object in the following way:

      return new PostMethod(pConfig.getServerURL().toString());

      When XmlRpcCommonsTransport.writeRequest(final ReqWriter pWriter) execution, HttpClient.executeMethod(HttpMethod method) is invoked. It calls HttpClient.executeMethod(HostConfiguration hostconfig, final HttpMethod method, final HttpState state) with null hostconfig parameter. This combined with the fact that PostMethod uri is absolute, causes hostconfig to be initialized from scratch using the URI. Whatever host configuration was provided by the user through HttpClient.getHostConfiguration().setHost(...) is ignored.

      I am aware that I could override httpclient's protocol handler for https using Protocol.registerProtocol(String id, Protocol protocol) call, but that would have ClassLoader wide scope, which is not something a "good citizen" application component should do.

      In order to circumvent this issue I have subclassed XmlRpcCommonsTransport to override PostMethod newPostMethod(XmlRpcHttpClientConfig pConfig) as follows:

          protected PostMethod newPostMethod(XmlRpcHttpClientConfig pConfig)
          {
              HostConfiguration hostConfiguration = client.getHostConfiguration();
              URL requestUrl = pConfig.getServerURL();
              if(hostConfig != null)
              {
                  if(requestUrl.getProtocol().equals(hostConfiguration.getProtocol().getScheme())
                      && requestUrl.getHost().equals(hostConfiguration.getHost())
                      && requestUrl.getPort() == hostConfiguration.getPort())
                  {
                      // use URI relative to base URI determined by HostConfiguration
                      return new PostMethod(requestUrl.getFile());
                  }
                  else
                  {
                      throw new IllegalArgumentException("Server URL " + requestUrl
                          + "does not agree with HttpClient host configuration " + hostConfiguration);
                  }
              }
              // use absolute URI
              return new PostMethod(requestUrl.toString());
          }
      

      If the user bothered to set a custom HostConfiguration but used different server base URL for the XmlRpcClient, the method throws an exception. I think it'll help the user to spot the configuration error earlier.

      Using this derived class (and matching XmlRpcCommonsTransportFactory) I was able to connect to the server using SSL with self signed certificate loaded from JKS keystore loaded into AuthSSLProtocolSocketFactory.

      Attachments

        Activity

          People

            Unassigned Unassigned
            rkrzewsk Rafal Krzewski
            Votes:
            0 Vote for this issue
            Watchers:
            0 Start watching this issue

            Dates

              Created:
              Updated: