1
\$\begingroup\$

I'm looking for feedback on some code I've written to work as a transparent proxy. I'm developing a web app that needs information from another web site's API, but that web site has disabled CORS and I cannot get it directly. This was an intentional decision by the web site to encourage development of services that will benefit their larger community.

I've recently seen a lot of articles and posts about how to correctly use HttpClient to avoid a huge number of open sockets and potential performance concerns. After reading those, I've updated my code to look like the following.

Startup.cs

 public void ConfigureServices(IServiceCollection services)
    {
       ...

        services.AddSingleton<IHttpClientService, HttpClientService>();
        services.AddScoped<IProxyService, ProxyService>();

        services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
    }

HttpClientService's only purpose is to provide an instance of HttpClient to ProxyService:

public class HttpClientService : IHttpClientService
{
    private HttpClient _client;

    public HttpClientService()
    {
        _client = new HttpClient();
    }

    public HttpClient Client()
    {
        return _client;
    }
}

I inject HttpClientService into ProxyService:

public class ProxyService : IProxyService
{
    private readonly Uri _websiteUri;
    private readonly IHttpClientService _http;

    public ProxyService(IHttpClientService httpClient)
    {
        _websiteUri = new Uri("https://www.website.com/api/get-information");
        _http = httpClient;
    }

    public async Task<HttpResponseMessage> GetInformationAsync(string name, string sessionId)
    {

        var builder = new UriBuilder(_websiteUri);
        builder.Port = -1;

        var query = HttpUtility.ParseQueryString(builder.Query);
        query["name"] = name;

        builder.Query = query.ToString();
        string url = builder.ToString();

        var httpRequestMessage = new HttpRequestMessage
        {
            Method = HttpMethod.Get,
            RequestUri = new Uri(url),
            Headers =
            {
                { HttpRequestHeader.Cookie.ToString(), "SESSIONID=" + sessionId }
            }
        };

        var response = await _http.Client().SendAsync(httpRequestMessage);

        return response;                
    }

    ...
}

My main API calls ProxyService like this:

public class APIController : ControllerBase
{
    private readonly IProxyService _proxy;

    public APIController(IProxyService proxy)
    {
        _proxy = proxy;
    }

    [HttpGet]
    public async Task<IActionResult> GetInformation(string name, string sessionId)
    {
        using (var response = await _proxy.GetInformationAsync(name, sessionId))
        {

            if (response.IsSuccessStatusCode)
            {
                var contents = await response.Content.ReadAsStringAsync();
                return Ok(contents);
            }
            else
            {
                return NotFound();
            }
        }
    }

    ...
}

Is this an okay approach? Do I even need to wrap the await _proxy.GetInformationAsync() call in a using block?

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.