web-push-libs / web-push

Web Push library for Node.js
Other
3.27k stars 306 forks source link

Cloudflare Worker support? #718

Open Code6226 opened 2 years ago

Code6226 commented 2 years ago

Setup

Currently web-push does not work on Cloudflare Workers. These do not use Node, so certain libraries are not available. They do offer a new Node compatibility mode, but it does not resolve all issues.

Operating System: Cloudflare Worker Node Version: none web-push Version: 3.5.0

Problem

I am trying to send a notification on a Cloudflare Worker using the usual two lines of code mentioned below. These do work when running under Node. But not on Cloudflare.

Expected

Would be nice if web-push would support sending notifications when running on a Cloudflare Worker.

Features Used

Example / Reproduce Case

Set up a Cloudflare Worker by using Wrangler2. Then use the usual two lines of code above to try to send an notification.

It first ran into Buffers not being supported on Cloudflare. I was able to bypass this issue by enabling Cloudflare's Node compatibility mode for my Worker.

Next, https.request is not supported on Cloudflare. It instead requires use of fetch. I was able to resolve this issue by hand by replacing this code: https://github.com/web-push-libs/web-push/blob/0c5c44c84c521ce23b0d75ab6bd5dc1fd7e7d6c5/src/web-push-lib.js#L338

with this:

      try {
        const response = await fetch(requestDetails.endpoint, {
          method: httpsOptions.method.toLowerCase(),
          body: requestDetails.body,
          headers: httpsOptions.headers
        });
        const responseText = await response.text();
        if (response.status < 200 || response.status > 299) {
          reject(new WebPushError(
            'Received unexpected response code',
            response.status,
            response.headers,
            responseText,
            requestDetails.endpoint
          ));
        } else {
          resolve({
            statusCode: response.status,
            body: responseText,
            headers: response.headers
          });
        }
      } catch (e) {
        reject(e);
      }

Unfortunately, that's when I ran into an issue I don't know how to resolve:

TypeError: crypto2.createECDH is not a function
web-push/src/encryption-helper.js:41

Other

While Cloudflare does not have node's crypto library, it does have this: https://developers.cloudflare.com/workers/runtime-apis/web-crypto

I'm just not sure how to use this to accomplish what web-push is currently doing here: https://github.com/web-push-libs/web-push/blob/5388395e110800547e011b64ae03d44ea12774a8/src/encryption-helper.js#L41

marcus-sa commented 2 years ago

ECDH is not supported by https://developers.cloudflare.com/workers/runtime-apis/web-crypto so it would have to be manually implemented. https://community.cloudflare.com/t/webcrypto-ecdh-unrecognized-or-unimplemented-key-generation-algorithm-requested/242488

jimmywarting commented 2 years ago

This pkg: https://github.com/alastaircoote/webpush-webcrypto is NodeJS dependency free of any node core modules and uses web crypto instead 👍

Code6226 commented 2 years ago

Edit: Tried again today (12-23-2023) and now webpush-webcrypto does work on Cloudflare Workers 🎉

Original:

Unfortunately, https://github.com/alastaircoote/webpush-webcrypto didn't quite work. I got it working locally with wrangler2 in local mode (which tries to emulate the real environment). However, when I actually tried it on Cloudflare, it doesn't get past generatePushHTTPRequest, so I assume it's crypto related.

I did notice this repo, which appears to have successfully implemented ~webpush on Cloudflare: https://github.com/K0IN/Notify