Socket hang up error in Cloud Functions for Firebase - firebase

I have a Cloud Function that is triggered by a Pub / Sub event. It uses request-promise to make multiple GET requests from an API I use for my data.
It works when running locally in the Cloud Functions Emulator, however in production I keep getting this error:
{ RequestError: Error: socket hang up
at new RequestError (/user_code/node_modules/request-promise/node_modules/request-promise-core/lib/errors.js:14:15)
at Request.plumbing.callback (/user_code/node_modules/request-promise/node_modules/request-promise-core/lib/plumbing.js:87:29)
at Request.RP$callback [as _callback] (/user_code/node_modules/request-promise/node_modules/request-promise-core/lib/plumbing.js:46:31)
at self.callback (/user_code/node_modules/request/request.js:185:22)
at emitOne (events.js:96:13)
at Request.emit (events.js:188:7)
at Request.onRequestError (/user_code/node_modules/request/request.js:877:8)
at emitOne (events.js:96:13)
at ClientRequest.emit (events.js:188:7)
at TLSSocket.socketOnEnd (_http_client.js:346:9)
at emitNone (events.js:91:20)
at TLSSocket.emit (events.js:185:7)
at endReadableNT (_stream_readable.js:974:12)
at _combinedTickCallback (internal/process/next_tick.js:80:11)
at process._tickDomainCallback (internal/process/next_tick.js:128:9)
name: 'RequestError',
message: 'Error: socket hang up',
cause:
{ Error: socket hang up
at createHangUpError (_http_client.js:254:15)
at TLSSocket.socketOnEnd (_http_client.js:346:23)
at emitNone (events.js:91:20)
at TLSSocket.emit (events.js:185:7)
at endReadableNT (_stream_readable.js:974:12)
at _combinedTickCallback (internal/process/next_tick.js:80:11)
at process._tickDomainCallback (internal/process/next_tick.js:128:9) code: 'ECONNRESET' },
error:
{ Error: socket hang up
at createHangUpError (_http_client.js:254:15)
at TLSSocket.socketOnEnd (_http_client.js:346:23)
at emitNone (events.js:91:20)
at TLSSocket.emit (events.js:185:7)
at endReadableNT (_stream_readable.js:974:12)
at _combinedTickCallback (internal/process/next_tick.js:80:11)
at process._tickDomainCallback (internal/process/next_tick.js:128:9) code: 'ECONNRESET' },
options:
{ method: 'GET',
uri: 'https://api.coinmarketcap.com/v2/ticker/?convert=BTC&start=0',
json: true,
callback: [Function: RP$callback],
transform: undefined,
simple: true,
resolveWithFullResponse: false,
transform2xxOnly: false },
response: undefined }
Any idea why I get this socket hang up error when my Cloud Function runs?
Edit: Here is what my cloud function code looks like:
const functions = require('firebase-functions');
// Import Admin SDK
var admin = require("firebase-admin");
var reqprom = require('request-promise');
admin.initializeApp(functions.config().firebase);
exports.minutely_tick =
functions.pubsub.topic('minutely-tick').onPublish((event) => {
console.log('This job runs every 5 minutes!');
getAllData()
.then((dataArray) => {
const ref = admin.database().ref(`myData/`);
ref.set(dataArray);
return console.log('dataArray length:', dataArray.length);
})
.catch((error) => {
return console.log('Caught error: ', error);
});
});
function getAllData() {
return new Promise((resolve, reject) => {
var promises = [];
var startInt = 0;
for (i = 0; i < 1000; i++) {
const options = {
method: GET,
uri: myUrlString,
json: true
}
promises.push(reqprom(options));
startInt += 100;
}
Promise.all(promises)
.then((dict) => {
var array = valuesFromDict(dict);
return resolve(array);
})
.catch((error) => {
return reject(error);
});
});
}
function valuesFromDict(dict) {
var values = Object.keys(dict).map((key) => {
return dict[key];
});
return values;
}
In summary, the function makes multiple API calls in a loop. And via promises I wait for all of them to complete. And then format that data into an array that I set to a Firebase Database reference.

You're not returning the final promise from your promise chain. Cloud Functions requires that you return a promise that resolves only when all of the async work is complete in your function.
return getAllData().then(...).catch(...)

i had a content filter in my computer, when i removed it the problem solved

Related

"Request is not available" on apollo graphql query to withApiAuthRequired endpoint

I'm fairly new to graphql/apollo setup, and am stuck on the following issue:
My setup looks like this roughly:
Resolvers:
export const resolvers: Resolvers = {
Query: {
getUser: withApiAuthRequired(getUser)
}
};
async function getUser(req: any, res: any) {
try {
const { accessToken } = await getAccessToken(req, res);
console.log(accessToken);
} catch (error) {
console.error(error);
res.status(error.status || 500).end(error.message);
}
}
Client caller:
const data = await client.query({
query: gql`
query UsersQuery {
getUser
}
`
});
console.log(data);
The error I get:
Uncaught (in promise) Error: Request is not available
at new ApolloError (index.js?f0e4:29:1)
at eval (QueryManager.js?2692:596:1)
at both (asyncMap.js?bd9c:16:46)
at eval (asyncMap.js?bd9c:9:57)
at new Promise (<anonymous>)
at Object.then (asyncMap.js?bd9c:9:1)
at Object.eval [as next] (asyncMap.js?bd9c:17:1)
at notifySubscription (module.js?9653:132:1)
at onNotify (module.js?9653:176:1)
at SubscriptionObserver.next (module.js?9653:225:1)
at eval (iteration.js?aad9:4:50)
at Array.forEach (<anonymous>)
at iterateObserversSafely (iteration.js?aad9:4:1)
at Object.next (Concast.js?eb39:25:43)
at notifySubscription (module.js?9653:132:1)
at onNotify (module.js?9653:176:1)
at SubscriptionObserver.next (module.js?9653:225:1)
at eval (createHttpLink.js?2d67:103:1)
Thank you so much for the guidance!
try this one:
const data = await client.query({
query: gql `
query {
getUser
}
`
});
console.log(data);
I believe the issue is that I was trying to use withApiAuthRequired inside Resolvers. The argument to Resolvers needs to be an unwrapped function to work. I ended up just skipping the withApiAuthRequired wrapper and using getSession instead.

Timeout occurred when trying to send messages from firebase admin

Am trying to send notifications to all registered users from firebase admin every 2 hours with pubsub schedule function
This is code am deploying in firebase functions
exports.scheduledFunction =functions.pubsub.schedule('every 2 hours').onRun((context) => {
console.log('This will be run every 2 hours!');
listAllUsers(undefined)});
function listAllUsers(nextPageToken) {
// List batch of users, 1000 at a time.
admin.auth().listUsers(1000, nextPageToken)
.then(function(listUsersResult) {
listUsersResult.users.forEach(function(userRecord) {
pushCheckMessageNotification(userRecord.customClaims['latest']);
});
if (listUsersResult.pageToken) {
// List next batch of users.
listAllUsers(listUsersResult.pageToken);
}
})
.catch(function(error) {
console.log('Error listing users:', error);
});
}
function pushCheckMessageNotification(token){
const promise = [];
promise.push(admin.messaging().send(
{
data: {
body: "Test",
title: "Test",
chat: "CHECK_MESSAGES"
},
android:{
priority: "high"
},
token: '' + token,
}).then(() => {
console.log("Pushed notification.");
console.log("Notify Token", token);
}).catch(error => {
console.error("Notification push crash", error);
}));
}
The below error occurred sometimes and notification not pushed
{ Error: Error while making request: timeout of 10000ms exceeded.
at FirebaseAppError.Error (native)
at FirebaseAppError.FirebaseError [as constructor] (/user_code/node_modules/firebase-admin/lib/utils/error.js:42:28)
at FirebaseAppError.PrefixedFirebaseError [as constructor] (/user_code/node_modules/firebase-admin/lib/utils/error.js:88:28)
at new FirebaseAppError (/user_code/node_modules/firebase-admin/lib/utils/error.js:122:28)
at /user_code/node_modules/firebase-admin/lib/utils/api-request.js:152:23
at process._tickDomainCallback (internal/process/next_tick.js:135:7)
errorInfo:
{ code: 'app/network-timeout',
message: 'Error while making request: timeout of 10000ms exceeded.' },
codePrefix: 'app' }

Firebase SendGrid error on sending email via Firebase functions - Error: Bad Request

