Hey there! Love Netlify. Great service. There is nothing better than an opinionated tool with sensible defaults that removes the need for cumbersome configs.
However! There is one sensible default that consistently causes me trouble: the way Netlify sets up API endpoints based on file names. It’s fine for a quick prototype, but even with prototypes I prefer to follow RESTful conventions for my APIs.
So let’s say I have a simple CRUD app with some users, I want endpoints to create, fetch one, fetch all, and update. Ideally, I would build the API to look like this:
POST /users -> Create a user
GET /users -> Fetch all users
GET /users/{id} -> Fetch one user
PUT /users/{id} -> Update a user
As near as I can tell, it is impossible to create an API like this while also having each endpoint point to a different Netlify Function. I could create a single users.js
lambda and put a router in it, but that would seem to defeat the purpose of serverless lambdas.
So while I love the zero-config convenience of naming routes after file names by default, I would love it if there were some way to support common RESTful conventions, even if it means some extra configuration.
I have three ideas about how this could be accomplished. Implementing one or all might be worthwhile.
Support Redirects Based On HTTP Method
I can already get halfway there with the current redirect support. For example, I could create a netlify.toml
like this:
[[redirects]]
from = "/.netlify/functions/users/:id/"
to = "/.netlify/functions/fetch-one-user/:id/"
[[redirects]]
from = "/.netlify/functions/users"
to = "/.netlify/functions/fetch-all-users"
This works if all I am doing is fetching, or if every endpoint happens to have a unique URI. However, without some support for redirecting on HTTP methods, I am stuck adding some sort of routing functionality to my lambdas. Adding a method
key to redirects would be very useful for this case, and probably for other use cases as well.
Example usage of the proposed method
property:
[[redirects]]
from = "/.netlify/functions/users/:id/"
to = "/.netlify/functions/update-user/:id/"
method = "PUT"
[[redirects]]
from = "/.netlify/functions/users/:id/"
to = "/.netlify/functions/fetch-one-user/:id/"
method = "GET"
[[redirects]]
from = "/.netlify/functions/users"
to = "/.netlify/functions/fetch-all-users"
method = "GET"
[[redirects]]
from = "/.netlify/functions/users"
to = "/.netlify/functions/create-user"
method = "POST"
If you do not specify a method, then the redirect would apply to all methods as it does now. I am not sure how difficult this is to implement, but from an API perspective, it seems like a straightforward non-breaking change.
Introduce file name conventions for methods and path variables
This one might need a little bit more design, since it is a potentially breaking change. However, you could expand the rules you have around filenames to include HTTP methods and nested routes representing path variables.
For the example above, you might create a directory structure like this:
functions/
└─┬ users/
├── get.js
└── post.js
That’s straightforward enough. But inevitably, it does get a bit weird once you introduce path variables. You might use some convention like underscores or curly braces to designate path variables.
functions/
└─┬ users/
├── get.js
├── post.js
└─┬ __id__/
├── get.js
└── put.js
Kind of ugly. But potentially useful. You might also use underscores or other special characters for the HTTP method based filenames as well to prevent breaking anyone’s deploys who happen to be using those names already.
Add new config options for manually specifying endpoints
This is kind of an anti-Netlify approach, but this would be an entirely optional addition, and it is not like Netlify is truly zero-config anyway. I don’t have any strong opinions on the exact syntax, but I imagine it would go in netlify.toml
and might take queues from something like the Serverless framework’s serverless.yaml
file:
[[functions]]
handler = "functions/update-user"
method = "PUT"
path = "/users/:id"
[[functions]]
handler = "functions/fetch-one-user"
method = "GET"
path = "/users/:id"
[[functions]]
handler = "functions/fetch-all-users"
method = "GET"
path = "/users"
[[functions]]
handler = "functions/create-user"
method = "POST"
path = "/users"
This is probably more work to implement, but since it is optional, it would not break anything.
Anyway! Hope that’s helpful. As I said, overall I love Netlify, and recommend it highly to whoever will listen. A little more robust support for naming backend endpoints would really be the icing on the cake.