Skip to content

RFC: Built-in Http module #5145

@thomasvidas

Description

@thomasvidas

TL;DR?

We are planning on building a new Capacitor Plugin called NHttp based on the @capacitor-community/http plugin that patches fetch, XMLHttpRequest, and adds in new functions like download, upload, and other functions. Will be opt-in in Capacitor 3 and the default in Capacitor 4.0.

But please go and read! We'd love to hear the community's thoughts!

Challenge

Currently the window.fetch and window.XMLHttpRequest functions in a Capacitor application have the same limitations that they have in the browser. This includes, but is not limited to:

  • CORS restrictions
  • Unable to use certificate based authentication
  • Unable to take advantage of parallel requests on multiple threads

These issues can be bypassed by using libraries such as @capacitor-community/http and cordova-plugin-advanced-http that use the native android/iOS http libraries to do web requests. But this introduces other problems:

  • Third party libraries still rely on window.fetch and window.XMLHttpRequest so you still aren't taking advantage of the plugins
  • You are restricted to using the plugin's APIs rather than using the existing browser APIs
  • Http requests have to wait until the plugins have been loaded into the Capacitor runtime, which may lead to race conditions.

Both of these approaches have drawbacks. And auth providers such as Okta require workarounds that are not intuitive. Hence this proposal!

Goal

What are we trying to achieve?

  1. Create a plugin that is bundled with @capacitor/core **that provides near 100% compatibility with fetch and XMLHttpRequest. This will be opt-in in Capacitor 3.x and the default (with an opt-out) in Capacitor 4.x.
  2. Add performance improvements with multi-threading on the native layer without compromising compatibility with existing browser APIs.
  3. Create a solid base for more advanced http functions that will be bundled into the core runtime for additions in Capacitor 4.x.

Proposal

Built in Native-Http plugin (NHttp)

With NHttp, we can patch window.fetch and window.XMLHttpRequest to use window.Capacitor.Plugins.NHttp functions in order to get the fix the challenges listed above with using the existing browser functions. This allows third party libraries to use NHttp without developers needing to rewrite their code. It also allows Capacitor developers to use more web APIs while getting the benefits of native application code/performance.

NHttp will be bundled with @capacitor/core in a similar way that the WebView plugin is bundled/initialized with the core runtime. This allows it to be initialized at the exact time that the Capacitor bridge is initialized, allowing for all requests to use NHttp.

Screen_Shot_2021-10-12_at_4 28 32_PM

In Capacitor 3.x, we will add a new capacitor.config option tentatively called "useNHttp" that will default to false. This value will default to true in Capacitor 4.x. The following code snippet demonstrates how the APIs will be patched.

if (capacitorConfig.useNHttp) {
  // Assign web fetch/XMLHttpRequest to another variable
  window.webFetch = window.fetch;
  window.webXMLHttpRequest = window.XMLHttpRequest;

  // Patch fetch and XMLHttpRequest
  window.fetch = window.Capacitor.Plugins.NHttp.fetch;
  window.XMLHttpRequest = window.Capacitor.Plugins.NHttp.XmlHttpRequest;
}

Deprecate @capacitor-community/http plugin

The @capacitor-community/http plugin, which is maintained by Ionic, will be updated to support Capacitor 4.0 and then deprecated. NHttp will have feature parity with @capacitor-community/http with the release of Capacitor 4.0. In Capacitor 5.0, the @capacitor-community/http plugin will not be updated and may not work with future releases of Capacitor.

Ionic will create a migration document for migrating code to support the NHttp plugin by providing code samples. An example of the migration guide would be something similar to this.

// old
const options = {
  url: 'https://example.com/my/api',
};
const response: HttpResponse = await Http.get(options);

// new
const response: Reponse = await window.fetch('https://example.com/my/api')

For extended functions that browser APIs don't cover, but the @capacitor-community/http plugin does, the syntax may look something similar to this.

// old
const options = {
  url: 'https://example.com/download.pdf',
  filePath: 'document.pdf',
  fileDirectory: FilesystemDirectory.Downloads,
};

const response: HttpDownloadFileResult = await Http.downloadFile(options);

// new
const response: Response = await window.download('https://example.com/download.pdf', {
  filename: 'document.pdf',
  directory: window.Capacitor.Plugins.NHttp.getDefaultDownloadDirectory()
}

If the community would like to continue maintaining the existing @capacitor-community/http plugin, please post in the comments!

Undecided

  • Should we bring in external dependencies or use the built in Http libraries? Is the community ok with bringing in something like OkHttp or AlamoFire?
  • Is 100% compatibility with XMLHttpRequest and fetch required? Should we aim for the same level of compatibility that https://github.com/github/fetch has?
  • Should we provide a harder opt-out that allows you to uninstall the NHttp module? Is having a passive Http module as a default a deal-breaker for some applications?
  • How would NHttp work on the web if we extended fetch for users that are using Capacitor on Web as well as Android and iOS.
  • Are there any other modules that should be a part of core? Cookies, motion, haptics, etc? (Certain modules like Geolocation, Push Notifications, etc can't be included in core due to permissions)

Metadata

Metadata

Assignees

No one assigned

    Labels

    RFCRequest For Comments

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions