firebase / flutterfire

πŸ”₯ A collection of Firebase plugins for Flutter apps.
https://firebase.google.com/docs/flutter/setup
BSD 3-Clause "New" or "Revised" License
8.63k stars 3.95k forks source link

πŸ› [firebase-messaging ] [web] - Error getToken when base href is not "/" #6177

Open Donk3ys opened 3 years ago

Donk3ys commented 3 years ago

Bug report

If i change the base href from <base href="/"> in web/index.html to <base href="/admin/"> I get an error when running FirebaseMessaging.instance.getToken();

Therefore I cant have push notifications for regular website & admin website if they on the same server.

Steps to reproduce

Change the base href from <base href="/"> in web/index.html to <base href="/admin/">

When accepting the notification permissions and my code runs:

void main() async {
    runApp(MyApp());    
    FirebaseMessaging.instance.getToken().then((token) => print(token));
}

I get an error: Error: [firebase_messaging/failed-service-worker-registration] Messaging: We are unable to register the default service worker. Failed to register a ServiceWorker for scope ('http://localhost:58007/firebase-cloud-messaging-push-scope') with script ('http://localhost:58007/firebase-messaging-sw.js'): A bad HTTP response code (404) was received when fetching the script.

Expected behavior

Print a token from FirebaseMessaging.instance.getToken();

Sample project

index.html

<!DOCTYPE html>
<html>
  <head>

  <!--  <base href="/"> WORKS -->
    <base href="/admin/"> <!-- DOESNT WORK -->

    <meta charset="UTF-8">
    <meta content="IE=Edge" http-equiv="X-UA-Compatible">
    <meta name="description" content="fcm">

    <!-- iOS meta tags & icons -->
    <meta name="apple-mobile-web-app-capable" content="yes">
    <meta name="apple-mobile-web-app-status-bar-style" content="black">
    <meta name="apple-mobile-web-app-title" content="fcm">

    <!-- Favicon -->
    <link rel="icon" type="icon/jpg" href="assets/logo-600.jpg"/>

    <title>fcm</title>
    <link rel="manifest" href="manifest.json">
  </head>
  <body>
    <script>
      if ('serviceWorker' in navigator) {
        window.addEventListener('flutter-first-frame', function () {
          //navigator.serviceWorker.register('flutter_service_worker.js');
          navigator.serviceWorker.register('firebase-messaging-sw.js');
        });
      }
    </script>

    <script src="https://www.gstatic.com/firebasejs/8.6.1/firebase-app.js"></script>
    <script src="https://www.gstatic.com/firebasejs/8.6.1/firebase-messaging.js"></script>
    <script>
      var firebaseConfig = {
        apiKey: "xxx",
        authDomain: "xxx.firebaseapp.com",
        projectId: "xxx",
        storageBucket: "xxx.appspot.com",
        messagingSenderId: "xxx",
        appId: "xxx"
      };

      firebase.initializeApp(firebaseConfig);
    </script>

    <script src="main.dart.js" type="application/javascript"></script>
  </body>
</html>

firebase-messaging-sw.js

importScripts("https://www.gstatic.com/firebasejs/8.6.1/firebase-app.js");
importScripts("https://www.gstatic.com/firebasejs/8.6.1/firebase-messaging.js");

firebase.initializeApp({
  apiKey: "xxx",
        authDomain: "xxx.firebaseapp.com",
        projectId: "xxx",
        storageBucket: "xxx.appspot.com",
        messagingSenderId: "xxx",
        appId: "xxx"
});

const messaging = firebase.messaging();

// Optional:
messaging.onBackgroundMessage((m) => {
  console.log("onBackgroundMessage", m);
});

main.dart

import 'package:firebase_messaging/firebase_messaging.dart';
import 'package:flutter/material.dart';

void main() async {
  runApp(MyApp());
  FirebaseMessaging.instance.getToken().then((token) => print(token));
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: HomePage(),
    );
  }
}

class HomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Container(),
    );
  }
}

Flutter doctor

