Coder Social home page Coder Social logo

capacitor-community / http Goto Github PK

View Code? Open in Web Editor NEW
207.0 14.0 135.0 12.2 MB

Community plugin for native HTTP

License: MIT License

Ruby 0.91% Java 42.91% Swift 23.66% Objective-C 0.81% JavaScript 4.57% TypeScript 26.79% HTML 0.32% Shell 0.04%
capacitor http

http's Introduction


HTTP

@capacitor-community/http

Capacitor community plugin for native HTTP requests, file download/uploads, and cookie management.


Maintainers

Maintainer GitHub Social
Max Lynch mlynch @maxlynch
Thomas Vidas thomasvidas @thomasvidas

Installation

npm install @capacitor-community/http
npx cap sync

Maintence Mode

The next iteration of this plugin will be an official plugin bundled with Capacitor 4.x. In order for a smooth transition, this repo will be in maintence mode with no new features added until the plugin moves to the main Capacitor Plugins repo. In the meantime, if there are critical security bug fixes required, they will still be made to this plugin as a patch release.

Capacitor 2.x

For Capacitor 2.x projects, you will need to install a version less than 1.0.0. You can do that by specifying the version in your package.json or installing like this. The latest 2.x compatible version is 0.3.1.

npm install @capacitor-community/[email protected]

Configuration

In most cases no configuration is required for this plugin. If the Android application connects with use the self-signed certificates or without encryption, see Network security configuration article.

Usage

To use the plugin while fully supporting the web version, import and use it like this:

import { Http } from '@capacitor-community/http';

// Example of a GET request
const doGet = () => {
  const options = {
    url: 'https://example.com/my/api',
    headers: { 'X-Fake-Header': 'Max was here' },
    params: { size: 'XL' },
  };

  const response: HttpResponse = await Http.get(options);

  // or...
  // const response = await Http.request({ ...options, method: 'GET' })
};

// Example of a POST request. Note: data
// can be passed as a raw JS Object (must be JSON serializable)
const doPost = () => {
  const options = {
    url: 'https://example.com/my/api',
    headers: { 'X-Fake-Header': 'Thomas was here' },
    data: { foo: 'bar', cool: true },
  };

  const response: HttpResponse = await Http.post(options);

  // or...
  // const response = await Http.request({ ...options, method: 'POST' })
};

const setCookie = async () => {
  const options = {
    url: 'http://example.com',
    key: 'language',
    value: 'en',
  };

  await Http.setCookie(options);
};

const deleteCookie = async () => {
  const options = {
    url: 'http://example.com',
    key: 'language',
  };

  await Http.deleteCookie(options);
};

const clearCookies = async () => {
  await Http.clearCookies({ url: 'http://example.com' });
};

const getCookies = async () => {
  const cookies: HttpCookie[] = await Http.getCookies({
    url: 'http://example.com',
  });
};

const downloadFile = async () => {
  const options = {
    url: 'https://example.com/path/to/download.pdf',
    filePath: 'document.pdf',
    fileDirectory: Directory.Downloads,
    // Optional
    method: 'GET',
  };

  // Writes to local filesystem
  const response: HttpDownloadFileResult = await Http.downloadFile(options);

  // Then read the file
  if (response.path) {
    const read = await Filesystem.readFile({
      path: 'download.pdf',
      directory: Directory.Downloads,
    });
  }
};

const uploadFile = async () => {
  const options = {
    url: 'https://example.com/path/to/upload.pdf',
    name: 'myFile',
    filePath: 'document.pdf',
    fileDirectory: FilesystemDirectory.Downloads,
  };

  const response: HttpUploadFileResult = await Http.uploadFile();
};

API Reference

You can view the API Reference generated by TypeDoc here: https://capacitor-community.github.io/http/docs/classes/web.httpweb.html

Third Party Cookies on iOS

As of iOS 14, you cannot use 3rd party cookies by default. There is an open issue on the Capacitor Core repo on properly patching in cookies on iOS. For now, you must specify a domain of for the cookie you are saving to properly save and send them via requests. You can also add the following lines to your Info.plist file to get better support for cookies on iOS. You can add up to 10 domains.

<key>WKAppBoundDomains</key>
<array>
    <string>www.mydomain.com</string>
    <string>api.mydomain.com</string>
    <string>www.myothercooldomain.com</string>
</array>

Contributors ✨

Thanks goes to these wonderful people (emoji key):


Daniel Sogl

📖

Priyank Patel

💻

Max Lynch

💻

Falk Schieber

👀

Andy Sousa

💻

Thomas Vidas

💻 🚧

Emily Curry

💻

graefenhain

💻

Lee Houghton

🐛

Felix Schwarzmeier

💻

Kamil Jakubus

💻

Joe Flateau

🐛

Frank608

🐛

Joel Nieto

🐛

ultimate-tester

💻

Adrian Sanchez

🐛

milanc

💻

herecoulbeyourname

💻

Landschaft

💻

stonewoodman

🐛

Héctor Cruz

🐛

Patrick Bußmann

💻

Jesper Bjerke

🐛

This project follows the all-contributors specification. Contributions of any kind welcome!

http's People

Contributors

allcontributors[bot] avatar askurios8 avatar asztal avatar danielsogl avatar dependabot[bot] avatar emily-curry avatar felixschwarzmeier avatar imhoffd avatar imrdjai avatar jesperbjerke avatar jkbz64 avatar joeflateau avatar landschaft avatar lucashsilva avatar manuelsc avatar mghcs87 avatar mlynch avatar muuvmuuv avatar patrickbussmann avatar payen83 avatar priyankpat avatar robingenz avatar sbannigan avatar sisoje avatar sosoba avatar thiagosantos avatar thomasvidas avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

http's Issues

Data object not getting assigned for anything not json

Describe the bug
I was trying to get the plugin to work with an OAuth call and quickly realized the data block wasn't being set correctly.

For example

   const ret = Http.request({
      method: 'POST',
      url: '/api/auth/connect/token',
      headers: {
        'Content-Type': 'application/x-www-form-urlencoded',
      },
      data: urlSearchParams.toString()
    });

