如何更改 pouchDB 使用的 http 客户端?

How to change the http client used by pouchDB?

我在离子应用程序中使用 PouchDB 和 CouchDB。虽然我可以在 Chrome 和 Android 上成功同步本地和远程数据库,但当我 运行 同步命令时,我在 Safari / iOS 上遇到未经授权的错误。下面是我的数据库服务提供商的简化版本。

import PouchDB from 'pouchdb';
import PouchDBAuthentication from 'pouchdb-authentication';

@Injectable()
export class CouchDbServiceProvider {
    private db: any;
    private remote: any;
    constructor() {
      PouchDB.plugin(PouchDBAuthentication);
      this.db = new PouchDB('localdb', {skip_setup: true});
    }
    ...
    login(credentials) {
      let couchDBurl = 'URL of my couchDB database';
      this.remote = new PouchDB(couchDBurl); 
      this.remote.logIn(credentials.username, credentials.password, function (err, response) {
            if (err) { concole.log('login error') }
            else {
                let options = { live: true, retry: true, continuous: true };
                this.db.sync(this.remote, options).on('error', (err_) => { console.log('sync error')});
            }
      })
    }
    ...
}

在上面的代码中,this.remote.logIn(...) 成功但 this.db.sync(...) 失败。我已经通过开发人员工具的网络选项卡检查了请求,我认为问题在于 this.remote.logIn(...) 的响应 header 中 ret运行ed 的 cookie 未被后续调用使用(因此是未经授权的错误)。在 Safari 上启用 third-party cookie 后,问题得到解决,这不是 iOS 上的选项。

我该如何解决这个问题?

我正在考虑的一个潜在解决方案是覆盖 fetch 以使用本机 http 客户端(即,来自 @ionic-native/httpHTTP 的实例)。似乎可以修改 http 客户端(例如,根据此 conversation),但我不确定如何实现。

更改 HTTP 管道听起来像是一个非常糟糕的主意 - 主要是时间成本 - 除非你绝对必须使用 sessions/cookies...如果你不这样做,请继续阅读。

作为 noted here regarding pouchDB Security, I tried using pouchdb-authentication 积极维护 并且由于多个问题而走另一条路(我不记得具体情况,那是 6 年前)。

请注意,上次提交 pouchdb-authentication 似乎是 3 年前。尽管从表面上看,不活动并不是一个负面指标——一个项目可能只是得出了一个可靠的结论——安装 pouchdb-authentication 会产生这个

found 6 vulnerabilities (2 moderate, 3 high, 1 critical)

再加上过去几年对插件缺乏热爱,导致新项目增加了危险的技术债务。

如果可能,只需在创建(或打开)远程数据库时使用 auth 选项发送凭据,例如

const credentials = { username: 'foo', passwd: 'bar' };
this.remote = new PouchDB(couchDBurl, { auth: credentials }); 

我不记得为什么,但我写的代码本质上是下面的内容,并且重复使用它令人作呕,因为它只适用于 fetch 选项

const user = { name: 'foo', pass: 'bar' };
const options = { fetch: function (url, opts) {
    opts.headers.set('Authorization', 'Basic ' + window.btoa(user.name+':'+user.pass));
    return PouchDB.fetch(url, opts);
  }
};

this.remote = new PouchDB(couchDBurl, options); 

我相信我之所以选择这种方法,是因为在本回答的第一个 link 中讨论了我的身份验证工作流程的性质。

我同意@RamblinRose 的观点,您可能必须在定义 PouchDB object.

时手动包含 headers

我自己在使用需要包含在 header 中以实现同步的 JWT 时找到了解决方案。

看到这个答案。注意:RxDB 在底层使用 PouchDB,因此适用于这种情况。它帮助我同步,希望你也能!

https://whosebug.com/a/64503760/5012227

One potential solution I'm considering is overriding fetch to use native http client (i.e., an instance of HTTP from @ionic-native/http). It seems modifying http clients is a possibility (e.g., according to this conversation) but I'm not sure how to achieve that.

是的,这是一个可能的选项 - 特别是如果您想要使用仅适用于本机请求的 SSL 固定。而且您无需担心 CORS(ionic serve 除外)。

你可以做到这一点,例如通过获取现有的 fetch - polyfill 并修改它 s.t。它使用 http 插件而不是 xhr。由于在与 CouchDB 交互时只处理 JSON,因此可以丢弃大部分 polyfill。