Click To Expand ``` ❯ flutter doctor -v [βœ“] Flutter (Channel stable, 2.0.6, on macOS 11.3 20E232 darwin-x64, locale en-US) β€’ Flutter version 2.0.6 at /Users/donk3y/development/flutter β€’ Framework revision 1d9032c7e1 (3 weeks ago), 2021-04-29 17:37:58 -0700 β€’ Engine revision 05e680e202 β€’ Dart version 2.12.3 [βœ“] Android toolchain - develop for Android devices (Android SDK version 30.0.3) β€’ Android SDK at /Users/donk3y/Library/Android/sdk β€’ Platform android-30, build-tools 30.0.3 β€’ ANDROID_HOME = /Users/donk3y/Library/Android/sdk β€’ Java binary at: /Applications/Android Studio.app/Contents/jre/jdk/Contents/Home/bin/java β€’ Java version OpenJDK Runtime Environment (build 11.0.8+10-b944.6916264) β€’ All Android licenses accepted. [βœ“] Xcode - develop for iOS and macOS β€’ Xcode at /Applications/Xcode.app/Contents/Developer β€’ Xcode 12.4, Build version 12D4e β€’ CocoaPods version 1.10.1 [βœ“] Chrome - develop for the web β€’ Chrome at /Applications/Google Chrome.app/Contents/MacOS/Google Chrome [βœ“] Android Studio (version 4.2) β€’ Android Studio at /Applications/Android Studio.app/Contents β€’ Flutter plugin can be installed from: πŸ”¨ https://plugins.jetbrains.com/plugin/9212-flutter β€’ Dart plugin can be installed from: πŸ”¨ https://plugins.jetbrains.com/plugin/6351-dart β€’ Java version OpenJDK Runtime Environment (build 11.0.8+10-b944.6916264) [βœ“] Connected device (2 available) β€’ macOS (desktop) β€’ macos β€’ darwin-x64 β€’ macOS 11.3 20E232 darwin-x64 β€’ Chrome (web) β€’ chrome β€’ web-javascript β€’ Google Chrome 90.0.4430.212 β€’ No issues found! ```

Flutter dependencies

Click To Expand ``` ❯ flutter pub deps -- --style=compact Dart SDK 2.12.3 Flutter SDK 2.0.6 test_firebase_message 1.0.0+1 dependencies: - cupertino_icons 1.0.3 - firebase_core 1.1.1 [firebase_core_platform_interface firebase_core_web flutter meta] - firebase_messaging 9.1.4 [firebase_core firebase_core_platform_interface firebase_messaging_platform_interface firebase_messaging_web flutter meta] - flutter 0.0.0 [characters collection meta typed_data vector_math sky_engine] dev dependencies: - flutter_test 0.0.0 [flutter test_api path fake_async clock stack_trace vector_math async boolean_selector characters charcode collection matcher meta source_span stream_channel string_scanner term_glyph typed_data] transitive dependencies: - async 2.5.0 [collection] - boolean_selector 2.1.0 [source_span string_scanner] - characters 1.1.0 - charcode 1.2.0 - clock 1.1.0 - collection 1.15.0 - fake_async 1.2.0 [clock collection] - firebase_core_platform_interface 4.0.1 [collection flutter meta plugin_platform_interface] - firebase_core_web 1.0.3 [firebase_core_platform_interface flutter flutter_web_plugins js meta] - firebase_messaging_platform_interface 2.1.4 [firebase_core flutter meta plugin_platform_interface] - firebase_messaging_web 1.0.7 [firebase_core firebase_core_web firebase_messaging_platform_interface flutter flutter_web_plugins js meta] - flutter_web_plugins 0.0.0 [flutter js characters collection meta typed_data vector_math] - js 0.6.3 - matcher 0.12.10 [stack_trace] - meta 1.3.0 - path 1.8.0 - plugin_platform_interface 2.0.0 [meta] - sky_engine 0.0.99 - source_span 1.8.0 [charcode collection path term_glyph] - stack_trace 1.10.0 [path] - stream_channel 2.1.0 [async] - string_scanner 1.1.0 [charcode source_span] - term_glyph 1.2.0 - test_api 0.2.19 [async boolean_selector collection meta path source_span stack_trace stream_channel string_scanner term_glyph matcher] - typed_data 1.3.0 [collection] - vector_math 2.1.0 ```

darshankawar commented 3 years ago

@Donk3ys Thanks for the detailed report and code sample. If you open a new browser tab and run http://localhost:58007/firebase-messaging-sw.js, what does it show ? an actual file or any error ?

Usually, the 404 error A bad HTTP response code (404) was received when fetching the script. indicates that the file cannot be found at root of the origin.

Donk3ys commented 3 years ago

If I have <base href="/"> and go to http://localhost:58007/firebase-messaging-sw.js I get my file

If I have <base href="/admin/"> and go to http://localhost:58007/firebase-messaging-sw.js I get an error

If I have <base href="/admin/"> and go to http://localhost:58007/admin/firebase-messaging-sw.js I get my file

If I have <base href="/admin/"> and navigator.serviceWorker.register('/admin/firebase-messaging-sw.js'); I get same error message:

Error: [firebase_messaging/failed-service-worker-registration] Messaging: We are unable to register the default service 
worker. Failed to register a ServiceWorker for scope ('http://localhost:58007/firebase-cloud-messaging-push-scope') with 
script ('http://localhost:58007/firebase-messaging-sw.js'): A bad HTTP response code (404) was received when fetching the 
script.
Ehesp commented 3 years ago

The base tag resolves all relative imports, which your service worker is. Have you tried:

navigator.serviceWorker.register('/firebase-messaging-sw.js');

or

navigator.serviceWorker.register('/admin/firebase-messaging-sw.js');
Donk3ys commented 3 years ago

@Ehesp

Thanks for the reply.

Yeah I've tried both and still get the exact same error for both, when trying to getToken().

Error: [firebase_messaging/failed-service-worker-registration] Messaging: We are unable to register the default service 
worker. Failed to register a ServiceWorker for scope ('http://localhost:58007/firebase-cloud-messaging-push-scope') with 
script ('http://localhost:58007/firebase-messaging-sw.js'): A bad HTTP response code (404) was received when fetching the 
script.
Ehesp commented 3 years ago

Have you tried putting the full URL in for now? I believe that will ignore the base path then.

Donk3ys commented 3 years ago

Have you tried putting the full URL in for now? I believe that will ignore the base path then.

Still the same error message

darshankawar commented 3 years ago

Using latest firebase_messaging plugin version and using latest JavaScript SDK version, I was able to replicate it on current stable version (2.2.0):

With default base href, we get the token back properly, but changing the href as mentioned, gives below error in the console:

dhs@Dhss-MacBook-Pro firebase_messaging_example % flutter run -d chrome
Launching lib/main.dart on Chrome in debug mode...
Waiting for connection from debug service on Chrome...             15.3s
This app is linked to the debug service: ws://127.0.0.1:51725/3RN-YodlhE4=/ws
Debug service listening on ws://127.0.0.1:51725/3RN-YodlhE4=/ws

πŸ’ͺ Running with sound null safety πŸ’ͺ