When i took a look at the web implementation of the plugin, makeFetchOptions(...) doesn't set the body of the request for any content type that isn't json

    makeFetchOptions(options, fetchExtra) {
        const req = Object.assign({ method: options.method || 'GET', headers: options.headers }, (fetchExtra || {}));
        const contentType = this.getRequestHeader(options.headers || {}, 'content-type') || '';
        if (contentType.indexOf('application/json') === 0) {
            req['body'] = JSON.stringify(options.data);
        }
        else if (contentType.indexOf('application/x-www-form-urlencoded') === 0) {
        }
        else if (contentType.indexOf('multipart/form-data') === 0) {
        }
        return req;
    }

Expected behavior
I would expect the data to be set for other types as well. This won't work with auth calls as a result. I have found this doesn't work in the native implementations either.

Send string in POST request

I am trying to make a POST request to an endpoint with the following:

async function getGames() {
    const response = await Http.request({
      method: 'POST',
      url: 'https://api-v3.igdb.com/games',
      headers: {
        'user-key': "xxxxxx",
        'Accept': "application/json"
      },
      data: "fields *, cover.*, release_dates.*; limit 50;"
    });
    return response;
  }

I am not able to send a string with the data property in this request.

Support Application Octet Stream

Is your feature request related to a problem? Please describe.
The full scope of HTTP is not presently supported by this plugin. The plugin naively assumes all responses are either JSON or some other UTF8 encoded string. This removes the possibility of interacting with APIs that return data with Content-Type application/octet-stream`.

Describe the solution you'd like
I would like the type of the data field of the response to depend on the Content-Type. Specifically, if the Content-Type is application/json it should be of type {} or []. If the Content-Type is application/octet-stream it should return either a Blob or an ArrayBuffer.

This will require some unfortunately wasteful changes along the native bridge since as far as I understand, the capacitor<->native bridge only supports a data type that is isomorphic to JSON. This problem can be solved by either a Hex or Base64 expansion across the capacitor barrier which is then re-compacted into the desired type before leaving the TypeScript side of the plugin to the calling code.

Describe alternatives you've considered
As far as alternatives go, I think there are only 2 real considerations here. 1. Blob vs ArrayBuffer as a TypeScript exit type. 2. Base16 (alignment) vs Base64 (space efficiency) as a utf8 string encoding over the capacitor<->native bridge.

Headers and params not set on web implementation

Describe the bug

The http headers are not send when set on web implementation

To Reproduce

This is just one example from one of my applications

    const result = await (Http as HttpPlugin).request({
      method: 'GET',
      url,
      // handle cors issues
      headers: {
        origin: 'x-requested-with',
      },
      params: {
        package: encodeURI(decodeURI(packageName)).replace('%252F', '%2F'),
        until: format(new Date(), 'YYYY-MM-DD'),
        from: fromDate,
      },
    });

Expected behavior

The we implementation of the plugin should set http headers and url params.

Response headers on Android have extra spaces and commas

Describe the bug
Hello, I think there's a bug with the returned headers values on Android, there's a comma and a space added at the end of every values. This can be problematic when retrieving a token from the response header.
I haven't tested on iOS so I don't know if it's a bug specific to Android.

Response headers in browser/Electron :

{
	content-length: "581"
	content-type: "text/html; charset=ISO-8859-1"
	date: "Tue, 27 Oct 2020 15:03:01 GMT"
	server: "Transmission"
	x-transmission-session-id: "xxxxxxxxxx"
}

Response headers in Android app :

[
	{},
	{"Content-Length":"581, "},
	{"Content-Type":"text/html; charset=ISO-8859-1, "},
	{"Date":"Tue, 27 Oct 2020 15:08:20 GMT, "},
	{"Server":"Transmission, "},
	{"X-Android-Received-Millis":"1603811299594, "},
	{"X-Android-Response-Source":"NETWORK 409, "},
	{"X-Android-Selected-Protocol":"http/1.1, "},
	{"X-Android-Sent-Millis":"1603811299593, "},
	{"X-Transmission-Session-Id":"xxxxxxxxxx, "}
]

To Reproduce

const ret = await Http.request({
    method: 'GET',
    url: 'https://example.com/my/api'
});
console.log(ret.headers);

Expected behavior
There shouldn't be content added at the end of the values.

Screenshots
Browser log:
capacitor-bug2

Android Studio log:
capacitor-bug3

Desktop (please complete the following information):

  • OS: Windows 10
  • Browser: Google Chrome
  • Version: 86.0.4240.111

Smartphone (please complete the following information):

  • Device: Pixel 3
  • OS: Android 11
  • Browser: Android Webview (capacitor)
  • Version: 2.4.2

Additional context
I'm using SDK for Android 11 (API level 30) to build the app.

Can this plugin override all HTTP calls?

Describe the bug

I'm trying to use Okta's Angular SDK and Sign-In Widget to embed a login form in my Ionic + Capacitor application. Everything works fine when I run it in my browser. When I try to run it in iOS Simulator, I get the following error:

Origin capacitor://localhost is not allowed by Access-Control-Allow-Origin.

I've known about this issue in the past and thought adding this plugin would solve the problem. Okta only allows http/s schemes for its Trusted Origins, and they're not (currently) willing to add support for capacitor://.

I tried installing this plugin to fix the problem:

npm install @capacitor-community/http
npx cap sync

Unfortunately, it still happens.

If I run the following command, it does use http://localhost:8100 as the origin instead of capacitor://localhost.

ionic capacitor run ios -l --host=localhost

To Reproduce
Steps to reproduce the behavior:

git clone -b angular-sdk https://github.com/oktadeveloper/okta-ionic-social-login-example
cd okta-ionic-social-login-example
npm i
npm run build
ionic capacitor add ios

Run app in Xcode, click Login, debug with Safari and you'll see the invalid origin error.

Expected behavior

This plugin overrides all origin headers to use http://localhost:8100 rather than capacitor://localhost.

Support array of params for same key

Is your feature request related to a problem? Please describe.
There is no way to send multiple query parameters for one key. For example:
/users?status=ACTIVE&status=INACTIVE

Describe the solution you'd like
It would be nice if the params object could accept both string and string array:

{
  ...
  params: {
    status: ['ACTIVE', 'INACTIVE'],
    otherParam: 'example'
  }
  ...
}

which would result in the following URL: /users?status=ACTIVE&status=INACTIVE&otherParam=example.

Describe alternatives you've considered
An alternative to this would be to send multiple values separated by a comma: /users?staus=ACTIVE,INACTIVE. However, this would require the server to support this way of sending query params.

Additional context
This is a common way APIs handle filtering, therefore this would be a nice feature to have.

Query params aren't sent with POST, PUT, or PATCH requests (android and iOS)

Describe the bug
Query params aren't sent with POST, PUT, or PATCH requests.

To Reproduce

const doPost = () => {
  const { Http } = Plugins;

  const ret = await Http.request({
    method: 'POST',
    url: 'https://example.com/my/api',
    headers: {
      'X-Fake-Header': 'Max was here',
      'Content-Type': 'application/json'
    },
    params: {
       size: 'XL'
    },
    data: {
      foo: 'bar',
      cool: true
    }
  });
}

Expected behavior
It would make sense that the request is sent with the provided query params:
POST https://example.com/my/api?size=XL

DownloadFile from Azure Blob Storage

Describe the bug
I'm trying to download an URL from azure storage, the link is generated with an access signature.

https://--test.blob.core.windows.net/--/message-attachments/3d1b73aa-4818-4d7d-a634-c165ceaf6e69.pdf?sv=2019-02-02&sr=b&sig=AuBDZA2%2B5LZUqtHbI7FOneOM0wKVy2bIUu3v%2BJgXoMA%3D&se=2020-10-06T19%3A06%3A35Z&sp=r

I've tried also the decodeURIComponent version of the URL:

https://--test.blob.core.windows.net/--/message-attachments/3d1b73aa-4818-4d7d-a634-c165ceaf6e69.pdf?sv=2019-02-02&sr=b&sig=AuBDZA2+5LZUqtHbI7FOneOM0wKVy2bIUu3v+JgXoMA=&se=2020-10-06T19:06:35Z&sp=r

The plugin is not working most probably while using "URL url = new URL(urlString);" in the downloadFile function,
it's giving "file not found" because of +/= characters that can be added in the signature.

It's adding number 5 after %2:

Original: AuBDZA2%2B5LZUqtHbI7FOneOM0wKVy2bIUu3v%2BJgXoMA%3D

Becoming: AuBDZA2%252B5LZUqtHbI7FOneOM0wKVy2bIUu3v%252BJgXoMA%253D

This is causing the file not to be found with the correct signature.

The below error found in the Android console:


E/Capacitor/Plugin: Error
    java.io.FileNotFoundException: https://--test.blob.core.windows.net/--/message-attachments/3d1b73aa-4818-4d7d-a634-c165ceaf6e69.pdf?sv=2019-02-02&sr=b&sig=AuBDZA2%252B5LZUqtHbI7FOneOM0wKVy2bIUu3v%252BJgXoMA%253D&se=2020-10-06T19%253A06%253A35Z&sp=r
        at com.android.okhttp.internal.huc.HttpURLConnectionImpl.getInputStream(HttpURLConnectionImpl.java:255)
        at com.android.okhttp.internal.huc.DelegatingHttpsURLConnection.getInputStream(DelegatingHttpsURLConnection.java:211)
        at com.android.okhttp.internal.huc.HttpsURLConnectionImpl.getInputStream(HttpsURLConnectionImpl.java:30)
        at com.getcapacitor.plugin.http.Http.downloadFile(Http.java:167)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.getcapacitor.PluginHandle.invoke(PluginHandle.java:99)
        at com.getcapacitor.Bridge$1.run(Bridge.java:526)
        at android.os.Handler.handleCallback(Handler.java:888)
        at android.os.Handler.dispatchMessage(Handler.java:100)
        at android.os.Looper.loop(Looper.java:213)
        at android.os.HandlerThread.run(HandlerThread.java:67)

--

Expected behavior
The URL should be working even with these characters

Screenshots
Screen Shot 2020-10-06 at 10 07 26 PM

Jest has issues with this package.

Describe the bug

When I try to test code that references a service, which in turn uses this package, I get the following error:

● Test suite failed to run

Jest encountered an unexpected token

This usually means that you are trying to import a file which Jest cannot parse, e.g. it's not plain JavaScript.

By default, if Jest sees a Babel config, it will use that to transform your files, ignoring "node_modules".

Here's what you can do:
 • To have some of your "node_modules" files transformed, you can specify a custom "transformIgnorePatterns" in your config.
 • If you need a custom transformation specify a "transform" option in your config.
 • If you simply want to mock your non-JS modules (e.g. binary assets) you can stub them out with the "moduleNameMapper" config option.

You'll find more details and examples of these config options in the docs:
https://jestjs.io/docs/en/configuration.html

Details:

/Users/xxxxx/Code/xxxxxx/node_modules/@capacitor-community/http/dist/esm/index.js:1
({"Object.<anonymous>":function(module,exports,require,__dirname,__filename,global,jest){export * from './web';
                                                                                         ^^^^^^

SyntaxError: Unexpected token export

  1 | import { Plugins, FilesystemDirectory } from '@capacitor/core';
> 2 | import "@capacitor-community/http";
    | ^
  3 | import pako from 'pako';
  4 | 
  5 | const ManifestDownloadService = () => {

  at ScriptTransformer._transformAndBuildScript (node_modules/@jest/transform/build/ScriptTransformer.js:537:17)
  at ScriptTransformer.transform (node_modules/@jest/transform/build/ScriptTransformer.js:579:25)
  at Object.<anonymous> (src/services/manifestDownloadService.ts:2:1)

Expected behavior
I would expect this to work without failing the tests.

Desktop (please complete the following information):

  • OS: OSX
  • Browser N/A

Additional context

Ionic:

Ionic CLI : 6.8.0 (/usr/local/lib/node_modules/@ionic/cli)
Ionic Framework : @ionic/react 5.2.2

Capacitor:

Capacitor CLI : 2.2.0
@capacitor/core : 2.2.0

Utility:

cordova-res (update available: 0.15.1) : 0.6.0
native-run (update available: 1.0.0) : 0.2.7

System:

NodeJS : v10.16.3 (/usr/local/bin/node)
npm : 6.13.4
OS : macOS Catalina

Return Headers when downloading a file

Is your feature request related to a problem? Please describe.
In my use case I'd like to download files via this plugin and store a reference in my database. For further procedures I need the mime type which could be retrieved via Content-Type header in the response object. But unfortunately this plugin does not grant access to response metadata when using the downloadFile method.

Describe the solution you'd like
Make the HttpDownloadFileResult object extend the HttpResponse so that status code and headers will be returned.

Describe alternatives you've considered
Making a request beforehand to get the mime type via HEAD request is not viable since I am doing a lot of requests resulting in 2x the request amount.

Additional context

NSURLErrorDomain: Unsupported URL

Describe the bug

I am transforming our services to this native solution ATM and everything works fine except the transloco language module which seems to only work with Angular HTTP Client. If I am changing the loader to native HTTP I get the following error from Xcode:

2020-07-09 18:33:56.457867+0200 App[51816:1435020] Task <25F642A2-F3D3-4215-B364-B443A1F2AB7A>.<5> finished with error [-1002] Error Domain=NSURLErrorDomain Code=-1002 "unsupported URL" UserInfo={NSUnderlyingError=0x6000034fa550 {Error Domain=kCFErrorDomainCFNetwork Code=-1002 "(null)"}, NSErrorFailingURLStringKey=/languages/de-DE.json?, NSErrorFailingURLKey=/languages/de-DE.json?, NSLocalizedDescription=unsupported URL}
ERROR MESSAGE:  {"message":"Error","errorMessage":"unsupported URL","code":"GET"}

To Reproduce

I am going to add one if the above error is not clear enough.

Steps to reproduce the behavior:

  1. Go to '...'
  2. Click on '....'
  3. Scroll down to '....'
  4. See error

Expected behavior
A clear and concise description of what you expected to happen.

Screenshots
If applicable, add screenshots to help explain your problem.

Desktop (please complete the following information):

  • OS: [e.g. iOS]
  • Browser [e.g. chrome, safari]
  • Version [e.g. 22]

Smartphone (please complete the following information):

  • Device: [e.g. iPhone6]
  • OS: [e.g. iOS8.1]
  • Browser [e.g. stock browser, safari]
  • Version [e.g. 22]

Additional context

I guess that it just has issues with getting local files so maybe it needs a prefix or something like file://.

Passing cookies to in-app browser

I'm currently trying to use the cookies, which are set using Http.setCookie({...}), in the Capacitor in-app Browser.

import '@capacitor-community/http';
import { Plugins } from '@capacitor/core';

...

async test() {
  const { Http, Browser } = Plugins;
  await Http.setCookie({
      url: URL,
      key: KEY,
      value: VALUE
    });
  await Browser.open({ url: URL});
}

Unfortunately, just setting the cookies and opening the browser is not working, document.cookie does not contain the set cookies. Am I missing something or is this currently not supported?

Cannot get csrf_token from instagram.com

Describe the bug
Hello everyone, csrf_token is a value that you can find inside the page source of the Instagram website, you can simply find it by performing a GET request to https://www.instagram.com then using a simple regex on the returned HTML code.
It's important because it's used as a header value (X-CSRFToken) which needed for login and challenge requests.
So here is my issue: using capacitor http plugin somehow doesn't return that value at all!

To Reproduce
So here is exactly what I did: on browser and node, I was able to use fetch to get csrf_token without any problem:

Here is the code: fetch('https://www.instagram.com/').then(async res => console.log(JSON.stringify(await res.text()).match(/csrf_token.{40}/)[0]))

browser (same origin):
1

node (node-fetch module):
2

But, on capacitor using this plugin:

3

code (executed on eruda console): Http.request({ method: 'GET', url: 'https://www.instagram.com/'}).then(res => console.log(JSON.stringify(res.data).match(/csrf_token.{40}/)[0]))

Expected behavior
It only gives an empty object instead, it should gives a string.

Desktop (please complete the following information):

  • OS: windows 10.
  • Browser: tested on opera and icedragon.
  • Version: least for both.

Smartphone (please complete the following information):

  • Device: LD Player Android Emulator.
  • OS: Android 7.1.2.
  • Browser: Android Webview (capacitor).
  • Version: I'm not sure.

Additional context
I think Instagram detects requests from this plugin as automated requests, so it hides the value to prevent bots/custom clients from login.

json request 204 crash on chrome

Describe the bug
http.request crash with the error 'Uncaught SyntaxError: Unexpected end of JSON input', when the server return a 204.
When investigating, it really look like the method try to "JSON.parse('')", and throw the error, instead of a type 204.
It's working fine on mobile devices (at least on android), and on firefox.

To Reproduce
Steps to reproduce the behavior:

Http.request({
    method,
    url,
 }).then(e => {
    if(response.status === 204) console.warn("204")
  }).catch(e => {
     console.warn(e)
});

In firefox, mobile, it show the 204 message
On chrome, it show the 'Uncaught SyntaxError: Unexpected end of JSON input'

Expected behavior
On chrome, it should have the same behavior than on firefox-> to succeed, with the status value set to 204

Desktop (please complete the following information):

  • OS: windows 10
  • Browser: chrome
  • Version 87.0.4280.141

downloadFile should not return when statusCode is not in 2xx range

Describe the bug
Using the downloadFile method successfully resolves even when the http statuscode is not in the 2xx range.

To Reproduce
Steps to reproduce the behavior:

  1. run the following code:
try {
   const result = await Http.downloadFile({
     url: 'https://bogus.com/myimage.png,
     filePath: 'myfilename.png',
     fileDirectory: FilesystemDirectory.Cache
   });
   console.log('download result: ', result);
} catch (error) {
   console.error('download error: ', error);
}

Expected behavior
I would expect the method to fail since the http statuscode in the example is equal to: 404.
Any statuscode that is not in the range of 2xx should reject the downloadFile method invocation.

On ios and web the downloadFile method will resolve successfully. On android you will end up in your catch block (like expected).
So there's a mismatch in Capacitor http api depending on the platform that should be handled by this plugin.

Screenshots
N/A

Additional context

"@capacitor-community/http": "^0.2.1

Changing capacitor://localhost to http://localhost

Describe the bug
For google auth, I need to have http since google's Authorized JavaScript origins only accept http. I've tried changing our fetch calls to Http.request but when I run it on iOS, I'm still getting capacitor://localhost.

Is there anyway to make the calls http instead of capacitor? I saw #45 but wasn't sure if that was asking for a blanket way to change all calls to http:// instead of changing all fetch calls to use Http.request.

Due to my poor understanding of this library, what is the purpose of this library if it's not for the purpose above of changing capacitor:// to http://?

Expected behavior
if I use Http.request to make a call on iOS, the origin should start with http:// instead of capacitor://

Can't get cookies on iOS

Question

I'm here because of the wkwebview issue of getting and setting cookies and hoped that this plugin will resolve this problems.
So i tried the Http.getCookie({url: ....}) method but the result is every time an empty array.

The first request to an IDP is done via an other framework so not with the Http Plugin. The IDP is setting the cookie. But it is not seen in Developer Console with Chrome when debugging on mobile. The cookie is seen when hosting the app in real browser but there also the plugins Http.GetCookie method returns an empty array.

So my Question is how to receive Cookies from other websites and send them with request to the same website?

I hope you can help me

204 crash on chrome (json)

Describe the bug
http.request crash with the error 'Uncaught SyntaxError: Unexpected end of JSON input', when the server return a 204.
When investigating, it really look like the method try to "JSON.parse('')", and throw the error, instead of a type 204.
It's working fine on mobile devices (at least on android), and on firefox.

To Reproduce
Steps to reproduce the behavior:

Http.request({
    method,
    url,
 }).then(response => {
    if(response.status === 204) console.warn("204")
  }).catch(e => {
     console.warn(e)
});

In firefox, mobile, it show the 204 message
On chrome, it show the 'Uncaught SyntaxError: Unexpected end of JSON input'

Expected behavior
On chrome, it should have the same behavior than on firefox-> to succeed, with the status value set to 204

Desktop (please complete the following information):

  • OS: windows 10
  • Browser: chrome
  • Version 87.0.4280.141

iOS Security Cache Vulnerability

When you make a request in iOS the information is stored and not encrypted in cache.db file

I suggest make an option in the interface to avoid caching the request.

Follow redirects

Is your feature request related to a problem? Please describe.

Either get or downloadFile both should follow redirects until the final endpoint is reached.

Describe the solution you'd like

If response 301/302 request again until final resource is reached.

Describe alternatives you've considered

None

Additional context

For example download a file from https://source.unsplash.com/150x150/weekly/?nature

Post does not append body to request

Describe the bug
When I do a post request, the http request does not send the json that is in the data field.

To Reproduce
Steps to reproduce the behavior:
Literally follow the tutorial

Expected behavior
A post request with the body.

Desktop (please complete the following information):
Browser Chrome/Brave

Additional context
Add any other context about the problem here.

Inconsistent results when calling API from different platforms

I'm sure if this is an issue with the platforms, my backend (old framework), or this package.

When making an HTTP request with a body of data different configuration needs to be used for iOS and Android.

When using "application/x-www-form-urlencoded" with iOS results in the requests data being decoded automatically.
When using "application/json" with Android the requests data is empty.

The issues below resolve themselves when using "application/json" on iOS and "application/x-www-form-urlencoded" for Android.

To Reproduce
IOS:
{ url: string, method: "POST", data: { "email": "[email protected]" }, headers: { "Content-Type": "application/x-www-form-urlencoded" } }

The body received by the server { "email": "email [email protected]" }

Android:
Request { url: string, method: "POST", data: { "email": "[email protected]" }, headers: { "Content-Type": "application/json" } }

The body received by the server {}

Expected behaviour
Results should be consistent across platforms, where $_POST['email'] would return "[email protected]"

Smartphone: IOS

  • Device: Emulator
  • OS: iOS12, iOS12.4, iOS14.4
    (Apple tester also experienced this issue when testing the app before approving it for the App Store, the test on physical devices)

Smartphone: Android

  • Device: Emulator, Redmi Note 9, Samsung S6
  • OS: Android 6, 10

Uploadfile Error: non-convertible Response

Hallo everyone,

the upload fails if the response is not a Json string. But the file can be found on the server. It seems to me that the plugin only works if the request and response are both Json-string. E.g. the normal POST-requests ("Content-Type": "application/text; charset=UTF-8") will also fail if the attribute "Data" or the Response is not convertible string.
Is that so or am I doing something wrong?

best regards,
Matari

URL paths are decoded prior to request on Android

Describe the bug
When making a request to a URL that includes encoded characters (e.g. %2F), those character sequences are decoded prior to making the the request. This breaks requests that expect such escape sequences (e.g. Firebase storage refs).

Example:
https://firebasestorage.googleapis.com/v0/b/xxxxxx/o/path%2Fto%2Ffile.json becomes https://firebasestorage.googleapis.com/v0/b/xxxxxx/o/path/to/file.json

This is caused by the following line in the setParams() method, due to the use of URI.getPath() which returns a decoded path:
URI newUri = new URI(uri.getScheme(), uri.getAuthority(), uri.getPath(), newQuery, uri.getFragment());

To Reproduce
Steps to reproduce the behavior:

  1. Invoke the Http plugin on an Android device or simulator, using a URL containing an encoded character sequence

Expected behavior
A request is made to the provided URL, as it was provided

Smartphone (please complete the following information):

  • Device: Pixel 2 Simulator
  • OS: Android
  • Browser: Stock web view
  • Version: API 30

Returning http headers behave differently on each platform

Describe the bug
I'm trying to read a custom http header which is set a server.
I've noticed that on each platform. ios/android/browser the headers are structured diffently which requires a diffrent handling on each platform.
This leads to the following:

 // if web
 token = res.headers['some-token']; // chrome on desktop is returning all lowercase header names
 //else if iOS
  token = res.headers['Some-Token']; // Case sensitive on iOS
 // else if Android
 token = res.headers[1]['Some-Token']; // Android is returning a 2d headers array 

Expected behavior
Reading headers should be consistent on all platforms

Desktop (please complete the following information):

Smartphone (please complete the following information):

  • Device: Android10, Ios13
  • Browser Chrome
  • Version 0.2.1

Additional context
This is tested in ionic4 project

Allow `expires` parameter for `Http.setCookie(...)`

Is your feature request related to a problem? Please describe.
As a web developer familiar with cookies, I would assume Http.setCookie() to have a parameter called expires, as opposed to ageDays.

Describe the solution you'd like
I would prefer an input option for expires to exist, instead of ageDays

Describe alternatives you've considered
Provide a helper function to calculated an appropriate ageDays value, given an expires date.

Additional context
I personally think it is more complicated to derive ageDays from expires than it is to derive expires from ageDays.

JSON-Response null: value null of type org.json.jsonobject$1 cannot be converted to jsonobject

Describe the bug
When I do a HTTP request and the response is a json value null, then throws a exception

Versions
@capacitor/[email protected]
@capacitor/[email protected]
@capacitor-community/[email protected]

To Reproduce
Steps to reproduce the behavior:

  1. Call request to an webserver
  2. Result from webserver is null
  3. See error in Android Studio or Chrome Debugger

Expected behavior
Attribute data in result object is a null-value

Smartphone:

  • Device: Samsung S10
  • OS: Android

Additional context

    org.json.JSONException: Value null of type org.json.JSONObject$1 cannot be converted to JSONArray
        at org.json.JSON.typeMismatch(JSON.java:112)
        at org.json.JSONArray.<init>(JSONArray.java:98)
        at org.json.JSONArray.<init>(JSONArray.java:110)
        at com.getcapacitor.JSArray.<init>(JSArray.java:17)
        at com.getcapacitor.plugin.http.Http.buildResponse(Http.java:394)
        at com.getcapacitor.plugin.http.Http.get(Http.java:83)
        at com.getcapacitor.plugin.http.Http.request(Http.java:64)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.getcapacitor.PluginHandle.invoke(PluginHandle.java:99)
        at com.getcapacitor.Bridge$1.run(Bridge.java:542)
        at android.os.Handler.handleCallback(Handler.java:883)
        at android.os.Handler.dispatchMessage(Handler.java:100)
        at android.os.Looper.loop(Looper.java:237)
        at android.os.HandlerThread.run(HandlerThread.java:67)

But the originally exception throws at Http.java:391
org.json.JSONException: Value null of type org.json.JSONObject$1 cannot be converted to JSONObject

iOS appends question mark to URL when params are empty

On 0.2.1 when executing a GET request with iOS, a question mark is appended to the URL if the params are empty. Depending on your server-side app, this could cause problems. My own solution was to add a dummy param.

Support reporting progress

Is your feature request related to a problem? Please describe.

We use an Angular feature called reportProgress to track the progress e.g. on a file upload. So the user see how far the upload/download has gone without showing him an infinity spinner. Would be great to have it in native support as well.

See: https://angular.io/guide/http#report-progress

Our Angular httpClient function ATM:

function uploadAvatar(base64: string): Observable<any> {
  const url = `${this.URI}/me/avatar`

  const formData = new FormData()
  formData.append('avatar', base64ToFile(base64))

  return this.http
    .post(url, formData, {
      reportProgress: true,
      observe: 'events',
    })
    .pipe(
      map((event) => this.getEventMessage(event)),
      catchError(this.handleError)
    )
}

Describe the solution you'd like

A new option in HttpOptions to allow tracking progress. Returning an observable seems pretty good, like the Angular httpClient does it.

See: https://github.com/angular/angular/blob/d1ea1f4c7f3358b730b0d94e65b00bc28cae279c/packages/common/http/src/xhr.ts#L314

Describe alternatives you've considered

No I can think of rn.

Additional context

If this is going to get accepted, I would add a "How to test" section to describe how to test such feature with network throttling.

CORS

Describe the bug
Unable to test the plugin with development server running on localhost:8100

Steps to reproduce the behavior:

  1. ionic serve --livereload
  2. Code:
    const ret = await Http.request({
    method: 'GET',
    url: 'http://www.bilbao.eus/cs/Satellite?c=Page&cid=1272990237857&pageid=1272990237857&idioma=es&pagename=Bilbaonet/Page/BIO_ListadoEventosAppInfoBilbao&todos=si.json'
    });
    console.log(JSON.stringify(ret.data));

Working on devices but fails on browser

  • Browser : Chrome / Firefox
  • Error traces:

from origin 'http://localhost:8100' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.

Thank you for your time and exceptional job!

Unable to use setCookie() method from the native http plugin for capacitor

Describe the bug
A clear and concise description of what the bug is.
The project is a Angular/Ionic based. It had the issue with the native IOS not retaining the cookies after authentication to do any subsequent requests. I tried to install the @capacitor-community/http plugin and use the Http to make requests instead of "httpClient" imported from angular. The setCookie() method is not setting the Auth cookie before performing a get/post request.

The below is the screenshot of the Request headers using the angular httpClient (It is having the cookie included in the request header)
Cookie1

The below is the screenshot of the Request headers using the native http plugin (It is missing the cookie in the request header)
Cookie2

CODE SNIPPET:

async get(path, method): Promise<Observable> {
const { Http } = Plugins;
try {
const { Http } = Plugins;
const cookies = await Http.getCookies({
url: this.apiUrl("/cookie"),
});
console.log(cookies);
let retValue = "";
for (let i = 0; i < cookies.value.length; i++) {
retValue = cookies.value[0].value;
}
await Http.setCookie({
url: "http://localhost:8102/",
key: ".ASPXAUTH",
value: retValue,
});
const ret = await Http.request({
method: method,
url: this.apiUrl(path),
headers: {
"X-Fake-Header": "Max was here",
"Content-Type": "application/json",
withCredentials: true,
},
});
console.log("Got ret", ret);
return ret;
} catch (e) {
console.error(e);
}
}

buildResponse doesn't catch IOException

When response is GZIP I get exception:

E/Capacitor/Plugin: Error org.json.JSONException: Value ������^��� of type java.lang.String cannot be converted to JSONArray at org.json.JSON.typeMismatch(JSON.java:111) at org.json.JSONArray.<init>(JSONArray.java:96) at org.json.JSONArray.<init>(JSONArray.java:108) at com.getcapacitor.JSArray.<init>(JSArray.java:17) at com.getcapacitor.plugin.http.Http.buildResponse(Http.java:394) at com.getcapacitor.plugin.http.Http.get(Http.java:83) at com.getcapacitor.plugin.http.Http.request(Http.java:64) at java.lang.reflect.Method.invoke(Native Method) at com.getcapacitor.PluginHandle.invoke(PluginHandle.java:99) at com.getcapacitor.Bridge$1.run(Bridge.java:517) at android.os.Handler.handleCallback(Handler.java:790) at android.os.Handler.dispatchMessage(Handler.java:99) at android.os.Looper.loop(Looper.java:164) at android.os.HandlerThread.run(HandlerThread.java:65)

Describe the bug
If response is gzip HttpURLConnection doesn't decompress data automaticaly

To Reproduce
Steps to reproduce the behavior:

  1. Try to fetch gzip compressed url
  2. See error

Smartphone (please complete the following information):

  • Device: [Nexus 5x]
  • OS: [Android 8]

Expected behavior
Should decode GZIP response with GZIPInputStream

Additional context
String encoding = conn.getContentEncoding(); if (encoding != null && encoding.contains("gzip")) { stream = new GZIPInputStream(stream); }

`decodeURIComponent` when getting cookies and `encodeURIComponent` when setting them

Describe the bug
All web frameworks encode Cookies with a function similar to encodeURIComponent (eg. Laravel XSRF-TOKEN) and consequentially need to be decoded with decodeURIComponent when retrived by Http.getCookies (and encoded when set).

Expected behavior
Cookies should be encoded with encodeURIComponent when set and decoded with decodeURIComponent when retrieved.

Additional context
https://stackoverflow.com/questions/1969232/what-are-allowed-characters-in-cookies/1969339#1969339

https://stackoverflow.com/questions/49205195/should-cookie-values-be-url-encoded

How to send body in a Post request

Describe the bug
I seem to be unable to send the body the http request

To Reproduce

const req = await Http.request({
      method: 'GET',
      headers: headers,
      url: this.apiLink + '/tests',
      body: paths
    });
    return req.data;

Smartphone (please complete the following information):

  • Device: Iphone Emulator

Is it possible to send it as body? or is it through data?

new JSONArray() trow error while parsing array of non primitive types

Describe the bug
Out BE is sending array of objects in response. While plugin is processing response it trow this error in Android Studio console
2020-06-23 11:31:15.059 14364-14445/com.my.app E/Capacitor/Plugin: Error org.json.JSONException: Not a primitive array: class java.lang.String at org.json.JSONArray.<init>(JSONArray.java:118) at com.getcapacitor.JSArray.<init>(JSArray.java:21) at com.getcapacitor.plugin.http.Http.buildResponse(Http.java:395) at com.getcapacitor.plugin.http.Http.get(Http.java:83) at com.getcapacitor.plugin.http.Http.request(Http.java:64) at java.lang.reflect.Method.invoke(Native Method) at com.getcapacitor.PluginHandle.invoke(PluginHandle.java:99) at com.getcapacitor.Bridge$1.run(Bridge.java:520) at android.os.Handler.handleCallback(Handler.java:883) at android.os.Handler.dispatchMessage(Handler.java:100) at android.os.Looper.loop(Looper.java:214) at android.os.HandlerThread.run(HandlerThread.java:67)

To Reproduce

  1. Try to get array of objects from server

Smartphone:

  • Device: Pixel 3 (Virtualized)
  • OS: Android 10

Additional context
Example response from BE
[ { "id": "XXXXX", "name": "xxxx", "info": "xyz", "available-from": "2020-05-01" }, { "id": "YYYY", "name": "yyyyy", "info": "yzx", "available-from": "2020-05-01" } ]

Error appears to be in Http.java. While plugins is trying to buildResponse that should be send back to "webview".
JSArray jsonValue = new JSArray(builder.toString());

We made a quick fix just as POC. Basically we just wrapped array in object and parse it like that.

//JSArray jsonValue = new JSArray(builder.toString());
JSObject jsonValue = new JSObject("{\"_CAPACITOR_FIX_ARRAY\": " + builder+ "}");
ret.put("data", jsonValue);

Support SSL pinning

Is your feature request related to a problem? Please describe.

We are currently trying to make SSL pinning work but because that does not work with Angular's httpClient I was looking for a native plugin and this Capacitor equivalent of cordova-plugin-advanced-http looks pretty good so far. Adding support for SSL pinning would make it more enterprise ready in my opinion.

See: silkimen/cordova-plugin-advanced-http#setservertrustmode

Describe the solution you'd like

Add a cordova-plugin-advanced-http#setservertrustmode equivalent or similar.

Describe alternatives you've considered

Always open for better/more secure solutions.

Additional context

I would love to but haven't added SSL pinning in any of my projects so I hope someone else will add more information about securing requests here.

No podspec found for `CapacitorCommunityHttp`

Describe the bug
When running npx cap sync after installing the http plugin the following error is given out.

✖ Updating iOS native dependencies with "pod install" (may take several minutes): 
✖ update ios: 
[error] Error running update: Analyzing dependencies
[!] No podspec found for `CapacitorCommunityHttp` in `../../node_modules/@capacitor-community/http`

Expected behavior

The missing field should be deployed with the next plugin update

URL Params not set on web

Describe the bug
Params defined in the params options are not set

To Reproduce

This request will be translated into following url

    const response = await Capacitor.Plugins.Http.request({
      method: 'GET',
      url: 'https://api.rss2json.com/v1/api.json',
      params: {
        rss_url: environment.npmBlogEndpoint,
        api_key: environment.rss2jsonApiKey,
        count: '100'
      }
    });
// expected URL
https://api.rss2json.com/v1/api.json?rss_url=http://blog.npmjs.org/rss&api_key=vaamv0bymd6t8b2lorlzway3ph5wg6gpauwfuk7a&count=100

// Requested URL
https://api.rss2json.com/v1/api.json

Expected behavior
The url params should been set correctly

Add Timeout Support to iOS

Is your feature request related to a problem? Please describe.
It seems that the timeout (both connectTimeout and readTimeout) is supported on Android however similar feature is not available for iOS platform.

Describe the solution you'd like
Support timeout for http requests for both, iOS and Android.

Describe alternatives you've considered
The cordova-plugin-advanced-http cordova plugin supports this feature https://github.com/silkimen/cordova-plugin-advanced-http#setrequesttimeout (even though there are some caveats - see silkimen/cordova-plugin-advanced-http#316)

Additional context
N/A

downloadFile fails on IOS if the path already exists

Describe the bug
I can't download a file and replace the existing one

couldn’t be moved to “Caches” because an item with the same name already exists.

To Reproduce
use downloadFile twice on an ios device

Expected behavior
We should be able to override the existing file

Smartphone (please complete the following information):

  • OS: IOS

client waits for server response before sending next request

Describe the bug
my server does not receive the next request before sending response to the client

To Reproduce
Steps to reproduce the behavior:

K0g0iA4gxV

Expected behavior

like angular http

P7ynLkWs4e

works also fine when using 'ionic serve'

Screenshots

what happens :

gPzeAAPr05

Smartphone (please complete the following information):

  • Device: Redmi note 7 Android 10

Additional context
Add any other context about the problem here.

Can someone help ? i'm not sure if i'm doing something wrong.

thanks a lot.

Capacitor transition

Hi @mlynch ✌️, I've heard about this plugin today in Ioniconf keynote (great job by the way) and wanted to reach out to you. Don't know if I chose the right place 😅. I'm the maintainer of cordova-plugin-advanced-http. I like the idea of capacitor and I do truly believe that it'll be the future of hybrid app development. But for the time being a lot of people are still using cordova (me too). HTTP requests are one of the essential functionalities needed for this purpose.

Maybe we can work together to make the transition easier? Bringing the feature list in sync with this plugin maybe? What do you think?

POST Data is not passing.

Desktop (please complete the following information):

  • OS: Windows
  • Browser Chrome
  • Version 88.0.4324.11 (Official Build) dev (64-bit)

Trying to use in Ionic Vue.

Http.request({
method: 'POST',
url: ApiHost + '/api/v1/seller/login',
data: {phone : this.phone, password: this.password},
headers: {
'X-Fake-Header': 'Max was here'
},
params: {
size: 'XL'
}
}).then((res)=>{
if(res.status == 200){
Storage.set({ key: 'token', value: res.data.token }).then((res)=>{
this.route.push('/register/step/2');
});
}else{
this.logging = false;
}
});

API request with non ascii characters brokes the server response

Describe the bug
We are having a big problem with this encoding here:
Screen Shot 2021-01-07 at 13 06 25

This is a request made from our application to the backend: getting a bug.
Screenshot from 2021-01-07 17-29-09

Every time we sent text with Turkish character from the application we get this bug; looking on how fixing this we meet this pull request which seems to solve the bug, but this pull request is not yet in the last plugin's version.

To Reproduce
Steps to reproduce the behavior:

  1. Create an object with some non ascii character to be the request body.
  2. Send the request to the backend through the api.
  3. Get the response from the server on the console log.

Expected behavior
A true response from the backend.

Screenshots
Screen Shot 2021-01-07 at 13 06 25

Desktop (please complete the following information):

  • OS: [e.g. iOS]
  • Browser [e.g. chrome, safari]
  • Version [e.g. 22]

Smartphone (please complete the following information):

  • Device: Lenovo Tab M10 (FHD)
  • OS: Android 9
  • Browser [e.g. stock browser, safari]
  • Version 0.2.1

Additional context
There is a possible solution already in this plugin's base code, but it is not in the last version.

downloadFile and uploadFile ignore headers object

Describe the bug

When downloading or uploading a file from a protected resource and sending an authorization header (or any other headers) the native iOS code doesn't use the headers to build the request.

Environments

  • Android
  • iOS

To Reproduce

const options: any = {
      url: https://your-host/proteced-download,
      name: 'file',
      filePath: filePath,
      headers: {
        Authorization: `Bearer ${accessToken}`
      }
 };

Http.uploadFile(options)

Expected behavior

Both HttpDownloadFileOptions and HttpDownloadFileOptions extend HttpDownloadFileOptions which has the headers object as an optional parameter. The download/upload functions should accept the headers object like it does on Android.

request on android 9 not working

I get this response {message: "Error"} when i try to make request in android .But it works fine on the browser. here is my envronnement :

Ionic:

Ionic CLI : 6.1.0 (C:\Users\Dame\AppData\Roaming\npm\node_modules@ionic\cli)
Ionic Framework : @ionic/angular 5.5.2
@angular-devkit/build-angular : 0.1101.1
@angular-devkit/schematics : 10.0.8
@angular/cli : 11.1.1
@ionic/angular-toolkit : 2.3.3

Capacitor:

Capacitor CLI : 2.4.6
@capacitor/core : 2.4.6

Utility:

cordova-res : 0.8.1
native-run : 0.2.9

System:

NodeJS : v12.13.1 (G:\Program Files\nodejs\node.exe)
npm : 6.14.5
OS : Windows 10

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.