How to execute Google Cloud Functions from Firebase Hosting? - firebase-cloud-messaging

I'm trying to create an Android project which can send notifications from one android device to another. For that purpose, I created a node.js file, it's working fine on the local server. But when I hosted it on Google Cloud Platform, it shows Page Not Found. It is not able to call Google Function from hosting. It is looking for or executing index.html but it should execute index.js, which is in functions directory which was created while initializing the project with Firebase.
I took the reference from this video: https://youtu.be/pnysHgQvOiM?list=PLk7v1Z2rk4hjM2NPKqtWQ_ndCuoqUj5Hh
index.js file
const functions = require('firebase-functions');
var {google} = require('googleapis')
var MESSAGING_SCOPE ="https://www.googleapis.com/auth/firebase.messaging"
var SCOPES = [MESSAGING_SCOPE]
var express = require('express')
var app = express();
var bodyParser = require('body-parser');
var router = express.Router();
var request = require('request');
app.use(bodyParser.urlencoded({extended:true}));
app.use(bodyParser.json());
router.post('/send',function(req,res){
getAccessToken().then(function(access_token){
var title = req.body.title;
var body = req.body.body;
var token = req.body.token;
request.post({
headers:{
Authorization: 'Bearer '+ access_token
}, url:
"https://fcm.googleapis.com/v1/projects/my_project_name/messages:send",
body: JSON.stringify(
{
"message":{
"token" : token,
"notification" : {
"body" : body,
"title" : title
}
}
}
)
},function(error,reponse,body){
res.end(body);
console.log(body);
});
});
});
app.use('/api',router);
function getAccessToken()
{
return new Promise(function(resolve,reject){
var key= require("./service-account.json");
var jwtClient = new google.auth.JWT(
key.client_email,
null,
key.private_key,
SCOPES,
null
);
jwtClient.authorize(function(error,tokens){
if(error)
{
reject(error)
}
resolve(tokens.access_token)
// console.log(tokens.access_token)
});
jwtClient.authorize(function(error,tokens){
if(error)
{
reject(error)
}
resolve(tokens.access_token)
console.log(tokens.access_token)
});
});
}
exports.api = functions.https.onRequest(app);
firebase.json
{
"hosting":
{
"public": "public",
"rewrites": [
{
"source": "/api/send",
"functions": "api"
}
],
"ignore": [
"firebase.json",
"**/.*",
"**/node_modules/**"
]
}
}
This code is working fine with using http://localhost:8085/api/send but it is not working as https://my_project_name.firebaseapp.com/api/send

Related

Amplify Cognito Admin Query listUsersInGroup not working

I am working with AWS Amplify, specifically with Auth; I am trying to get the listUsersInGroup from Cognito pool using the next function in React:
import { Auth, API } from 'aws-amplify';
const listUsersInGroup = async (group) => {
let apiName = 'AdminQueries';
let path = '/listUsersInGroup';
let myInit = {
body: {
"groupname": group
},
headers: {
'Content-Type' : 'application/json',
Authorization: `${(await Auth.currentSession()).getAccessToken().getJwtToken()}`
}
};
const supervisorGet = await API.get(apiName, path, myInit);
}
But the API response is having code 403 and the response brings the message: {"message":"groupname is required"}
I made tests with other HTTP methods like listUsers, listGroups, listGroupsForUser and works correctly.
Can anyone help on this issue?
I found the example below in the Amplify documenation for admin actions.
It looks like the myInit object you are making is using body, but the example has queryStringParameters. That's why it's not finding the groupname key.
let nextToken;
async function listEditors(limit){
let apiName = 'AdminQueries';
let path = '/listUsersInGroup';
let myInit = {
queryStringParameters: {
"groupname": "Editors",
"limit": limit,
"token": nextToken
},
headers: {
'Content-Type' : 'application/json',
Authorization: `${(await Auth.currentSession()).getAccessToken().getJwtToken()}`
}
}
const { NextToken, ...rest } = await API.get(apiName, path, myInit);
nextToken = NextToken;
return rest;
}

Graphql studio getting null data

I am new to Graphql, express, and Apollo.
Expected result: I am trying to consume data from JSON file data and get results in the studio.
Actual Result: Getting "null" data instead.
I am attaching my code snippets and problems below
Refer the following:
Let me show you the code:
directory structure:
MOCK_DATA.json
I am just keeping data small for testing the concept.
[{
"name": "Leanne Graham",
"username": "Bret"
},
{
"name": "Rohit Sharma",
"username": "rohituid"
}]
index.js
As per my understanding, The significance of the file is wiring up the express middle wire with the Apollo server. Tried to make this file in a way that it will be hardly touched.
Other than that, I have the async function was required to fix Apollo Server await server.start bug .
I am creating apollo server
const { ApolloServer } = require("apollo-server-express");
const { typeDefs } = require("./Schema/TypeDefs");
const { resolver } = require("./Schema/Resolver");
const express = require("express");
const app = express();
const PORT = 3001;
async function createApolloServer() {
//passing into apollo constructor
const server = new ApolloServer({
typeDefs,
resolver
});
//instantiatiating the apollo server
await server.start();
//this will install the apollo server on express app
server.applyMiddleware({ app });
}
createApolloServer();
//console.log(resolver);
app.listen(PORT, () => {
console.log('Server is running on : http://localhost:3001/graphql');
Schema:
TypeDefs.js
const { ApolloServer, gql } = require("apollo-server");
//below is known as tagged template literal
const typeDefs = gql`
type User {
name: String
username: String
}
#Queries -like get in REST World
type Query {
getAllUsers: [User]
}
`;
//console.log(typeDefs);
module.exports = { typeDefs };
Resolver.js
const userData = require("../MOCK_DATA.json");
//const userData = require("../FakeData.js");
// this is resolver map -> javascript object
//using arrow function
/*
below arrow function equivalent to using function like:
function getAllUsers() {
return userData;
}
*/
const resolver = {
Query: {
getAllUsers: ()=> {
return userData;
}
},
};
//console.log(userData);
module.exports = { resolver };

How to resolve Cloud Function Error:401 Unauthorized

I have coded an Apps Script that creates an event in the Calendar.
Apps Script is stand alone, and event in also created in my personal Gmail account.
This Script is linked to GCP project linked to same account as Script.
Oauth consent screen is created in the GCP account and also credentials for Oauth2.0 client ID.
Now I created a cloud function to call this appsScript but it is giving an Error:401
following is code for the cloud function
let message = req.query.message || req.body.message || 'Hello World!';
const axios = require('axios');
const {google} = require('googleapis');
//Authorization
const { GoogleAuth } = require('google-auth-library');
const auth1 = new GoogleAuth({
keyFile: 'credentials.json',
scopes: ['https://www.googleapis.com/auth/drive','https://www.googleapis.com/auth/drive.metadata'
, 'https://www.googleapis.com/auth/calendar','https://www.googleapis.com/auth/calendar.events' ],
});
const drive = google.drive({version: 'v3', auth: auth1 });
const calendar = google.calendar({version : "v3"});
//calling formSchedule function with all the variables
async function formSchedule(eventDate,claimId, garageId, claimDet,startTime,cEmailG){
//Schedule Meeting Json Data
var evDurtion=30;
var startDateTime = startTime;
var endDateTime=new Date(startDateTime.getTime()+(evDurtion*60000));
// console.log(endDateTime)
var subject="Claim ID : "+claimId+' - Call';
var attendees=[{
"email": garageId,
},
];
var eventData={
"summary":subject,
'start': {
'dateTime': startDateTime,
'timeZone': 'Asia/Kolkata'
},
'end': {
'dateTime': endDateTime,
'timeZone': 'Asia/Kolkata'
},
"attendees":attendees,
"conferenceData": {
"createRequest": {
"conferenceSolutionKey": {
"type": "hangoutsMeet"
},
"status": {
"statusCode": "success"
},
"requestId": "test1235"
}
},
"description":claimDet,
"defaultReminders": [
{
"method": "popup",
"minutes": "5"
}
]
}
console.log("after all variables initialization")
// Schedule Meeting
axios({
method: "post",
url : //API Executable deployed Apps Script link,
data: {
'eventdata' : eventData,
'serviceId' : cEmailG
},
headers: {
'Content-Type': 'text/plain;charset=utf-8',
},
}).then(function (response) {
try{
console.log('Event Added Successfully.')
}
catch (error){
console.log('------error-----',error)
}
})
}
res.status(200).send(message);
};```

swagger-ui-express persistAuthorization not working

I have a very simple sample code using swagger-ui-express:
const express = require("express");
app = express();
app.listen(3000);
const swaggerUi = require('swagger-ui-express');
var options = {
swaggerOptions: {
persistAuthorization: true
}
};
app.use('/doc',
swaggerUi.serve, swaggerUi.setup(
{
"swagger": "2.0",
"info": {
"title": "Simple API overview",
"version": "v2"
},
securityDefinitions: {
BearerAuth: {
type: 'apiKey',
in: 'header',
name: 'Authorization'
},
},
}
,
options
)
);
I am not able to mak persistAuthorization work, after entering anything in the authorization field, when refreshing the web page the authorization is deleted.
The code follows the documentation in https://www.npmjs.com/package/swagger-ui-express
And the persistAuthorization option is documented in https://swagger.io/docs/open-source-tools/swagger-ui/usage/configuration/

How to send a request from Nuxt.js client over Nuxt.js server and receive the response back to the client

I'm developing a Vue.js application which has only frontend (no server) and send a lot of requests to different APIs. The originally quite simple app became more complex. And there are problems with some APIs, because browsers do not accept the responses due to CORS. That is why I'm trying to test, if I can migrate the app to Nuxt.js.
My approach is as follows (inspired by this comment), but I expect, that there is probably a better way to send the requests from the client over the server.
pages/test-page.vue
methods: {
async sendRequest(testData) {
const response = await axios.post('api', testData)
// Here can I use the response on the page.
}
}
nuxt.config.js
serverMiddleware: [
{ path: '/api', handler: '~/server-middleware/postRequestHandler.js' }
],
server-middleware/postRequestHandler.js
import axios from 'axios'
const configs = require('../store/config.js')
module.exports = function(req, res, next) {
let body = ''
req.on('data', (data) => {
body += data
})
req.on('end', async () => {
if (req.hasOwnProperty('originalUrl') && req.originalUrl === '/api') {
const parsedBody = JSON.parse(body)
// Send the request from the server.
const response = await axios.post(
configs.state().testUrl,
body
)
req.body = response
}
next()
})
}
middleware/test.js (see: API: The Context)
export default function(context) {
// Universal keys
const { store } = context
// Server-side
if (process.server) {
const { req } = context
store.body = req.body
}
}
pages/api.vue
<template>
{{ body }}
</template>
<script>
export default {
middleware: 'test',
computed: {
body() {
return this.$store.body
}
}
}
</script>
When the user makes an action on the page "test", which will initiate the method "sendRequest()", then the request "axios.post('api', testData)" will result in a response, which contains the HTML code of the page "api". I can then extract the JSON "body" from the HTML.
I find the final step as suboptimal, but I have no idea, how can I send just the JSON and not the whole page. But I suppose, that there must be a much better way to get the data to the client.
There are two possible solutions:
Proxy (see: https://nuxtjs.org/faq/http-proxy)
API (see: https://medium.com/#johnryancottam/running-nuxt-in-parallel-with-express-ffbd1feef83c)
Ad 1. Proxy
The configuration of the proxy can look like this:
nuxt.config.js
module.exports = {
...
modules: [
'#nuxtjs/axios',
'#nuxtjs/proxy'
],
proxy: {
'/proxy/packagist-search/': {
target: 'https://packagist.org',
pathRewrite: {
'^/proxy/packagist-search/': '/search.json?q='
},
changeOrigin: true
}
},
...
}
The request over proxy can look like this:
axios
.get('/proxy/packagist-search/' + this.search.phpLibrary.searchPhrase)
.then((response) => {
console.log(
'Could get the values packagist.org',
response.data
)
}
})
.catch((e) => {
console.log(
'Could not get the values from packagist.org',
e
)
})
Ad 2. API
Select Express as the project’s server-side framework, when creating the new Nuxt.js app.
server/index.js
...
app.post('/api/confluence', confluence.send)
app.use(nuxt.render)
...
server/confluence.js (simplified)
const axios = require('axios')
const config = require('../nuxt.config.js')
exports.send = function(req, res) {
let body = ''
let page = {}
req.on('data', (data) => {
body += data
})
req.on('end', async () => {
const parsedBody = JSON.parse(body)
try {
page = await axios.get(
config.api.confluence.url.api + ...,
config.api.confluence.auth
)
} catch (e) {
console.log('ERROR: ', e)
}
}
res.json({
page
})
}
The request over API can look like this:
this.$axios
.post('api/confluence', postData)
.then((response) => {
console.log('Wiki response: ', response.data)
})
.catch((e) => {
console.log('Could not update the wiki page. ', e)
})
Now with nuxtjs3 :
nuxtjs3 rc release
you have fetch or useFetch no need to import axios or other libs, what is great, automatic parsing of body, automatic detection of head
fetching data
you have middleware and server api on same application, you can add headers on queries, hide for example token etc
server layer
a quick example here in vue file i call server api :
const { status } = await $fetch.raw( '/api/newsletter', { method: "POST", body: this.form.email } )
.then( (response) => ({
status: response.status,
}) )
.catch( (error) => ({
status: error?.response?.status || 500,
}) );
it will call a method on my server, to init the server on root directory i created a folder name server then api, and a file name newsletter.ts (i use typescript)
then in this file :
export default defineEventHandler(async (event) => {
const {REST_API, MAILINGLIST_UNID, MAILINGLIST_TOKEN} = useRuntimeConfig();
const subscriber = await readBody(event);
console.log("url used for rest call" + REST_API);
console.log("token" + MAILINGLIST_TOKEN);
console.log("mailing list unid" + MAILINGLIST_UNID);
let recipientWebDTO = {
email: subscriber,
subscriptions: [{
"mailingListUnid": MAILINGLIST_UNID
}]
};
const {status} = await $fetch.raw(REST_API, {
method: "POST",
body: recipientWebDTO,
headers: {
Authorization: MAILINGLIST_TOKEN,
},
}).then((response) => ({
status: response.status,
}))
.catch((error) => ({
status: error?.response?.status || 500,
}));
event.res.statusCode = status;
return "";
})
What are the benefits ?
REST_API,MAILING_LIST_UNID, MAILING_LIST_TOKEN are not exposed on
client and even file newsletter.ts is not available on debug browser.
You can add log only on server side You event not expose api url to avoid some attacks
You don't have to create a new backend just to hide some criticals token or datas
then it is up to you to choose middleware route or server api. You don't have to import new libs, h3 is embedded via nitro with nuxtjs3 and fetch with vuejs3
for proxy you have also sendProxy offered by h3 : sendProxy H3
When you build in dev server and client build in same time(and nothing to implement or configure in config file), and with build to o, just don deploy your project in static way (but i think you can deploy front in static and server in node i don't know)