I'm using Firebase and SendGrid and I'm using Firebase functions. I'm trying to send an email when a new user is created. When I trigger the function, I get the following error:
firestoreEmail: Function execution started
2019-09-10T08:13:49.245Z I firestoreEmail: { Error: Bad Request
at Request.http [as _callback] (node_modules/#sendgrid/client/src/classes/client.js:124:25)
at Request.self.callback (node_modules/request/request.js:185:22)
at emitTwo (events.js:126:13)
at Request.emit (events.js:214:7)
at Request.<anonymous> (node_modules/request/request.js:1161:10)
at emitOne (events.js:116:13)
at Request.emit (events.js:211:7)
at IncomingMessage.<anonymous> (node_modules/request/request.js:1083:12)
at Object.onceWrapper (events.js:313:30)
at emitNone (events.js:111:20)
code: 400,
message: 'Bad Request',
response:
{ headers:
{ server: 'nginx',
date: 'Tue, 10 Sep 2019 08:13:49 GMT',
'content-type': 'application/json',
'content-length': '365',
connection: 'close',
'access-control-allow-origin': 'https://sendgrid.api-docs.io',
'access-control-allow-methods': 'POST',
'access-control-allow-headers': 'Authorization, Content-Type, On-behalf-of, x-sg-elas-acl',
'access-control-max-age': '600',
'x-no-cors-reason': 'https://sendgrid.com/docs/Classroom/Basics/API/cors.html' },
body: { errors: [Array] } } }
Here is my Index.js:
const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp(functions.config().firebase);
const SENDGRID_API_KEY = 'exact API key here because functions.config().sendgrid.key doesn't work, says sendgrid is undefined';
const sgMail = require('#sendgrid/mail');
sgMail.setApiKey(SENDGRID_API_KEY);
exports.firestoreEmail = functions.firestore
.document('Users/{userId}/Followers/{followerId}')
.onCreate(event => {
const userId = "for now exact id";
const db = admin.firestore()
return db.collection('Users').doc(userId)
.get()
.then(doc => {
const user = doc.data()
const msg = {
to: "someEmailAddress#gmail.com",
from: 'hello#someEmailAddress.com',
subject: 'New Follower',
};
return sgMail.send(msg)
})
.then( () => console.log('email sent!') )
.catch( (err) => console.log(err) )
})
P.S. I was following Fireship's tutorial https://www.youtube.com/watch?v=JVy0JpCOuNI&t=333s
Edit:
These are the database SCs
first image
second image
The problem was that the const msg was missing a templateId field, which is apparently mandatory if SendGrid is used.
Here is the working snippet:
const msg = {
to: "majasveljo#gmail.com",
from: 'hello#angularfirebase.com',
subject: 'New Follower',
templateId: 'd-03ff1102c6e647c08207f293fce1701f', <--- this was missing
};

Error occurred while parsing your function triggers firebase

I am trying to implement an image upload in react using firebase storgae and I run into err 'Error occurred while parsing your function triggers firebase' when I run firebase deploy in cmd. I can't seem to figure out where the error is coming from.
The error can be seen at the bottom of the code.
const functions = require("firebase-functions");
const cors = require("cors")({origin: true});
const Busboy = require("busboy");
const fs = require("fs");
const gcconfig = {
projectId: "abcdefgh-13ff0",
keyFilename: "abcdefgh-13ff0-firebase-adminsdk-abcdefgh.json"
}
const gcs = require("#google-cloud/storage")(gcconfig);
// // Create and Deploy Your First Cloud Functions
// // https://firebase.google.com/docs/functions/write-firebase-functions
//
// exports.helloWorld = functions.https.onRequest((request, response) => {
// response.send("Hello from Firebase!");
// });
exports.uploadFile = functions.https.onRequest((req, res) => {
cors(req, res, () => {
if (req.method !== "POST"){
return res.status(500).json({
message: "Not Allowed"
});
}
const busboy = new Busboy({headers: req.headers});
let uploadData = null;
busboy.on("file", (fieldname, file, filename, encoding, mimetype) => {
const filepath = path.join(os.tmpdir(), filename);
uploadData = {file: filepath, type: mimetype};
file.pipe(fs.createWriteStream(filepath));
});
busboy.on("finish", () => {
const bucket = gcs.bucket("gs://abcdefgh-13ff0.appspot.com");
bucket.upload(uploadData.file, {
uploadType: "media",
metadata: {
metadata: {
contentType: uploadData.type
}
}
})
.then(() => {
return res.status(200).json({
message: "It worked"
});
})
.catch(err => {
return res.status(500).json({
error: err
});
});
return;
});
busboy.end(req.rawBody);
return null;
});
});
This is the error
Error: Error occurred while parsing your function triggers.
C:\Users\Joseph\node_modules\streamsearch\lib\sbmh.js:1
(function (exports, require, module, __filename, __dirname) {
SyntaxError: Invalid or unexpected token
at new Script (vm.js:74:7)
at createScript (vm.js:246:10)
at Object.runInThisContext (vm.js:298:10)
at Module._compile (internal/modules/cjs/loader.js:670:28)
at Object.Module._extensions..js (internal/modules/cjs/loader.js:713:10)
at Module.load (internal/modules/cjs/loader.js:612:32)
at tryModuleLoad (internal/modules/cjs/loader.js:551:12)
at Function.Module._load (internal/modules/cjs/loader.js:543:3)
at Module.require (internal/modules/cjs/loader.js:650:17)
at require (internal/modules/cjs/helpers.js:20:18)
the error you're experiencing might be 1 of 2 things, but probably both combined...
The keyFileName file (abcdefgh-13ff0-firebase-adminsdk-abcdefgh.json) should be in your src folder so it can be directly accessed.
You should edit these lines of code:
const gcconfig = {
projectId: "abcdefgh-13ff0",
keyFilename: "abcdefgh-13ff0-firebase-adminsdk-abcdefgh.json"
}
const gcs = require("#google-cloud/storage")(gcconfig);
TO INSTEAD READ:
const gcs = require('#google-cloud/storage')
gcs.projectId ='abcdefgh-13ff0'
gcs.keyFilename = 'abcdefgh-13ff0-firebase-adminsdk-abcdefgh.json'
// As far as I'm concerned this should fix the issue you're experiencing!

Cannot proper handle error in ajax from rxjs

I write application in React an Redux and I have a case that I have to send request to some resource when specific action was called and response of type 'text/html' write to state. This resource can return status 200 or 404, and I cannot write correct test for case with response 404.
To run tests I use jest library.
Action.js:
export const actions = {
GET_RESOURCE_SUCCESS: 'GET_RESOURCE_SUCCESS',
GET_RESOURCE_FAILURE: 'GET_RESOURCE_FAILURE'
};
export const getResourceSuccess = (response) => ({
type: actions.GET_RESOURCE_SUCCESS,
payload: response
});
export const getResourceFailure = () => ({
type: actions.GET_RESOURCE_FAILURE
});
Reducer.js:
import { handleActions } from 'redux-actions';
import { actions } from './Action';
const initialState = {
content: ''
};
export const getResourceReducer = handleActions(
{
[actions.GET_RESOURCE_SUCCESS]: (state, action) => ({ ...state, content: action.payload })
},
{
[actions.GET_RESOURCE_FAILURE]: () => ({ initialState })
},
initialState
);
In brief: when resource returns status 200 and content exists I want to overwrite content from initialState and call action GET_RESOURCE_SUCCESS, when resource returns status 404 and content doesn't exist I want not to overwrite the content and call action GET_RESOURCE_FAILURE.
GetResourceEpic.js:
import { ajax } from 'rxjs/observable/dom/ajax';
import { combineEpics } from 'redux-observable';
import { Observable } from 'rxjs';
import { getResourceSuccess, getResourceFailure } from '../Action';
const specificActionTypes = [
'SPECIFIC_ACTION_ONE',
'SPECIFIC_ACTION_TWO'
];
const getResource = () => ajax({
method: 'GET',
url: 'http://example.com',
headers: {
Accept: 'text/html'
},
crossDomain: true,
responseType: 'text/html'
});
const getResourceEpic = (action$, store) => action$
.filter(action => specificActionTypes.includes(action.type))
.flatMap(() => getResource()
// when response has status 200 and field response call getResourceSuccess
.map(({ response }) => getResourceSuccess(response))
// when response has status 404 and doesn't have field response call getResourceFailure
.catch(() => {
// helper statement to show in browser that the .catch() was called
console.log('Error');
return getResourceFailure();
})
);
export default combineEpics(
getResourceEpic
);
And it works in generally, but I get two errors:
first:
Uncaught TypeError: You provided an invalid object where a stream was expected. You can provide an Observable, Promise, Array, or Iterable.
at Object.subscribeToResult (subscribeToResult.js:73)
at CatchSubscriber../node_modules/rxjs/operator/catch.js.CatchSubscriber.error (catch.js:111)
at MapSubscriber../node_modules/rxjs/Subscriber.js.Subscriber._error (Subscriber.js:128)
at MapSubscriber../node_modules/rxjs/Subscriber.js.Subscriber.error (Subscriber.js:102)
at AjaxSubscriber../node_modules/rxjs/Subscriber.js.Subscriber._error (Subscriber.js:128)
at AjaxSubscriber../node_modules/rxjs/Subscriber.js.Subscriber.error (Subscriber.js:102)
at XMLHttpRequest.xhrReadyStateChange (AjaxObservable.js:327)
at XMLHttpRequest.d (raven.js:363)
and second:
Could not consume error: TypeError: Cannot read property 'length' of null
at getLinesAround (http://localhost:3000/static/js/bundle.js:47197:74)
at http://localhost:3000/static/js/bundle.js:47537:402
at Array.map (native)
at _callee2$ (http://localhost:3000/static/js/bundle.js:47517:54)
at tryCatch (http://localhost:3000/static/js/bundle.js:58220:40)
at Generator.invoke [as _invoke] (http://localhost:3000/static/js/bundle.js:58458:22)
at Generator.prototype.(anonymous function) [as next] (http://localhost:3000/static/js/bundle.js:58272:21)
at step (http://localhost:3000/static/js/bundle.js:47553:191)
at http://localhost:3000/static/js/bundle.js:47553:361
raven.js:51
And mentioned above problems don't allow me to write a tests, because only responses with status 200 pass the tests, other throws errors.
it('should dispatch GET_RESOURCE_SUCCESS when SPECIFIC_ACTION_ONE was dispatched', async () => {
store = mockStore();
const response = 'some content';
nock('http://example.com')
.get('/')
.reply(200, response);
const payload = { type: 'SPECIFIC_ACTION_ONE' };
// specificActionOne() produces and action of type 'SPECFIC_ACTION_ONE'
const action$ = ActionsObservable.of(specificActionOne(payload));
const resultAction = await getResourceEpic(action$, store).toPromise();
expect(resultAction)
.toEqual(getResourceSuccess(response));
});
And test above pass, but case with status equal to 404 doesn't pass:
it('should dispatch GET_RESOURCE_FAILURE when SPECIFIC_ACTION_ONE was dispatched', async () => {
store = mockStore();
nock('http://example.com')
.get('/')
.reply(404);
const payload = { type: 'SPECIFIC_ACTION_ONE' };
const action$ = ActionsObservable.of(specificActionOne(payload));
const resultAction = await getResourceEpic(action$, store).toPromise();
expect(resultAction)
.toEqual(getResourceFailure());
});
And test above doesn't pass and I get the result:
TypeError: You provided an invalid object where a stream was expected. You can provide an Observable, Promise, Array, or Iterable.
at Object.subscribeToResult (node_modules/rxjs/util/subscribeToResult.js:73:27)
at CatchSubscriber.Object.<anonymous>.CatchSubscriber.error (node_modules/rxjs/operator/catch.js:111:42)
at MapSubscriber.Object.<anonymous>.Subscriber._error (node_modules/rxjs/Subscriber.js:128:26)
at MapSubscriber.Object.<anonymous>.Subscriber.error (node_modules/rxjs/Subscriber.js:102:18)
at AjaxSubscriber.Object.<anonymous>.Subscriber._error (node_modules/rxjs/Subscriber.js:128:26)
at AjaxSubscriber.Object.<anonymous>.Subscriber.error (node_modules/rxjs/Subscriber.js:102:18)
at XMLHttpRequest.xhrReadyStateChange [as onreadystatechange] (node_modules/rxjs/observable/dom/AjaxObservable.js:327:32)
at XMLHttpRequest.callback.(anonymous function) (node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:289:32)
at invokeEventListeners (node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:219:27)
at invokeInlineListeners (node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:166:7)
at EventTargetImpl._dispatch (node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:122:7)
at EventTargetImpl.dispatchEvent (node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:87:17)
at XMLHttpRequest.dispatchEvent (node_modules/jsdom/lib/jsdom/living/generated/EventTarget.js:61:35)
at readyStateChange (node_modules/jsdom/lib/jsdom/living/xmlhttprequest.js:829:9)
at Request.properties.client.on (node_modules/jsdom/lib/jsdom/living/xmlhttprequest.js:947:7)
at Request.emit (events.js:132:15)
at IncomingMessage.<anonymous> (node_modules/request/request.js:1085:12)
at Object.onceWrapper (events.js:219:13)
at IncomingMessage.emit (events.js:132:15)
at endReadableNT (_stream_readable.js:1101:12)
at process._tickCallback (internal/process/next_tick.js:114:19)
The function passed to catch has to return an observable. You are returning an action.
Instead, you should do this:
import { of } from 'rxjs/observable/of';
...
.catch(() => {
console.log('Error');
return of(getResourceFailure());
})

Resources