πŸ”₯  To hot restart changes while running, press "r" or "R".
For a more detailed help message, press "h". To quit, press "q".
Error: [firebase_messaging/failed-service-worker-registration] Messaging: We are unable to register the default service worker. Failed to register a ServiceWorker for scope
('http://localhost:51703/firebase-cloud-messaging-push-scope') with script ('http://localhost:51703/firebase-messaging-sw.js'): A bad HTTP response code (404) was received when fetching
the script. .
    at Object.throw_ [as throw] (http://localhost:51703/admin/dart_sdk.js:5037:11)
    at http://localhost:51703/admin/packages/firebase_core/src/internals.dart.lib.js:81:63
    at _RootZone.runUnary (http://localhost:51703/admin/dart_sdk.js:37245:59)
    at _FutureListener.catchError.handleError (http://localhost:51703/admin/dart_sdk.js:32513:48)
    at handleError (http://localhost:51703/admin/dart_sdk.js:33044:51)
    at Function._propagateToListeners (http://localhost:51703/admin/dart_sdk.js:33070:17)
    at _Future.new.[_completeError] (http://localhost:51703/admin/dart_sdk.js:32920:23)
    at async._AsyncCallbackEntry.new.callback (http://localhost:51703/admin/dart_sdk.js:32956:31)
    at Object._microtaskLoop (http://localhost:51703/admin/dart_sdk.js:37497:13)
    at _startMicrotaskLoop (http://localhost:51703/admin/dart_sdk.js:37503:13)
    at http://localhost:51703/admin/dart_sdk.js:33274:9
flutter doctor -v ``` [βœ“] Flutter (Channel stable, 2.2.0, on Mac OS X 10.15.4 19E2269 darwin-x64, locale en-GB) β€’ Flutter version 2.2.0 at /Users/dhs/documents/fluttersdk/flutter β€’ Framework revision b22742018b (5 days ago), 2021-05-14 19:12:57 -0700 β€’ Engine revision a9d88a4d18 β€’ Dart version 2.13.0 [!] Xcode - develop for iOS and macOS β€’ Xcode at /Applications/Xcode.app/Contents/Developer β€’ Xcode 12.3, Build version 12C33 ! CocoaPods 1.9.3 out of date (1.10.0 is recommended). CocoaPods is used to retrieve the iOS and macOS platform side's plugin code that responds to your plugin usage on the Dart side. Without CocoaPods, plugins will not work on iOS or macOS. For more info, see https://flutter.dev/platform-plugins To upgrade see https://guides.cocoapods.org/using/getting-started.html#installation for instructions. [βœ“] Chrome - develop for the web β€’ Chrome at /Applications/Google Chrome.app/Contents/MacOS/Google Chrome [βœ“] VS Code (version 1.55.2) β€’ VS Code at /Applications/Visual Studio Code.app/Contents β€’ Flutter extension version 3.21.0 [βœ“] Connected device (3 available) β€’ Darshan's iphone (mobile) β€’ 21150b119064aecc249dfcfe05e259197461ce23 β€’ ios β€’ iOS 14.4.1 β€’ macOS (desktop) β€’ macos β€’ darwin-x64 β€’ Mac OS X 10.15.4 19E2269 darwin-x64 β€’ Chrome (web) β€’ chrome β€’ web-javascript β€’ Google Chrome 90.0.4430.212 ! Doctor found issues in 1 category. ```
thiencapa commented 3 years ago

I face the same problem. When trying to call getToken() in a dart script of the application, it tries to fetch the "firebase-messaging-sw.js" from our server with the wrong url and the same error occurs.

In the "index.html" we have set:

<base href="/server/demo/">

When starting our application, it initially is able to fetch the "firebase-messaging-sw.js" succesfully and it is able to register the service worker with the correct url e.g. http://localhost:8080/server/demo/firebase-messaging-sw.js. However, when we call getToken() in the application to save the token in a database, it tries to fetch the "firebase-messaging-sw.js" another time with an incorrect request url e.g. http://localhost:8080/firebase-messaging-sw.js. This throws an error since it is not accessible this way.

praveeno commented 3 years ago

maybe adding scope can help navigator.serviceWorker.register('/sw.js', {scope: '/admin/'})

Fabrice-TEICHTEIL-KOENIGSBUCH commented 3 years ago

Same issue than everyone when base href is not "/", adding scope as suggested above is not working.

lmordell commented 2 years ago

Any update on this issue? Running into the same problem. Confirmed @praveeno 's solution does not work.

luisfelipesd commented 2 years ago

have the same issue here any workaround?

Tapaswi846580 commented 2 years ago

Looks like in the firebase library someone has hardcoded the static path which is "root path" ( https:/// ). Firebase has to change this hardcoded path or has to define a function in the library to change this hardcoded path.

Tapaswi846580 commented 2 years ago

Another workaround which anyone can think of is to put firebase-messaging-sw.js file in the root folder of the server which one can access the file just by writing the {hostname}/firebase-messaging-sw.js

palmsnipe commented 2 years ago

Any update on the issue? The only way I could make it work was moving firebase-messaging-sw.js to the root folder.

Kuryia commented 2 years ago

Any updates on this issue? I have the same problem, and I have googled for decades. I am desperate!

Novskilol commented 2 years ago

Same issue here, I am using github pages for hosting, so the only file that will go next to the root is index.html and we cannot change that, the other files are moved to root/project_name/file.js, including firebase-messaging-sw.js, and again, you can't choose to put them at the root. It seems the call to "await FirebaseMessaging.instance.getToken()" is refreshing the serviceWorker() with root path and doesn't care at all about "base href" like Tapas explained, so I am completely stuck here :(

mufarrah commented 2 years ago

having the same issue

mrleesin commented 2 years ago

same problem! help!

emmadedayo commented 2 years ago

same problem help!!!

krasznaidavid commented 2 years ago

+1

leoshusar commented 2 years ago

I found open issue in Firebase SDK.

There is one workaround and that's passing the registration into getToken, however I'm not sure if it would be possible to implement it in this library.

EDIT: I made a workaround, if anyone wants. Put this in index.html before Flutter init:

const baseRegister = navigator.serviceWorker.register;
navigator.serviceWorker.register = function (url, options) {
  if (url.startsWith('/') && url.indexOf('/', 1) === -1) {
    url = url.substring(1);
  }

  if (options && options.scope && options.scope.startsWith('/') && options.scope.indexOf('/', 1) === -1) {
    options.scope = options.scope.substring(1);
  }

  return baseRegister.call(navigator.serviceWorker, url, options);
};

it could probably be simpler, but I'm not a JS dev.

darshankawar commented 2 years ago

Please upvote original issue description with thumbs up emoji instead of commenting to ask for updates. Number of upvotes helps the team to prioritize issues.

RomanKuzo commented 1 year ago

Any update on the issue? The only way I could make it work was moving firebase-messaging-sw.js to the root folder.

Hey. What do you mean by root folder? I have this firebase-messaging-sw.js file in the web folder which is generated by flutter. But I still have the same problem. I know it was a long time ago, but maybe you remember :)

RomanKuzo commented 1 year ago

@darshankawar any updates? It's really sad that this problem has been around for so long. If there is no new version with a fix, maybe you have some custom solution?

Astramo commented 10 months ago

having the same issue

russellwheatley commented 9 months ago

This issue is upstream from FlutterFire, you can follow the open issue on the Firebase web JS SDK here: https://github.com/firebase/firebase-js-sdk/issues/2582

There are a couple of workarounds suggested on this thread, but I'd suggest you thumb up the issue in that repo if you wish to see this issue expedited.