-
-
Notifications
You must be signed in to change notification settings - Fork 2.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
How to deploy on Firebase Functions/Google Cloud Functions #946
Comments
This is not possible currently. #804 is a similar issue. |
We are working on that feature in #937. |
One more PR #960 |
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions. |
@endigo in the latest version of Fastify ( Closing this, please feel free to reopen if you have other questions :) |
@delvedor @mcollina would love to have some pointers to actually use fastify in Cloud Functions. The typical call for http triggered functions is done by calling Functions' built-in onRequest method: The full code example is at https://gist.github.com/shwei/d34c7383a117451c07dc701ad12482f1 Is there a way I can make this happens with Fastify? Thank you all. |
@shwei you might want to use https://www.fastify.io/docs/v1.13.x/Server/#serverfactory and pass the given handler to https://gist.github.com/shwei/d34c7383a117451c07dc701ad12482f1#file-fastify-in-firebase-function-js-L9 instead of the fastify instance. |
@mcollina thanks, but I don't know how to pass the given handler from serverFactory out to onRequest. Here is what I've so far https://gist.github.com/shwei/d34c7383a117451c07dc701ad12482f1#file-fastify-in-firebase-function-js-L14 I know this is not what you're asking. But at this point I don't know the core concept I'm missing to understand this better. If you know, please let me know! Thanks again! |
is this fixed yet? I tried to use the serverFactory as pointed out by @shwei but it's not working! Can you please provide me with a code example?
I am getting |
@mtermoul Something like this should work: const functions = require('firebase-functions')
const http = require('http')
const Fastify = require('fastify')
let handleRequest = null
const serverFactory = (handler, opts) => {
handleRequest = handler
return http.createServer()
}
const fastify = Fastify({serverFactory})
fastify.get('/', (req, reply) => {
reply.send({ hello: 'world' })
})
exports.app = functions.https.onRequest((req, res) => {
fastify.ready((err) => {
if (err) throw err
handleRequest(req, res)
})
}) This is more efficient as well since it doesn't create a new Fastify instance on every request. |
Thanks @nwoltman! This is very helpful. I had to put in the line before fastify.ready() call: req = Object.assign({ip: ''}, {...req});
fastify.ready((err) => {
... Without that hacky line, I would get the error: error: /Users/shwei/Work/workspace/cf-fastify-restify-express/functions/node_modules/fastify/fastify.js:249
req.ip = req.connection.remoteAddress
^
TypeError: Cannot set property ip of [object Object] which has only a getter
at _ipAsRemoteAddress (/Users/shwei/Work/workspace/cf-fastify-restify-express/functions/node_modules/fastify/fastify.js:249:12) Is there a way to avoid this error? @mtermoul: thanks for following up with this man.
|
@shwei It looks like that error happens because @fastify/fastify What do you think is the right thing to do here? Is this a problem that should be fixed in Fastify? |
Thanks for looking into this @nwoltman . If this can be accommodated without too much sacrifice on performance, it would allow greater compatibility with one of very popular serverless infrastructures. Or maybe if we could pass an option to skip setting req.ip?
|
Another solution would be to set |
@nwoltman when you said, "set ip on the Fastify request object", can you elaborate it a little more? Did you mean set trustProxy? const fastify = Fastify({ trustProxy: true })
// OR given IP/CIDR?
const fastify = Fastify({ trustProxy: '${IP/CIDR}' }) Thanks!
|
@shwei Yes, it's related to the Line 307 in 356cf6f
rather than setting it on Node's req object here:Lines 273 to 283 in 356cf6f
Of course, if that were done, |
@nwoltman Interesting with passing ip in the context.Request call! It sounds like Another idea: if req.ip has a value and if there is an option we can pass into fastify to indicate that we want to skip calling the method Express's prototype-extended
|
@shwei Having an option that is only used to avoid setting a particular property does seem pretty hacky, especially when there's a non-hacky solution. I'd suggesting submitting a PR to move |
Thank you, @nwoltman. Finally got around to work on this. I'm fairly new to fastify, so would you please take a look at my changes? shwei/fastify@88f4c8a Your comments are greatly appreciated.
|
@shwei I found another way to avoid the error that's less likely to introduce other bugs. Instead of req = Object.assign({ip: ''}, {...req}); do Object.defineProperty(req, 'ip', {
value: req.ip,
configurable: true,
enumerable: true,
writable: true,
}); This just modifies the |
Can you please explain to me what is the problem? I don’t understand. |
The problem is that people who use Fastify with Google Cloud's Firebase Functions will run into this error on every request:
This happens because Fastify is trying to set the |
I’m happy to add an option to disable that. I think it should work. |
By all means, please do if that makes most sense. Hope the new option will be available for 1.x. Let me know how I can help. Thanks! |
@shwei can you update your PR in that direction? I'm happy to have the change backported. |
@mcollina Just wondering, is the plan you're thinking of to:
|
That’s the plan. |
OK, that sounds good to me 🙂 |
@shwei I would go one step further and do: |
@mcollina would this option apply to |
@shwei yes, I would actually go that far. |
We just spent a considerable amount of time trying to get fastify running on google cloud functions, and then we discovered google cloud run which shares many of the benefits of cloud functions but works much more easily with fastify. You just specify a docker file and cloud run will run your dockerized fastify server like a serverless function. It took 10 minutes to setup and required no major code changes from how you would run fastify on a regular server |
@jineshshah36 would you like to add your finding in the Serverless.md? This would help the community for sure 💪 |
Yes, keep forgetting to do this. Will try to send a PR this weekend! |
Done: #1770 |
I understand it's a bit easier to configure fastify with Google Cloud Run due to it's container based approach. But I'm still wondering if any progress was made to better support fastify with Firebase Cloud functions for people that prefer the Firebase ecosystem? |
I never had a chance. Would you like to investigate it and send a PR for the serverless docs? |
@rfgamaral It should work just fine if you set the |
So for anybody who is having trouble on google cloud functions or firebase functions use this in your package.json "@google-cloud/functions-framework": "devotox/google-cloud-functions-framework" The problem with POST requests was that functions-framework already attached a body parser |
Any small working example will help the community a lot. How and where to use the above line? |
To this day, the issue @devotox mentions is present. The root of the problem is in Since the fastify.addContentTypeParser('application/json', {}, (req, body, done) => {
done(null, body.body);
}); Hope I can help someone else wanting to use this superb library together with cloud functions 🤗 Full Example Code const functions = require('firebase-functions');
let requestHandler = null;
const fastify = require('fastify')({
logger: true,
serverFactory: (handler) => {
requestHandler = handler;
return require('http').createServer();
},
});
fastify.addContentTypeParser('application/json', {}, (req, body, done) => {
done(null, body.body);
});
fastify.post('/postToMeWithJSON', async (req) => {
return req.body;
});
exports.myApi = functions.https.onRequest((req, res) => {
fastify.ready((err) => {
if (err) throw err;
requestHandler(req, res);
});
}); |
I second this. I am experiencing the same issues. |
Great analysis. Thanks for the detailed solution. |
this fix in no longer valid since body is now an incoming message and there is no |
FWIW, body.body still works as of today, even though body is IncomingMessage, and the types say there is no body.body. I'm using |
The typings is correct since the |
this solution won't work (or the one from the doc) for multipart / file upload :/
Also won't correctly work and the body will stay as a Buffer in the route. |
How to run the server from cloud functions?
in express
The text was updated successfully, but these errors were encountered: