kawansoft / AceQL.Client

Legacy PCL version. C# Client toolkit for easy access of remote SQL databases managed with AceQL HTTP.
https://www.aceql.com
Apache License 2.0
3 stars 2 forks source link

Defaultproxy is not working? #5

Closed quirrel1002 closed 4 years ago

quirrel1002 commented 4 years ago

Hello, I try to use aceQL server "behind" a proxy. To make it easier to configure I try to not specify the proxy explicitly, but it is not working then. I just checked in ./AceQL.Client/AceQL.Client/Src/Api.Http/HttpClientHandlerBuilder.cs
httpClientHandler.Proxy = System.Net.WebRequest.DefaultWebProxy; is used. I found a working example of my own, where I am using: IWebProxy proxy = WebRequest.GetSystemWebProxy(); proxy.Credentials = (NetworkCredential) CredentialCache.DefaultCredentials;

So I wonder if there is any reason why the DefaultWebProxy is used? Is there a change to check if changing to my example works also for AceQL.Client?

ndepomereu commented 4 years ago

Hi, Just to confirm: you are using a proxy with authentication and want to use the proxy username/password cached?

quirrel1002 commented 4 years ago

Hello, so yes I use a proxy with authentication and want to use already configured proxy (through windows "internet options" configured) and cached default credentials.

ndepomereu commented 4 years ago

Default proxy is implemented in v5.1:

Just addUseCredentialCache=Truein the connection string, and AceQL will automatically retriieve the Credential to use for the proxy to use:

"Server=https://www.acme.com:9443/aceql; Database=myDataBase; Username=myUsername; Password=myPassword; UseCredentialCache=True"

quirrel1002 commented 4 years ago

Hello, thanks for the update. I updated and tried the example similarly to above, but it seems not to work. Is there anything missing? I also tried to add the "ProxyUri" parameter but both did not help. Are there special log files I could check?

ndepomereu commented 4 years ago

Hi, If your proxy is defined with Windows as a System proxy, do not declare anything in the connection string, just the mandatory parameters: "Server=https://www.acme.com:9443/aceql; Database=myDataBase; Username=myUsername; Password=myPassword; UseCredentialCache=True"

The internal AceQL detects both the proxy and the CacheCredential, as in your sample code

This the internal AceQL code that sets the proxy credential using the CacheCredential:

                NetworkCredential networkCredential = (NetworkCredential)CredentialCache.DefaultCredentials;
                proxyCredentials = new NetworkCredential(networkCredential.UserName, networkCredential.Password);

This is the internal AceQL thats sets the HttpClientHandler passed to the HttpClient (proxy is null):

                HttpClientHandler httpClientHandler = new HttpClientHandler
                {
                    UseProxy = true,
                    UseDefaultCredentials = false
                };

                if (proxy == null)
                {
                    httpClientHandler.Proxy = System.Net.WebRequest.DefaultWebProxy;
                }
                else
                {
                    httpClientHandler.Proxy = proxy;
                }

                httpClientHandler.Proxy.Credentials = credentials;
                httpClientHandler.PreAuthenticate = true;

This the applicative code I used for my tests to set the CredentialCache:

            CredentialCache.DefaultNetworkCredentials.UserName = "myUsername";
            CredentialCache.DefaultNetworkCredentials.Password = "myPassword";

Everything has been tested in real conditions with a proxy that requires authentication.

Please let me know if this is OK?

quirrel1002 commented 4 years ago

Hello, so the implementation looks basically good. I only wonder if it would be easier to directly use CredentialCache.DefaultNetworkCredentials as this removes the need of a cast and should lead to proxyCredentials = CredentialCache.DefaultNetworkCredentials.

The only real difference I noticed is that in my example and test(s) I used

System.Net.WebRequest.GetSystemWebProxy().GetProxy(new Uri("http://www.google.com")).ToString() to get the URL of the proxy, while System.Net.WebRequest.DefaultWebProxy.GetProxy(new Uri("http://www.google.com")).ToString() "only" returned the adress http://www.google.com.

May be this makes a difference for me, since currently the "UseCredentialCache=True" results in a 'System.Net.Http.HttpRequestException: An error occurred while sending the request. ---> System.Net.WebException: The remote name could not be resolved: 'myaceQLserver.com''

