Search code examples
c#httpflurl

Flurl Proxy after construction?


I'm using Flurl to consume an API in my application and I have a question about proxies. The thing is that I want the user to be able to set the proxy if necessary after startup, is that possible with Flurl?

I found this, but that's recommending that you only call on startup so as far as I can tell you can't really change it after the fact. I also found this but that is separating out different requests to use different proxies which isn't what I need either.

Basically I want it to default to no proxy at first like it does and use that for all requests. Then sometime later if the user sets up the proxy and enters the data I want to be able to set the proxy for Flurl and have it use that for all requests thereafter.

Is there a way to do this?


Solution

  • The short answer is you would need to create a new client every time the proxy is set or changed. This is due to constraints down the chain of dependencies:

    1. Proxy information is set in HttpClientHandler.
    2. The handler is passed to the HttpClient constructor and cannot be changed thereafter.
    3. FlurlClient wraps exactly one HttpClient, which is either passed explicitly via its constructor, or (more typically) created lazily via its default rules or custom ones configured via settings and factories. Once created it can't be changed.
    4. Even if you held a reference to the HttpClientHandler and tried to change its proxy settings at some later point, you'd get a runtime error.

    If you're not currently using FlurlClient explicitly, I would switch to that paradigm. Here's an example of what would need to happen when the user changes the proxy:

    var hch = new HttpClientHandler {
        UseProxy = true,
        Proxy = new WebProxy(proxyUrl)
    };
    var hc = new HttpClient(hch) { BaseAddress = baseUrl };
    var fc = new FlurlClient(hc);
    

    Then you can fluently build calls off fc similar to how you would if you started with a URL:

    var thing = await fc.Request("path", "to", "endpoint").GetJsonAsync<T>();
    

    Depending on whether you have multiple concurrent users or concurrent calls, you could make this a bit more robust by encapsulating this into something that caches FlurlClient instances per proxy address, such as by using a ConcurrentDictionay.