1and1 restricts request to another server using ASP.NET CORE

Viewed 542

I am trying to make a request to Paypal endpoint via SDK in my .NET Core application. The request works on local server just fine. But when I pulished the application on 1and1 hosting server, I get this error.

A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond.

The reason I found out is that 1and1 doesn't allow direct calls so I need to use proxy. Some people have asked the same question already. But there is no real answer for me.

Here are two of them:

I also did contact 1and1 for support (2x times). They sent me the same link (in german) which I have already found and tried. No success.

Here are some senairos, that I have tried:

1. Add proxy server to web.config file

My config file looks something like this

<configuration>
  <location path="." inheritInChildApplications="false">
    <system.webServer>
      <handlers>
        <add name="aspNetCore" path="*" verb="*" modules="AspNetCoreModuleV2" resourceType="Unspecified" />
      </handlers>
      <aspNetCore processPath=".\MyApp.exe" stdoutLogEnabled="false" stdoutLogFile=".\logs\stdout" hostingModel="inprocess" />
    </system.webServer>
  </location>
  <system.net>
    <defaultProxy>
        <proxy  proxyaddress="http://1and1proxy:123"
                bypassonlocal="true"/>
    </defaultProxy>
  </system.net>
</configuration>

2. Add AspNetCore.Proxy to startup.cs file

 public void ConfigureServices(IServiceCollection services) {
  ...
  services.AddProxies();
  ...
 }

 public void Configure(IApplicationBuilder app, IWebHostEnvironment env) {
  ...
  app.RunProxy(proxy => proxy.UseHttp("http://1and1proxy:123"));
  ...
 }

3. Make another simple request to another server (using webproxy but also failed)

public async Task < IActionResult > callingGet() {
 var proxiedHttpClientHandler = new HttpClientHandler() {
  UseProxy = true
 };
 proxiedHttpClientHandler.Proxy = new WebProxy("http://1and1proxy:123");
 HttpClient client = new HttpClient(proxiedHttpClientHandler);
 using
 var client = new HttpClient();
 var result = await client.GetAsync("https://reqres.in/api/users/2");
 return View(new Model {
  Message = result.ToString()
 });
}

Did I miss something here or do I have to switch to another provider? PS: this is my first time publishing a website

1 Answers

It turns out that the third did work (but I still don't know why the first and second one do not).

So I created an issue on GitHub page to ask if there is any option for me to create a proxy while calling request to PayPal service. I've got no response from any SDK's developers but a member, who had the same request. He had to create on his own this option, because there is no official way to set proxy using PayPal .Net SDK yet. So I am going to repost his answer here. I think it could help someone. Thanks to WSSC-Jonathan again.

using System;
using System.Threading.Tasks;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Reflection;
using PayPalCheckoutSdk.Core;
namespace MongMi.Application.Paypal
{
    public class ProxiedPayPalHttpClient : PayPalHttp.HttpClient
    {
        private WebProxy _proxy;
        private PayPalEnvironment _environment;

        private PayPalHttp.IInjector _gzipInjector;
        private PayPalHttp.IInjector _authInjector;

        public ProxiedPayPalHttpClient(PayPalEnvironment environment, WebProxy proxy)
            : base(environment)
        {
            _environment = environment;
            _proxy = proxy;

            OverrideClient();
            SetupInjectors();
        }

        public ProxiedPayPalHttpClient(PayPalEnvironment environment, string url, string username = "", string password = "")
            : base(environment)
        {
            _environment = environment;
            _proxy = SetupProxy(url, username, password);

            OverrideClient();
            SetupInjectors();
        }

        public WebProxy SetupProxy(string url, string username, string password)
        {
            var proxy = new WebProxy(url)
            {
                BypassProxyOnLocal = true,
                UseDefaultCredentials = true
            };

            if (!string.IsNullOrEmpty(username) || !string.IsNullOrEmpty(password))
                proxy.Credentials = new NetworkCredential(username, password);

            return proxy;
        }

        private void OverrideClient()
        {
            var handler = new HttpClientHandler
            {
                Proxy = _proxy
            };

            var client = new HttpClient(handler, true) { BaseAddress = new Uri(environment.BaseUrl()) };
            client.DefaultRequestHeaders.Add("User-Agent", GetUserAgent());

            SetClient(client);
        }

        private void SetupInjectors()
        {
            _gzipInjector = new GzipInjector();
            _authInjector = new AuthorizationInjector(_proxy, _environment);

            AddInjector(_gzipInjector);
            AddInjector(_authInjector);
        }

        protected void SetClient(HttpClient client)
        {
            var type = GetType();

            while (type != null)
            {
                var field = type.GetField("client", BindingFlags.Instance | BindingFlags.NonPublic);

                if (field != null)
                {
                    field.SetValue(this, client);
                    break;
                }

                type = type.BaseType;
            }
        }

        private class AuthorizationInjector : PayPalHttp.IInjector
        {
            private WebProxy _proxy;
            private PayPalEnvironment _environment;

            private AccessToken _accessToken;

            public AuthorizationInjector(WebProxy proxy, PayPalEnvironment environment)
            {
                _environment = environment;
                _proxy = proxy;
            }

            public void Inject(PayPalHttp.HttpRequest request)
            {
                if (!request.Headers.Contains("Authorization") && !(request is AccessTokenRequest || request is RefreshTokenRequest))
                {
                    if (_accessToken == null || _accessToken.IsExpired())
                        _accessToken = FetchAccessToken().Result<AccessToken>();

                    request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", _accessToken.Token);
                }
            }

            private PayPalHttp.HttpResponse FetchAccessToken()
            {
                var client = new ProxiedPayPalHttpClient(_environment, _proxy);
                var request = new AccessTokenRequest(_environment, null);

                return Task.Run(async () => await client.Execute(request).ConfigureAwait(false)).Result;
            }
        }

        private class GzipInjector : PayPalHttp.IInjector
        {
            public void Inject(PayPalHttp.HttpRequest request)
            {
                request.Headers.AcceptEncoding.Add(new StringWithQualityHeaderValue("gzip"));
            }
        }
    }
}
Related