[Mono-bugs] [Bug 687580] New: Mono 2.10.1WCF fails with '(400) Bad Request' when the calling client uses URIs that should be functionally equivalent such as IP address instead of machine name

bugzilla_noreply at novell.com bugzilla_noreply at novell.com
Thu Apr 14 11:50:19 EDT 2011


https://bugzilla.novell.com/show_bug.cgi?id=687580

https://bugzilla.novell.com/show_bug.cgi?id=687580#c0


           Summary: Mono 2.10.1WCF fails with '(400) Bad Request' when the
                    calling client uses URIs that should be functionally
                    equivalent such as IP address instead of machine name
    Classification: Mono
           Product: Mono: Runtime
           Version: 2.10.x
          Platform: 64bit
        OS/Version: Windows Server 2008 R2
            Status: NEW
          Severity: Normal
          Priority: P5 - None
         Component: remoting
        AssignedTo: lluis at novell.com
        ReportedBy: emily.lewis at lumension.com
         QAContact: mono-bugs at lists.ximian.com
          Found By: ---
           Blocker: ---


Created an attachment (id=424965)
 --> (http://bugzilla.novell.com/attachment.cgi?id=424965)
This is a working example to reproduces the bug

User-Agent:       Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64;
Trident/5.0)

I am presently evaluating whether mono 2.10 WCF is stable enough for a project
we are working on. I have written a very simple WCF REST client/server test jig
upon which to make this assessment and for the most part it works. However it
has revealed some oddity in URI syntax that I don't understand - this oddity
only shows up in mono whereas it works fine in Microsoft.NET on windows. I
would like to know if this behavior is normal for mono, or simply a known or
new bug. My searches in bugzilla seem to indicate this exact bug isn't
reported.

To understand the issue, consider that when I run my WCF server I add a service
endpoint with the URI "http://localhost:8080/ProfileREST". Of course, on the
client side I also connect using an endpoint address with the URI
"http://localhost:8080/ProfileREST" and that works fine. 

I have discovered however, that mono is very literal about these URIs. For
example, if I run my server with the URI "http://localhost:8080/ProfileREST"
the client can ONLY connect using the like URI
"http://localhost:8080/ProfileREST". If I try to connect the client instead to
say a URI with my explicit machine name "http://mymachinename:8080/ProfileREST"
or even its IP address "http://10.12.12.161:8080/ProfileREST" I receive this
error on the client (and no error on the server):

System.ServiceModel.ProtocolException Message The remote server returned an
unexpected response: (400) Bad Request. Stack Server stack trace: at
System.ServiceModel.Channels.HttpChannelUtilities.ValidateRequestRe
plyResponse(HttpWebRequest request, HttpWebResponse response,
HttpChannelFactory factory, WebException responseException, ChannelBinding
channelBinding) at
System.ServiceModel.Channels.HttpChannelFactory.HttpRequestChannel.
HttpChannelRequest.WaitForReply(TimeSpan timeout) at
System.ServiceModel.Channels.RequestChannel.Request(Message message , TimeSpan
timeout) at System.ServiceModel.Dispatcher.RequestChannelBinder.Request(Message
message, TimeSpan timeout) at
System.ServiceModel.Channels.ServiceChannel.Call(String action, Boo lean
oneway, ProxyOperationRuntime operation, Object[] ins, Object[] outs, TimeS pan
timeout) at System.ServiceModel.Channels.ServiceChannelProxy.InvokeService(IMet
hodCallMessage methodCall, ProxyOperationRuntime operation) at
System.ServiceModel.Channels.ServiceChannelProxy.Invoke(IMessage me ssage)
Exception rethrown at [0]: at
System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage(IMess age reqMsg,
IMessage retMsg) at
System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(MessageData & msgData,
Int32 type) at client.IProfileREST.Ping() at
client.ProfileRESTClient.client.IProfileREST.Ping() in c:\temp\FunW
ithMonoRESTClient\client\Program.cs:line 35 at client.Program.DoMain(String[]
args) in c:\temp\FunWithMonoRESTClie nt\client\Program.cs:line 79 at
client.Program.Main(String[] args) in c:\temp\FunWithMonoRESTClient
\client\Program.cs:line 54 ---->System.Net.WebException Message The remote
server returned an error: (400) Bad Request. Stack at
System.Net.HttpWebRequest.GetResponse() at
System.ServiceModel.Channels.HttpChannelFactory.HttpRequestCha
nnel.HttpChannelRequest.WaitForReply(TimeSpan timeout)

