react-native-community / discussions-and-proposals

Discussions and proposals related to the main React Native project
https://reactnative.dev
1.67k stars 126 forks source link

Custom domain to IP resolving or DNS for networking API #245

Open halaei opened 4 years ago

halaei commented 4 years ago

Introduction

As far as I understand, it is currently impossible to set a custom DNS server or other domain to IP resolving mechanisms for the application to be used by networking API (e.g. fetch and XMLHttpRequest). A setting to be applied to the whole application or to a single network API call will be great.

Details

Something like curl --resolve option would be enough to resolve IP address per request:

curl https://example.com/ping --resolve example.com:443:192.168.20.20

Setting the preferred dns server will also be great. If custom domain to IP resolve is already implemented, one can set preferred DNS server using https://github.com/tableau/react-native-dns-lookup so I guess it is not needed to be in the core of react-native.

halaei commented 4 years ago

It seems it is already possible for Android to change DNS settings, but the feature isn't documented I guess. See https://github.com/facebook/react-native/commit/81fcaa151df4f81e1751719173376bebedb42f36 An instance of NetworkingModule.CustomClientBuilder should be passed to NetworkingModule.setCustomClientBuilder() to change the builder made by ReactNative:

  public static interface CustomClientBuilder {
    public void apply(OkHttpClient.Builder builder);
  }

I have no clue for iOS.

kelset commented 4 years ago

👋 this is not really a long form discussion as more of a precise conversation/question around this feature.

What I would suggest: 1) open a PR to the documentation adding the how to for changing the DNS on Android 2) open a PR against the main repo to add the same feature iOS side so that it can be discussed further

halaei commented 4 years ago

@kelset I write here my progress so far to make it a real discussion, hoping for it to lead to either to a documentation or code PR.

I was able to apply my dns for NetworkingModule as I mentioned, however, this doesn't apply to ImageLoaderModule. ImageLoaderModule module uses FrescoModule's ReactOkHttpNetworkFetcher, which uses its own OkHttp client. The client is provided by either FrescoModule.getDefaultConfigBuilder() or MainPackageConfig.getFrescoConfig(). So I have 2 options:

  1. Change client created by getDefaultConfigBuilder():
    OkHttpClient client = OkHttpClientProvider.createClient();

    To use my custom client, I can OkHttpClientProvider.setOkHttpClientFactory(OkHttpClientFactory myCustomFactor). However, it isn't a good idea because the interface of OkHttpClientFactory doesn't accept any Context to configure cache:

    // in class OkHttpClientProvider:
    public static OkHttpClient createClient(Context context) {
    if (sFactory != null) { // if sFactory is not null, context won't be applied, and http cache will be disabled!
      return sFactory.createNewNetworkModuleClient();
    }
    return createClientBuilder(context).build();
    }

So maybe in future release some improvement can be done to OkHttpClientFactory, like to adding a nullable context as the first argument of createNewNetworkModuleClient():

public interface OkHttpClientFactory {
-  OkHttpClient createNewNetworkModuleClient();
+  OkHttpClient createNewNetworkModuleClient(Context context);
};
  1. Change fresco config by calling MainPackageConfig.Builder.setFrescoConfig() If I call this function, I can pass in my own custom fresco config, including my own OkHttpClient. But I haven't yet find how and where to call this. Any idea about that?
jdmg94 commented 2 years ago

would the CustomClientBuilder approach work for iOS too?

halaei commented 2 years ago

Hi @jdmg94 I didn't need this for iOS, so I don't know. I remember Android solution was also very dirty and involved checking the stack trace at runtime, but that could have been solved if https://github.com/facebook/react-native/pull/29435 were merged.