0 votes
by (2.0k points)

Hello.

If an http response arrives when making an https request, is there a way to recognize it?

When connecting to "https://....", a server responded with "HTTP/1.1" as http.
At that time, when I looked at the rebex http log, "nizpp.eykqb: Handshake failed due to: Alert:UnexpectedMessage (Level:Fatal, Source:Local). ---> nizpp.agepo: Alert:UnexpectedMessage (Level:Fatal, Source:Local) "
An error appears.
The Exception error I get is "WebExceptionStatus : SecureChannelFailure : Alert:UnexpectedMessage (Level:Fatal, Source:Local)."

In this case, I hope there is a way to determine if it is an http response.
Is it possible?

Also, is there a way to determine if the server's response is https when making an http request?

Thank you.

Applies to: Rebex HTTPS

1 Answer

+1 vote
by (73.5k points)
selected by
 
Best answer

Unless specified explicitly, port 443 is used for URLs starting with "https://" and port 80 is used for "http://". If a web server is listening on those ports, but it uses inappropriate protocols for them, it is serious bug in the web server configuration and it should be fixed at the server side at the first place.

There is no built-in support for distinguishing such errors. However, Rebex supports custom transport layer. You can implement your own ISocket and use it to examine all the received data.
Using this, you will be able to check whether the first 5 bytes of the server response were "HTTP/" and react accordingly.

The custom socket can look like this:

public class CustomSocket : ISocket
{
    public static readonly ISocketFactory Factory = new CustomSocketFactory();

    private class CustomSocketFactory : ISocketFactory
    {
        public ISocket CreateSocket()
        {
            return new CustomSocket();
        }
    }

    private readonly ISocket _socket;

    public CustomSocket()
    {
        _socket = new ProxySocket();
    }

    public bool Connected
    {
        get { return _socket.Connected; }
    }

    public EndPoint LocalEndPoint
    {
        get { return _socket.LocalEndPoint; }
    }

    public EndPoint RemoteEndPoint
    {
        get { return _socket.RemoteEndPoint; }
    }

    public int Timeout
    {
        get { return _socket.Timeout; }
        set { _socket.Timeout = value; }
    }

    public void Close()
    {
        _socket.Close();
    }

    public void Connect(EndPoint remoteEP)
    {
        _socket.Connect(remoteEP);
    }

    public void Connect(string serverName, int serverPort)
    {
        _socket.Connect(serverName, serverPort);
    }

    public bool Poll(int microSeconds, SocketSelectMode mode)
    {
        return _socket.Poll(microSeconds, mode);
    }

    public int Receive(byte[] buffer, int offset, int count, SocketFlags socketFlags)
    {
        return _socket.Receive(buffer, offset, count, socketFlags);
    }

    public int Send(byte[] buffer, int offset, int count, SocketFlags socketFlags)
    {
        return _socket.Send(buffer, offset, count, socketFlags);
    }

    public void Shutdown(SocketShutdown how)
    {
        _socket.Shutdown(how);
    }
}

It can be used like this:

var client = new Rebex.Net.WebClient();
client.SetSocketFactory(CustomSocket.Factory);

or when using HttpRequestCreator:

var creator = new HttpRequestCreator();
creator.SetSocketFactory(CustomSocket.Factory);

Note:
In case you don't know which protocol should be used for specified host:port I suggest you to use HTTP at first. If the server is using HTTPS, it will close the connection, because it receives invalid TLS ClientHello. Then you can use HTTPS, which should succeed.

by (2.0k points)
Thank you for your detailed explanation so I can handle it well.
...