Here are the details of my test setup (I have included the fully Visual Studio
2010 solution in an attachment as well):

Contract

    [ServiceContract]
    public interface IProfileREST
    {
      [OperationContract, WebGet(UriTemplate = "Ping")]
      void Ping();
    }

Server 

    [ServiceBehavior
        (
            InstanceContextMode = InstanceContextMode    .Single        , 
            ConcurrencyMode        = ConcurrencyMode        .Multiple
        )
    ]
    public class ProfileRest : IProfileREST
    {
        #region members
        long _hits = 0;
        #endregion

        #region .ctor
        public ProfileRest()
        {
        }
        #endregion

        #region IProfileREST
        void IProfileREST.Ping()
        {
            Console.WriteLine("Ping {0}",Interlocked.Increment(ref _hits));
        }
        #endregion
    }

        static void Main(string[] args)
        {
            var address = new Uri("http://localhost:8080/ProfileREST");
            var binding    = new WebHttpBinding ();
            var server    = new ProfileRest();
            var host    = new WebServiceHost(server);
            host.AddServiceEndpoint(typeof(IProfileREST), binding, address);
            host.Open();

            Console.WriteLine("The server is running, press a key to stop...");
            Console.ReadKey();
        }


Client

    public class ProfileRESTClient : ClientBase<IProfileREST>, IProfileREST
    {
        #region .ctor
        public ProfileRESTClient() : base()
        {
        }

        public ProfileRESTClient(Binding binding, EndpointAddress address) :
base(binding, address) 
        {
            base.Endpoint.Behaviors.Add(new WebHttpBehavior());
        }
        #endregion

        #region IProfileREST
        void IProfileREST.Ping()
        {
            base.Channel.Ping();
        }
        #endregion
    }

        static void Main(string[] args)
        {
            EndpointAddress address = new EndpointAddress(new
Uri("http://localhost:8080/ProfileREST"));
            Binding binding = new WebHttpBinding();
            using (IProfileREST client = new ProfileRESTClient(binding,
address))
            {
                client.Ping();
            }
        }



Here is a Wireshark dump of the inbound request:

GET /ProfileREST/Ping HTTP/1.1\r\n    [Expert Info (Chat/Sequence): GET
/ProfileREST/Ping HTTP/1.1\r\n]    Request Method: GET    Request URI:
/ProfileREST/Ping    Request Version: HTTP/1.1Content-Type: application/xml;
charset=utf-8\r\nHost: elewisdesktopr2:8080\r\nAccept-Encoding: gzip,
deflate\r\nConnection: Keep-Alive\r\n

And the response:

HTTP/1.1 400 Bad Request\r\n    [Expert Info (Chat/Sequence): HTTP/1.1 400 Bad
Request\r\n]    Request Version: HTTP/1.1    Response Code: 400Content-Type:
text/html; charset=Windows-1252\r\nServer: Mono-HTTPAPI/1.0\r\nDate: Wed, 13
Apr 2011 17:40:17 GMT\r\nContent-Length: 35\r\nConnection: close\r\n

I have noticed that when I run the server under Microsoft .NET, TCPView reports
the following ports open:

System    4    TCP    elewisdesktopr2    8080    elewisdesktopr2    0   
LISTENING                            
System    4    TCPV6    elewisdesktopr2.patchlink.com    8080   
elewisdesktopr2.patchlink.com    0    LISTENING                                 