I could also resolve the proxy with above mentioned code, but if I provide the proxyUri then Credentialcache is not used if I get it right?

ndepomereu commented 4 years ago

Hi,

I don't understand reading your text if you could make work the CredentialCache?

Did you try without setting any proxy in the C# code and in the connection string , as in my sample connection string? :

"Server=https://www.acme.com:9443/aceql; Database=myDataBase; Username=myUsername; Password=myPassword; UseCredentialCache=True"

Do not do any call like this in your code: IWebProxy proxy = WebRequest.GetSystemWebProxy();

If you cannot make it work, please send me sample code of the AceQLConnectioncall and how you set the CredentialCache.

quirrel1002 commented 4 years ago

HI, sorry so I tried only using the connection string as you mentioned in your example. I used only "UseCredentialCache=True" without any other proxy options. This is not working and giving me the error 'System.Net.Http.HttpRequestException: An error occurred while sending the request. ---> System.Net.WebException: The remote name could not be resolved: 'myaceQLserver.com'' => this leads for me to the conclusion somehow proxy is not "found". I hope that help and clarifies my last post.

ndepomereu commented 4 years ago

Hi, Please, how is set the proxy? How is set the CredentialCache? Source code is welcomed, it will help a lot.

quirrel1002 commented 4 years ago

Hi, so I tried:

        /// <summary>
        /// Get connection as an asynchronous operation.
        /// </summary>
        /// <returns>aceql Connection</returns>
        private AceQLConnection GetConnection()
        {
           ServicePointManager.SecurityProtocol =
              SecurityProtocolType.Tls12 | SecurityProtocolType.Tls11 | SecurityProtocolType.Ssl3;
           var proxy = DBManagement.Settings.ProxyUri; //read all settings throough a settings file
           if (string.IsNullOrEmpty(proxy))
           {
             //comment: I tried using this proxy with username and password works
              proxy = WebRequest.GetSystemWebProxy().GetProxy(new Uri("http://www.google.com")).ToString();
              Log.Debug("detected proxy " + proxy);
           }
          //comment: I tried with and without settings this here
           CredentialCache.DefaultNetworkCredentials.UserName = DBManagement.Settings.ProxyUsername;
           CredentialCache.DefaultNetworkCredentials.Password = DBManagement.Settings.ProxyPassword;

           string connectionString =
              $"Server= {DBManagement.Settings.Server}; Database= {DBManagement.Settings.Database}; " +
              "UseCredentialCache=True;";
           //$"ProxyUri= {proxy}; ProxyUsername= {DBManagement.Settings.ProxyUsername}; ProxyPassword= {DBManagement.Settings.ProxyPassword};";

           AceQLConnection localconnection = new AceQLConnection(connectionString)
           {
              Credential = new AceQLCredential(DBManagement.Settings.ServerUsername,
                 DBManagement.Settings.ServerPassword.ToArray()),
              GzipResult = false
           };
           return localconnection;
        }

I added some comments for variants, but this function in current state produces the error message I reported allready.

ndepomereu commented 4 years ago

Hi,

Can you please try to get the Connection using exactly this code? It will connect to a demo database. Just replace the two myProxyUsername& myProxyPasswordwith your values:

        public static AceQLConnection GetConnection()
        {
            CredentialCache.DefaultNetworkCredentials.UserName = myProxyUsername;
            CredentialCache.DefaultNetworkCredentials.Password = myProxyPassword;

            string connectionString = "Server= http://www.runsafester.net:8081/aceql; Database= sampledb; " +
               "UseCredentialCache=True;";

            AceQLConnection localconnection = new AceQLConnection(connectionString)
            {
                Credential = new AceQLCredential("user1", "password".ToCharArray()),
                GzipResult = false
            };
            return localconnection;
        }

If it works, try to connect to your server using the same skeleton.

quirrel1002 commented 4 years ago

Hello, so I tried exact code above and replaced only myProxyUsername and myProxyPassword. Connection does not work, I get the following error:

