I want to make a simple serverless backend, so I'm trying to use google cloud functions with flask routing.
I'm trying to test a simple code, but it's not working. The following source always returns 404 errors.
from flask import Flask, make_response
class Services:
pass
def create_app(test_config = None):
app = Flask(__name__)
services = Services
create_endpoints(app, services)
return app
def create_endpoints(app, services):
#app.route("/test", methods=['GET'])
def test():
return make_response('Test worked!', 200)
function URL : ######.cloudfunctions.net/test1
I tried "######.cloudfunctions.net/test1" and "######.cloudfunctions.net/test1/test", but it always returns 404 error.
can I use flask routing ?
I think that it is a not fancy way to add a router to a cloud function, but it works.
I used the property "path" of the object "request"( this is a flask.request object) to read the path after the domain in the requested URL
from flask import abort
def coolrouter(request):
path = (request.path)
if (path == "/test"):
return "test page"
elif (path == "/home" or path =="/"):
return "ḧome page"
else:
abort (404)
keep in mind that cloud functions are designed to be a one shot services, that means that is not possible to save session variables or other things since this is service is ephemeral.
If you want upload a complete site I recommend you to use App Engine, which is a Fully managed serverless application platform.
Google now has api gateway which would allow you to have a single endpoint to handle all of your routes. See goblet as an easy way to manage and deploy your api to api gateway
I agree with all the answers given here, but I want to elaborate a bit from my experience. Since Cloud Functions are designed for single-purpose use only. It can process HTTP requests and events from pubsub, storage etc. When using API gateway or Cloud Endpoints in front of your Cloud Functions, you can offload authentication and routing, so your code has only one responsibility.
However, the downside that you will never get rid of the cold-start problem when using Cloud Functions as an API. Serving requests can sometimes last up to 2-10 seconds or more, depending on the size of your code and programming language. So you are probably better of with Google App Engine or something that you can reserve to be "always there".
I am currently experimenting with the Cloud Function + API Gateway setup. I am routing GET, POST and DELETE methods for one object to the same cloud function. So I am basically trying to let it be single-purpose in the way that one function only handles requests for only one object. This could easily be accomplished with a switch case on the method used, so no routing is needed. A schematic example:
Cloud function one:
Path: /blogs
Methods: GET, POST, DELETE
Purpose: Handles all actions on blog objects
Cloud function two:
Path: /posts
Methods: GET, POST, DELETE
Purpose: Handles all actions on post objects
According to the official documentation:
Cloud Functions is a serverless execution environment for building and
connecting cloud services. With Cloud Functions you write simple,
single-purpose functions that are attached to events emitted from your
cloud infrastructure and services. Your function is triggered when an
event being watched is fired.
Python Quickstart Cloud Functions
Related
I have set up a REST endpoint (simple http GET) using Sveltekit's endpoints implementation. It works in 'npm run dev' mode when it's running on my computer, but certain requests give errors when hosted on Netlify. The specific error message is straightforward:
{"errorMessage":"Response payload size exceeded maximum allowed payload size (6291556 bytes).","errorType":"Function.ResponseSizeTooLarge"}
I know I can fix this by splitting up and paging results.
My question is: Does Netlify use AWS Lambda to host the compiled Svelte endpoints even if I don't use Netlify's serverless functions explicitly?
I ask because searching this error message gives results about Netlify/AWS lambda, and I'm just curious to know if anyone knows concretely how Netlify handles these svelte endpoints behind the scenes. It really looks like they bundle them into AWS Lambda functions (which they already advertise they are using for their own Netlify functions).
Svelte uses #sveltejs/adapter-netlify under-the-hood: https://www.npmjs.com/package/#sveltejs/adapter-netlify to work on Netlify. This package generates a Netlify Function named render which handles the Server Side Rendering of your Svelte application.
So to answer your question, yes, you're using Netlify Functions in your project - not yourself, but your framework is doing that for you.
I am trying to use the AWS API Gateway+Swagger to route the request to my express backend. I can't figure out how to automate the setup of the integration request as the Swagger file has no details on it.
I'm also having difficulty with the endpoint url parameter when setting my method requests to GET/VPC Link on the integration type
For example:
My api gateway path is /info/car/{model}/aggregate
Now the endpoint url is http://carapi.com/info/car/{model}/aggregate
I have lots of gateway paths all of which are the same paths that my carapi.com site uses, so I don't want to keep retyping the path over and over. When entering in the endpoint url, I was able to simplify not having to type carapi.com by using stage variables turning my endpoint url to
http://${stageVariables.carApi}/info/car/{model}/aggregate
However after reading https://docs.aws.amazon.com/apigateway/latest/developerguide/api-gateway-mapping-template-reference.html#stagevariables-template-reference
I see that there is also a $context available, but it gives me an error(when I try to call the api in postman, says 'internal server error' for the message) when I try to implement the context (which through that link shows that I can implement the path).
http://${stageVariables.carApi}/${context.resourcePath}
So my question is: how do I automate the setup of Integration requests so I don't have to manually setup each and every one(as I have hundreds of paths)? Is there also anyway to not have to set the paths manually for the endpoints?
I don't know of any solution which is ready to use.
In my project, we wrote a custom solution that downloads the application Swagger json, parses it, adds the required integration and generates another json file. Then we import that into API Gateway. This has been converted as a Jenkins job and runs as a post job of microservice deployment.
Another way is, instead of generating the json, directly call API Gateway APIs and add the integration.
I can't see any option anywhere to set up a custom domain for my Google Cloud Function when using HTTP Triggers. Seems like a fairly major omission. Is there any way to use a custom domain instead of their location-project.cloudfunctions.net domain or some workaround to the same effect?
I read an article suggesting using a CDN in front of the function with the function URL specified as the pull zone. This would work, but would introduce unnecessary cost - and in my scenario none of the content is able to be cached so using a CDN is far from ideal.
If you connect your Cloud project with Firebase, you can connect your HTTP-triggered Cloud Functions to Firebase Hosting to get vanity URLs.
Using Cloudflare Workers (CDN, reverse proxy)
Why? Because it not only allows you to set up a reverse proxy over your Cloud Function but also allows you to configure things like - server-side rendering (SSR) at CDN edge locations, hydrating API response for the initial (SPA) webpage load, CSRF protection, DDoS protection, advanced caching strategies, etc.
Add your domain to Cloudflare; then go to DNS settings, add a A record pointing to 192.0.2.1 with Cloudflare proxy enabled for that record (orange icon). For example:
Create a Cloudflare Worker script similar to this:
function handleRequest(request) {
const url = new URL(request.url);
url.protocol = "https:";
url.hostname = "us-central1-example.cloudfunctions.net";
url.pathname = `/app${url.pathname}`;
return fetch(new Request(url.toString(), request));
}
addEventListener("fetch", (event) => {
event.respondWith(handleRequest(event.request));
});
Finally, open Workers tab in the Cloudflare Dashboard, and add a new route mapping your domain URL (pattern) to this worker script, e.g. example.com/* => proxy (script)
For a complete example, refer to GraphQL API and Relay Starter Kit (see web/workers).
Also, vote for Allow me to put a Custom Domain on my Cloud Function
in the GCF issue tracker.
Another way to do it while avoiding Firebase is to put a load balancer in front of the Cloud Function or Cloud Run and use a "Serverless network endpoint group" as the backend for the load balancer.
Once you have the load balancer set up just modify the DNS record of your domain to point to the load balancer and you are good to go.
https://cloud.google.com/load-balancing/docs/https/setting-up-https-serverless
Been a while for this answer.
Yes, now you can use a custom domain for your Google Cloud functions.
Go over to firebase and associate your project with firebase. What we are interested in here is the hosting. Install the Firebase CLI as per the firebase documentation - (very good and sweet docs here)
Now create your project and as you may have noticed on the docs, to add firebase to your project you type firebase init. Select hosting and that's it.
Once you are done, look for the firebase.json file. Then customize it like this
{
"hosting": {
"public": "public",
"ignore": [
"firebase.json",
"**/.*",
"**/node_modules/**"
],
"rewrites": [
{
"source": "myfunction/custom",
"function": "myfunction"
},
]
}
}
By default, you get a domain like https://project-name.web.app but you can add your own domain on the console.
Now deploy your site. Since you are not interested in web hosting probably you can leave as is. Now your function will execute like this
Function to execute > myfunction
Custom url > https://example.com/myfunction/custom
If you don't mind the final appearance of the url you could also setup a CNAME dns record.
function.yourdomain.com -> us-central1******.cloudfunctions.net
then you could call it like
function.yourdomain.com/function-1/?message=Hello+World
I have been messing around with AWS lambda today trying some things out. I am currently trying to trigger the function from a url in a browser.
The URL looks similar to this: https://abcdef.execute-api.eu-west-2.amazonaws.com/default/test
As I understand it I can assign a custom domain to my endpoint, but can I also get rid of the path part of the url, so for example:
GET: https://example.com/
GET: https://example.com/somefile.txt
POST: https://example.com/ ['some_post_field' => 'some data']
Will all be passed to my function, or do I need to configure an EC2 instance with NGINX to proxy-pass the requests to lambda?
Any thoughts would be useful.
There are now a couple different ways you can accomplish this in AWS:
The newest (arguably coolest!) is to use Cloudfront to run your code using their Lambda#Edge service. You can completely customize your URL path and have portions used as variables like any other REST endpoint. You attach your Lambda fn to "behaviour" endpoints which give you full URL control. Its fairly deep and beyond the scope of your question to explain it all here, but read through the docs at the link provided and you'll likely see lots of stuff you like.
Another older, more expensive but more documented method is to use AWS's API Gateway as you have eluded to in your question's tags. It has a great front end console and is easy to connect API endpoints to your Lambda backend logic by attaching them to REST methods. The console helps you "variable-ize" your URL with form field data. This service helps you the most with custom domains to trigger from. Setting up custom domains is a snap in API Gateway. Be sure to use AWS's SSL Certificate Manager for free SSL certs on your custom domain too!
How you specifically setup your endpoints depends on which service you choose. Personally, given your desire to serve up different types of content, I would lean towards CloudFront, and define a "behaviour" URL for your dynamic Lambda content. If the URL request does not match one of your defined behaviours, it defaults to the Cloudfront cache/origin to serve your static assets (somefile.txt). Only matches go to your attached Lambda fn with form data. Very slick!
A lot of example Lambda#Edge fn's are available here.
I have used both and have clients on both now. Lambda#Edge is ridiculously faster and less expensive, BUT is less documented, has a steeper learning curve, and console is not nearly as helpful. I would honestly try both to see which fits your situation and experience level best. Both will get the job done. EC2 is most definitely NOT needed (nor desired perhaps). Hope that helps — good luck!
Instead of directly exposing the Lambda function via URL, expose it through AWS API Gateway where you can define your own paths and map to a Domain.
I can't see any option anywhere to set up a custom domain for my Google Cloud Function when using HTTP Triggers. Seems like a fairly major omission. Is there any way to use a custom domain instead of their location-project.cloudfunctions.net domain or some workaround to the same effect?
I read an article suggesting using a CDN in front of the function with the function URL specified as the pull zone. This would work, but would introduce unnecessary cost - and in my scenario none of the content is able to be cached so using a CDN is far from ideal.
If you connect your Cloud project with Firebase, you can connect your HTTP-triggered Cloud Functions to Firebase Hosting to get vanity URLs.
Using Cloudflare Workers (CDN, reverse proxy)
Why? Because it not only allows you to set up a reverse proxy over your Cloud Function but also allows you to configure things like - server-side rendering (SSR) at CDN edge locations, hydrating API response for the initial (SPA) webpage load, CSRF protection, DDoS protection, advanced caching strategies, etc.
Add your domain to Cloudflare; then go to DNS settings, add a A record pointing to 192.0.2.1 with Cloudflare proxy enabled for that record (orange icon). For example:
Create a Cloudflare Worker script similar to this:
function handleRequest(request) {
const url = new URL(request.url);
url.protocol = "https:";
url.hostname = "us-central1-example.cloudfunctions.net";
url.pathname = `/app${url.pathname}`;
return fetch(new Request(url.toString(), request));
}
addEventListener("fetch", (event) => {
event.respondWith(handleRequest(event.request));
});
Finally, open Workers tab in the Cloudflare Dashboard, and add a new route mapping your domain URL (pattern) to this worker script, e.g. example.com/* => proxy (script)
For a complete example, refer to GraphQL API and Relay Starter Kit (see web/workers).
Also, vote for Allow me to put a Custom Domain on my Cloud Function
in the GCF issue tracker.
Another way to do it while avoiding Firebase is to put a load balancer in front of the Cloud Function or Cloud Run and use a "Serverless network endpoint group" as the backend for the load balancer.
Once you have the load balancer set up just modify the DNS record of your domain to point to the load balancer and you are good to go.
https://cloud.google.com/load-balancing/docs/https/setting-up-https-serverless
Been a while for this answer.
Yes, now you can use a custom domain for your Google Cloud functions.
Go over to firebase and associate your project with firebase. What we are interested in here is the hosting. Install the Firebase CLI as per the firebase documentation - (very good and sweet docs here)
Now create your project and as you may have noticed on the docs, to add firebase to your project you type firebase init. Select hosting and that's it.
Once you are done, look for the firebase.json file. Then customize it like this
{
"hosting": {
"public": "public",
"ignore": [
"firebase.json",
"**/.*",
"**/node_modules/**"
],
"rewrites": [
{
"source": "myfunction/custom",
"function": "myfunction"
},
]
}
}
By default, you get a domain like https://project-name.web.app but you can add your own domain on the console.
Now deploy your site. Since you are not interested in web hosting probably you can leave as is. Now your function will execute like this
Function to execute > myfunction
Custom url > https://example.com/myfunction/custom
If you don't mind the final appearance of the url you could also setup a CNAME dns record.
function.yourdomain.com -> us-central1******.cloudfunctions.net
then you could call it like
function.yourdomain.com/function-1/?message=Hello+World