When I run the server under mono I see this:

mono.exe    1816    TCP    elewisdesktopr2    8080    elewisdesktopr2    0   
LISTENING                            
mono.exe    1816    TCP    elewisdesktopr2    64935    localhost    64934   
ESTABLISHED                        
mono.exe    1816    TCP    elewisdesktopr2    64934    localhost    64935   
ESTABLISHED                                        


Reproducible: Always

Steps to Reproduce:
1. Open the attach solution and build it
2. Run the server under mono
3. Run the client under windows (a different bug appears to prevent the client
from working in mono, I will report that in a different bug).
4. Observe that the client connects to the server and the server prints out the
message "Ping 1".
5. Edit the client's "Program.cs" file and replace the line:

EndpointAddress address = new EndpointAddress(new
Uri("http://localhost:8080/ProfileREST"));

With 

EndpointAddress address = new EndpointAddress(new
Uri("http://YOURMACHINENAME:8080/ProfileREST"));

Where "YOURMACHINENAME" is the name of your windows machine. 

6. Re-run the client - observe that this time you get a crash dump
Actual Results:  
The client program catches an exception:

     ---->System.ServiceModel.ProtocolException
     Message
          The remote server returned an unexpected response: (400) Bad Request.
     Stack
          Server stack trace:
          at
System.ServiceModel.Channels.HttpChannelUtilities.ValidateRequestRe
plyResponse(HttpWebRequest request, HttpWebResponse response,
HttpChannelFactory
 factory, WebException responseException, ChannelBinding channelBinding)
          at
System.ServiceModel.Channels.HttpChannelFactory.HttpRequestChannel.
HttpChannelRequest.WaitForReply(TimeSpan timeout)
          at System.ServiceModel.Channels.RequestChannel.Request(Message
message
, TimeSpan timeout)
          at
System.ServiceModel.Dispatcher.RequestChannelBinder.Request(Message
 message, TimeSpan timeout)
          at System.ServiceModel.Channels.ServiceChannel.Call(String action,
Boo
lean oneway, ProxyOperationRuntime operation, Object[] ins, Object[] outs,
TimeS
pan timeout)
          at
System.ServiceModel.Channels.ServiceChannelProxy.InvokeService(IMet
hodCallMessage methodCall, ProxyOperationRuntime operation)
          at System.ServiceModel.Channels.ServiceChannelProxy.Invoke(IMessage
me
ssage)
          Exception rethrown at [0]:
          at
System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage(IMess
age reqMsg, IMessage retMsg)
          at
System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(MessageData
& msgData, Int32 type)
          at client.IProfileREST.Ping()
          at client.ProfileRESTClient.client.IProfileREST.Ping() in
C:\Temp\FunW
ithMonoRESTClient.Report\client\Program.cs:line 35
          at client.Program.DoMain(String[] args) in
C:\Temp\FunWithMonoRESTClie
nt.Report\client\Program.cs:line 68
          at client.Program.Main(String[] args) in
C:\Temp\FunWithMonoRESTClient
Report\client\Program.cs:line 54
          ---->System.Net.WebException
          Message
               The remote server returned an error: (400) Bad Request.
          Stack
               at System.Net.HttpWebRequest.GetResponse()
               at
System.ServiceModel.Channels.HttpChannelFactory.HttpRequestCha
nnel.HttpChannelRequest.WaitForReply(TimeSpan timeout)

Expected Results:  
The client should be able to contact the server with a URI that specifies the
machine name or IP address without throwing an exception.

This test was performed with the server running on Windows Server 2008 R2 and
Ubuntu 10.10, they both act the same way.

I don't know why I always have to run the client on windows .net, i think this
is another bug that I will report.

-- 
Configure bugmail: https://bugzilla.novell.com/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
You are the QA contact for the bug.


More information about the mono-bugs mailing list