AceQLException during connection try: 
errorType: 0 / reason: An error occurred while sending the request. / httpStatusCode: 0 / exception: System.Net.Http.HttpRequestException: An error occurred while sending the request. ---> System.Net.WebException: The remote name could not be resolved: 'www.runsafester.net'
   at System.Net.HttpWebRequest.EndGetRequestStream(IAsyncResult asyncResult, TransportContext& context)
   at System.Net.Http.HttpClientHandler.GetRequestStreamCallback(IAsyncResult ar)
   --- End of inner exception stack trace ---
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd(Task task)
   at AceQL.Client.Src.Api.Http.HttpManager.<CallWithPostAsync>d__20.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at AceQL.Client.Src.Api.Http.HttpManager.<CallWithPostAsyncReturnString>d__23.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd(Task task)
   at AceQL.Client.Api.Http.AceQLHttpApi.<OpenAsync>d__22.MoveNext()

I expect the issue is similar as when connecting to "my" aceQL Server...

ndepomereu commented 4 years ago

Hi, Very weird. Please retry without the two lines:

            CredentialCache.DefaultNetworkCredentials.UserName = myProxyUsername;
            CredentialCache.DefaultNetworkCredentials.Password = myProxyPassword;
quirrel1002 commented 4 years ago

Hi, If I comment these two lines the result is still the same. So my guess would be that DefaultWebproxy somehow does not give the correct value for my use case. I just red through https://stackoverflow.com/questions/14887679/whats-the-difference-between-webrequest-defaultwebproxy-and-webrequest-getsyste I think the "issue" is that my default settings uses a PAC file for proxy resolutions that is not correctly use by the System.Net.WebRequest.DefaultWebProxy; but works for System.Net.WebRequest.GetSystemWebProxy(); Is it possible to make this configurable?

ndepomereu commented 4 years ago

Hi, I understand; I think your diagnosis is good. This could be configurable. I will read the C# doc and make some tests asap...

ndepomereu commented 4 years ago

Hi, It should be doable, but because AceQL.Client is a PCL, there is no access to System.Net.WebRequest.GetSystemWebProxy() implementation of IWebProxy. (Aka you will have to pass yourself your own System.Net.WebRequest.GetSystemWebProxy() value as a IWebProxy parameter to AceQL .). I work on it asap.

quirrel1002 commented 4 years ago

Hello, so what I already tried is passing the proxy address I received through System.Net.WebRequest.GetSystemWebProxy() through connection string to aceQL client. This worked together with proxyusername and proxypassword. May be as intermediate step it is possible to use credential cache also if proxyURL is provided in the connection string?

ndepomereu commented 4 years ago

Hi, I am afraid that there is no way to set the proxy to us in AceQL as the System.Net.WebRequest.GetSystemWebProxy() without passing a concrete instance to AceQL. So there is no way - as I know - to use text representation in the connection string.

It will be thus passed to AceQL using a static setter such as: AceQLConnection.setWebProxy(System.Net.WebRequest.GetSystemWebProxy());

I will implement this for tomorrow Saturday.

ndepomereu commented 4 years ago

Hi, New version 5.2 allows to set System.Net.WebRequest.GetSystemWebProxy() as the default global proxy with an AceQLConnection static method to be called before creating the Connection: AceQLConnection.SetDefaultWebProxy(WebRequest.GetSystemWebProxy());

santhosh250595 commented 4 years ago

Hello,

I've also adapted the above but I face the below error in some machines (WebRequest.GetSystemWebProxy() works fine in some machines) and I also checked the proxy settings and it is same across all the machines. Any clue why there is a different behavior in some machines

errorType: 0 / reason: An error occurred while sending the request. / httpStatusCode: 0 / exception: System.Net.Http.HttpRequestException: An error occurred while sending the request. ---> System.Net.WebException: The remote server returned an error: (407) Proxy Authentication Required. at System.Net.HttpWebRequest.EndGetRequestStream(IAsyncResult asyncResult, TransportContext& context) at System.Net.Http.HttpClientHandler.GetRequestStreamCallback(IAsyncResult ar) --- End of inner exception stack trace --- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd(Task task) at AceQL.Client.Src.Api.Http.HttpManager.d20.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at AceQL.Client.Src.Api.Http.HttpManager.d23.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd(Task task) at AceQL.Client.Api.Http.AceQLHttpApi.d__22.MoveNext()

