laravel-notification-channels / webpush

Webpush notifications channel for Laravel.
http://laravel-notification-channels.com
MIT License
670 stars 118 forks source link

Allow to set WebPush automatic padding in config #176

Open goaround opened 2 years ago

goaround commented 2 years ago

To support Firefox Android, automatic padding applied by WebPush has to be disabled: https://github.com/web-push-libs/web-push-php#how-can-i-disable-or-customize-automatic-padding

This PR just applies the default 3052 bytes but you can set automatic_padding to false to support Firefox Android

Fix for https://github.com/laravel-notification-channels/webpush/issues/103#issuecomment-1205132556

imrodrigoalves commented 1 year ago

Using the approach suggested sets a lower padding value for every notification sent using the current webpush instance. To mitigate this only to reduce the padding on firefox v1 I restricted the lowering of the padding to the subscriptions that have a Firefox v1 endpoint.

Here's what I did:

  1. Extend the default WebPush class
<?php

namespace App\Providers\Models;

use Illuminate\Support\Str;
use Minishlink\WebPush\Encryption;
use Minishlink\WebPush\SubscriptionInterface;
use Minishlink\WebPush\WebPush as MWWebpush;

class WebPush extends MWWebpush
{
    // Solves:
    // https://github.com/laravel-notification-channels/webpush/issues/103
    // https://github.com/web-push-libs/web-push-php/issues/108#issuecomment-545977603

    // Had to lower the Mobile Firefox padding for it to work. It probably can go higher but no longer works under 2847 as  suggested.
    const MAX_MOBILE_FIREFOX_PADDING = 2048;

    public function queueNotification(SubscriptionInterface $subscription, ?string $payload = null, array $options = [], array $auth = []): void
    {
        $this->setAutomaticPadding(Encryption::MAX_COMPATIBILITY_PAYLOAD_LENGTH);

        if(Str::startsWith($subscription->getEndpoint(), 'https://updates.push.services.mozilla.com/wpush/v1')){
            $this->setAutomaticPadding(self::MAX_MOBILE_FIREFOX_PADDING);
        }

        parent::queueNotification($subscription, $payload, $options, $auth);
    }
}
  1. Overwrite the WebPush class loaded by the WebPushServiceProvider
<?php

namespace App\Providers;

use App\Providers\Models\WebPush;
use Minishlink\WebPush\WebPush as MWWebPush;
use NotificationChannels\WebPush\WebPushChannel;
use NotificationChannels\WebPush\WebPushServiceProvider as NCWebPushServiceProvider;

class WebPushServiceProvider extends NCWebPushServiceProvider
{
    /**
     * Register services.
     *
     * @return void
     */
    public function register()
    {

    }

    /**
     * Bootstrap services.
     *
     * @return void
     */
    public function boot()
    {
        parent::boot();

        $this->app->when(WebPushChannel::class)
        ->needs(MWWebPush::class)
        ->give(function () {
            return (new WebPush(
                $this->webPushAuth(), [], 30, config('webpush.client_options', [])
            ))->setReuseVAPIDHeaders(true);
        });
    }
}
  1. Enable the service provide in config/app.php

  2. Disable automatic loading of the service provider in composer.json

"extra": {
        "laravel": {
            "dont-discover": [
                "laravel-notification-channels/webpush"
            ]
        }
    },

I'll assume some maintenance responsibility over time yet I am completely able to bypass the firefox problem and retain max padding compatibility.