Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

WCF http service via https load balancer

I have a WCF webservice that can be accessed via a http endpoint. Now, this service shall be published with a load balancer via https. Clients are created in .Net via svcutil.exe but the WSDL is also needed for a Java client.

What I understand is:

  • Internally the webservice is a http service and nothing needs to be changed. The address is http://myserver.com/example.svc with WSDL ..?wsdl
  • Externally the service has to show up as a https service with address https://loadbalancer.com/example.svc and WSDL ..?wsdl

From other posts I have learned that the load balancer problem can be solved with following behaviour configuration:

    <behavior>
      <!-- To avoid disclosing metadata information, set the value below to false before deployment -->
      <serviceMetadata httpGetEnabled="true"/>
      <useRequestHeadersForMetadataAddress>
        <defaultPorts>
          <!-- Use your own port numbers -->
          <add scheme="http" port="81" />
          <add scheme="https" port="444" />
        </defaultPorts>
      </useRequestHeadersForMetadataAddress>
    </behavior>

Using this workaround I get both URLs resolved to the services help page, but calling https://loadbalancer.com/example.svc the page leads me to http://loadbalancer.com/example.svc?wsdl. When I replace the http by https I can load the wsdl but it has all internal links as http and not https.

Trying to switch httpsGetEnabled="true" leads me to a lot of https related issues and I don't know if this can help me as my server itself only knows http.

So, my problem is the https for the load balanced URL. Can I tell WCF that it shall show https in the WSDL meta data instead of http and how can I do this?

like image 882
Peter Buchmann Avatar asked Nov 05 '13 12:11

Peter Buchmann


1 Answers

I have had this issue before and the fix pretty much was overriding the SoapExtensionReflector method name: ReflectDescription.

using System.Web.Services.Description;
namespace LoadBalancer
{
    public class HttpsSoapExtensionReflector : SoapExtensionReflector
    {
        public override void ReflectMethod()
        {
            //no-op
        }

    public override void ReflectDescription()
    {
        ServiceDescription description = ReflectionContext.ServiceDescription; 
        foreach (Service service in description.Services)
        {
            foreach (Port port in service.Ports)
            {
                foreach (ServiceDescriptionFormatExtension extension in port.Extensions)
                {
                    SoapAddressBinding binding = extension as SoapAddressBinding;
                    if (null != binding)
                    {
                        binding.Location = binding.Location.Replace("http://", "https://");//Updating the soap address binding location to use https
                    }
                }
            }
        }            

    }
    }
}

Once you create the above class into a new or an existing dll project (In my example the dll name is LoadBalancer) you just need to invoke our new extension from the server web config like:

<webServices>
  <soapExtensionReflectorTypes>
    <add type="LoadBalancer.HttpsSoapExtensionReflector, LoadBalancer"/>
  </soapExtensionReflectorTypes>
</webServices>

If it is under LoadBalancer then it will go ahead and modify the binding location and it will be generate the WSDL with the HTTPS url. Tested on SoapUI and from Visual Studio adding service references (app.config will reflect https). Thanks

like image 155
Ernest Avatar answered Sep 20 '22 23:09

Ernest