ndepomereu commented 4 years ago

Hi, I think this means that either: 1) in some machines the CredentialCache are not set! 2) Otherwise, it could be that when using CredentialCache , it's possible that the first response is "(407) Proxy Authentication Required." AceQL always try to repeat the call once in this case. You have to handle to repeat first call auth until 407 disappears.

ndepomereu commented 4 years ago

Hi , Please ignore my last today post (13:15 UTC+2). There is an AceQL bug when using CredentialCache, I will fix it today.

santhosh250595 commented 4 years ago

I changed the below piece code in mine and in aceql client and it worked

--mine IWebProxy proxy = WebRequest.GetSystemWebProxy(); proxy.Credentials = CredentialCache.DefaultCredentials; AceQLConnection.SetDefaultWebProxy(proxy);

--aceqlclient // Creates the HttpClientHandler, with or without an associated IWebProxy HttpClientHandlerCreator httpClientHandlerCreator = new HttpClientHandlerCreator(webProxy, webProxy.Credentials, enableDefaultSystemAuthentication);

ndepomereu commented 4 years ago

Hi, Problem is fixed with new 5.3 version. AceQL will work smoothly with an authenticated proxy, and using CredentialCache will not raise any more 407 responses.

ndepomereu commented 4 years ago

P.S : quirrel1002, you will still need to call: AceQLConnection.setWebProxy(System.Net.WebRequest.GetSystemWebProxy()) before creating the AceQLConnection, of course.

santhosh250595 commented 4 years ago

Hello,

I'm facing the same error using AceQL Client 5.3 version. But modifying the below part in AceQL Client resolved this error.

--aceqlclient // Creates the HttpClientHandler, with or without an associated IWebProxy HttpClientHandlerCreator httpClientHandlerCreator = new HttpClientHandlerCreator(webProxy, webProxy.Credentials, enableDefaultSystemAuthentication);

AceQLException during connection try: errorType: 0 / reason: An error occurred while sending the request. / httpStatusCode: 0 / exception: System.Net.Http.HttpRequestException: An error occurred while sending the request. ---> System.Net.WebException: The remote server returned an error: (407) Proxy Authentication Required. at System.Net.HttpWebRequest.EndGetResponse(IAsyncResult asyncResult) at System.Net.Http.HttpClientHandler.GetResponseCallback(IAsyncResult ar) --- End of inner exception stack trace --- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at AceQL.Client.Src.Api.Http.HttpManager.d20.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at AceQL.Client.Src.Api.Http.HttpManager.d22.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at AceQL.Client.Api.Http.AceQLHttpApi.d23.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd(Task task) at AceQL.Client.Api.Http.AceQLHttpApi.d22.MoveNext()

ndepomereu commented 4 years ago

Q10Hi,

What is your connection string, please? Aka are you using a CredentialCache? Did you try AceQLConnection.SetDefaultWebProxy(proxy)?

Le mar. 11 août 2020 à 06:31, santhosh250595 notifications@github.com a écrit :

Hello,

I'm facing the same error using AceQL Client 5.3 version. But modifying the below part in AceQL Client resolved this error.

--aceqlclient // Creates the HttpClientHandler, with or without an associated IWebProxy HttpClientHandlerCreator httpClientHandlerCreator = new HttpClientHandlerCreator(webProxy, webProxy.Credentials, enableDefaultSystemAuthentication);

AceQLException during connection try: errorType: 0 / reason: An error occurred while sending the request. / httpStatusCode: 0 / exception: System.Net.Http.HttpRequestException: An error occurred while sending the request. ---> System.Net.WebException: The remote server returned an error: (407) Proxy Authentication Required. at System.Net.HttpWebRequest.EndGetResponse(IAsyncResult asyncResult) at System.Net.Http.HttpClientHandler.GetResponseCallback(IAsyncResult ar) --- End of inner exception stack trace --- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at AceQL.Client.Src.Api.Http.HttpManager.d20.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at AceQL.Client.Src.Api.Http.HttpManager.d22.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at AceQL.Client.Api.Http.AceQLHttpApi.d23.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd(Task task) at AceQL.Client.Api.Http.AceQLHttpApi.d22.MoveNext()

