mutlucan96
mutlucan96

Reputation: 427

Firebase Functions on Firebase Hosting: 404

I'm trying to call functions from app but it doesn't work and I'm getting the following error from the console:

index.esm.js:402 OPTIONS https://us-central1-undefined.cloudfunctions.net/addMessage 404 () Failed to load https://us-central1-undefined.cloudfunctions.net/addMessage: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'https://MYWEBADDRESS' is therefore not allowed access. The response had HTTP status code 404. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.

firebase.json:

{
  "database": {
    "rules": "database.rules.json"
  },
  "hosting": {
    "public": "public",
    "rewrites": [
      {
        "source": "**",
        "function": "addMessage"
      }
    ]
  },
  "functions": {
    "predeploy": [
      "npm --prefix $RESOURCE_DIR run lint"
    ],
    "source": "functions"
  }
}

index.js

const functions = require('firebase-functions');

const admin = require('firebase-admin');
admin.initializeApp();


exports.addMessage = functions.https.onCall((data, context) => {

    // Message text passed from the client.
    const text = data.text;

        // Checking attribute.
    if (!(typeof text === 'string') || text.length === 0) {
      // Throwing an HttpsError so that the client gets the error details.
      throw new functions.https.HttpsError('invalid-argument', 'The function must be called with ' +
          'one arguments "text" containing the message text to add.');
    }
    // Checking that the user is authenticated.
    if (!context.auth) {
      // Throwing an HttpsError so that the client gets the error details.
      throw new functions.https.HttpsError('failed-precondition', 'The function must be called ' +
          'while authenticated.');
    }

    // Saving the new message to the Realtime Database.
    return admin.database().ref('/messages').push({
      text: text
    }).then(() => {
      console.log('New Message written');
      // Returning the sanitized message to the client.
      return { text: sanitizedMessage };
    }).catch((error) => {
    // Re-throwing the error as an HttpsError so that the client gets the error details.
    throw new functions.https.HttpsError('unknown', error.message, error);
  });
});

my script in index.html

var addMessage = firebase.functions().httpsCallable('addMessage');
addMessage({text: "messageText"}).then(function(result) {
     var message = result.data.text;
     console.log(message);
});

How I initialize Firebase:

  <script src="https://www.gstatic.com/firebasejs/5.0.4/firebase-app.js"></script>
  <script src="https://www.gstatic.com/firebasejs/5.0.4/firebase-auth.js"></script>
  <script src="https://www.gstatic.com/firebasejs/5.0.4/firebase-database.js"></script>
  <script src="https://www.gstatic.com/firebasejs/5.0.4/firebase-functions.js"></script>
    <script>
      // Initialize Firebase
      var config = {
        apiKey: "**",
        authDomain: "***",
        databaseURL: "***",
        storageBucket: "***",
      };
      firebase.initializeApp(config);
      var functions = firebase.functions();
    </script>

Upvotes: 8

Views: 9809

Answers (2)

georg.dev
georg.dev

Reputation: 1263

For anyone else stumbling upon this question who runs into the same error even though the projectId is already set: if you happen to use Express.js for your functions, check out this Github issue and this StackOverflow comment.

To summarize them: make sure that you include the full URI of your function when setting it up with express. For example, if your function runs under https://us-central1.your-project-id.cloudfunctions.net/api/addMessage, make sure you include the api/ part as well. So, in this example that would be:

app.post('/api/addMessage', addMessage);

Upvotes: 0

casieber
casieber

Reputation: 7542

I was having the same exact problem, found your question without an answer, but managed to figure it out in the end.

As @Doug Stevenson mentioned above in the comments, the problem is that the Cloud Functions URL you are seeing has undefined instead of your project ID as the last piece of the url subdomain.

The reason it is undefined is because your project ID is not part of your initial Firebase config object. Like me, you likely copied and pasted the starter snippet from Firebase for the JS SDK, but you did it before they started including the Project ID as part of it. For some reason, even though the project ID is now needed to construct the cloud functions URL, the SDK doesn't error / warn if you don't include it.

All you need to do is add the following field to your config object:

projectId: <YOUR_PROJECT_ID_HERE>

Then you should see the requests no longer 404.

Upvotes: 7

Related Questions