— You are receiving this because you modified the open/close state. Reply to this email directly, view it on GitHub https://github.com/kawansoft/AceQL.Client/issues/5#issuecomment-671718412, or unsubscribe https://github.com/notifications/unsubscribe-auth/ADQ7CVWIH5Y3HNAVIQSMD2DSADCT3ANCNFSM4PIS4NTA .

santhosh250595 commented 4 years ago

Hello, This is my connection string.

**IWebProxy proxy = WebRequest.GetSystemWebProxy(); proxy.Credentials = CredentialCache.DefaultCredentials; AceQLConnection.SetDefaultWebProxy(proxy); string connectionString = $"Server= {DBManagement.Settings.Server}; Database= {DBManagement.Settings.Database}; UseCredentialCache = True; ";

        AceQLConnection localconnection = new AceQLConnection(connectionString)
        {
            Credential = new AceQLCredential(DBManagement.Settings.ServerUsername, DBManagement.Settings.ServerPassword.ToArray()),
            GzipResult = false
        };**
ndepomereu commented 4 years ago

Did you try Did you try AceQLConnection.SetDefaultWebProxy(proxy) ?

Le mar. 11 août 2020 à 08:33, santhosh250595 notifications@github.com a écrit :

Hello, This is my connection string.

**IWebProxy proxy = WebRequest.GetSystemWebProxy(); proxy.Credentials = CredentialCache.DefaultCredentials; AceQLConnection.SetDefaultWebProxy(proxy); string connectionString = $"Server= {DBManagement.Settings.Server}; Database= {DBManagement.Settings.Database}; UseCredentialCache = True; ";

    AceQLConnection localconnection = new AceQLConnection(connectionString)
    {
        Credential = new AceQLCredential(DBManagement.Settings.ServerUsername, DBManagement.Settings.ServerPassword.ToArray()),
        GzipResult = false
    };**

— You are receiving this because you modified the open/close state. Reply to this email directly, view it on GitHub https://github.com/kawansoft/AceQL.Client/issues/5#issuecomment-671757091, or unsubscribe https://github.com/notifications/unsubscribe-auth/ADQ7CVQPWVP4L3G2EPB4C43SADQ4NANCNFSM4PIS4NTA .

santhosh250595 commented 4 years ago

Hi, Yes I've tried and below are the combinations

**IWebProxy proxy = WebRequest.GetSystemWebProxy(); proxy.Credentials = CredentialCache.DefaultCredentials; AceQLConnection.SetDefaultWebProxy(proxy);

AceQLConnection.SetDefaultWebProxy(WebRequest.GetSystemWebProxy());**

ndepomereu commented 4 years ago

Hi,

OK, thanks, I will test your hack/solution and make a new version.

Le mar. 11 août 2020 à 09:27, santhosh250595 notifications@github.com a écrit :

Hi, Yes I've tried and below are the combinations

**IWebProxy proxy = WebRequest.GetSystemWebProxy(); proxy.Credentials = CredentialCache.DefaultCredentials; AceQLConnection.SetDefaultWebProxy(proxy);

AceQLConnection.SetDefaultWebProxy(WebRequest.GetSystemWebProxy());**

— You are receiving this because you modified the open/close state. Reply to this email directly, view it on GitHub https://github.com/kawansoft/AceQL.Client/issues/5#issuecomment-671778200, or unsubscribe https://github.com/notifications/unsubscribe-auth/ADQ7CVQGK34LG2WCALHWUMTSADXEVANCNFSM4PIS4NTA .

ndepomereu commented 4 years ago

Hi, For santhosh250595: I have applied your hack in new version 5.3.1:

 // Use the Credentials of the Web Proxy if webProxy.Credentials is not null
httpClientHandlerCreator = new HttpClientHandlerCreator(webProxy, webProxy.Credentials, enableDefaultSystemAuthentication);
santhosh250595 commented 4 years ago

Hi, Thanks for the new version. it works very fine

ndepomereu commented 4 years ago

Welcome! (I close the issue.)

quirrel1002 commented 4 years ago

Hello, so I did not reply since the issue solved for me also now. Thanks for the solution.