I've been building a lot of quick prototypes on Netlify lately. I love the service for its ease of setup and deployment. But I keep running into this conflict between their JAMstacky conventions around API endpoints and my own background in RESTful API design.
To be more specific, say I am building a basic CRUD API in which I can create, fetch one, fetch all, and update some resource type . Let's say a User. If I were designing those endpoints from a RESTful perspective, it would 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
Now, if I were setting this up on AWS, perhaps with the serverless framework, each of those endpoints would be their own lambda. But Netlify offers no such configuration options. Which is mostly nice. I hate configuration. But it is difficult to achieve these endpoints at all with Netlify.
Specifically in this case, Netlify automatically creates endpoints which match filenames. So if you have a file named users.js, that creates a /users endpoint. The problem is, that file will be used for every possible permutation of /users. Every HTTP method. Every subroute. They all go to this one lambda. So in order to achieve a RESTful API design, I have to put everything in a single lambda and essentially make it a router. Which seems to defeat the whole idea of serverless.
So usually when you read Netlify examples, which claim to follow JAMstack patterns (something I'm not super familiar with), they do not use RESTful endpoints. Instead they tend to do something like this:
POST /create-user -> Create a user
GET /fetch-users -> Fetch all users
GET /fetch-user?id={id} -> Fetch one user
POST /update-user -> Update a user
So this is in some ways a Netlify question, and in some way a larger question about JAMstack patterns. Is there something inherent about JAMstack that makes it incompatible with REST? Are there different conventions which tend to replace REST for Netflify/JAMstack projects?
"Is there something inherent about JAMstack that makes it incompatible with REST?"
I would say no as it's not related. You aren't building an API with the Jamstack. You are using a service (Netlify) which supports serverless functions that operate alongside the rest of your site. Remember that the Netlify serverless functions are just one option. You could set up your own AWS setup and support the mechanism you want, and still use it in conjunction with the rest of your Jamstack site. I like Netlify's serverless stuff, but it's not going to work for 100% of the use cases out there.
I guess my tl;dr is - Netlify tried to make serverless simple for folks building Jamstack sites, but it won't cover every use case. When it doesn't, you can still use your own solutions along with your site.
Related
At work we're discussing how to structure our upcoming APIs. As of now, we're about to launch an API containing different user information endpoints, and though we'd publish it under an URI like this: api.mycompany.com/userinfo. Examples of endpoints:
api.mycompany.com/userinfo/users
api.mycompany.com/userinfo/users/{id}
api.mycompany.com/userinfo/api-docs <-- Swagger document for this particular API will be located here
This type of setup would allow us to have server1.mycompany.com host the API, and use our load balancer / proxy to forward traffic to api.mycompany.com/userinfo to server1.mycompany.com. For our next API running on server2.mycompany.com, we'll simply have our load balancer / proxy forward traffic from api.company.com/transportation to server2.mycompany.com, like this:
api.mycompany.com/transportation/cars
api.mycompany.com/transportation/cars/{id}
api.mycompany.com/transportation/api-docs <-- Swagger document for this particular API will be located here
By using "userinfo" and "transportation" in the URI, we'll have a simple way to reference our different APIs as a whole, and a simple way to publish the Swagger UI along side the actual API.
My concern with these URIs is that they're not hierarchical, but more like a way to group endpoints together. Nor is "userinfo" a resource, so compared to the REST API examples one typically comes across online, using elements such as "userinfo" and "transportation" in the path may not be according to best practices.
Does this design break any REST API design patterns? If so, how would you suggest us publishing our different APIs under a single fqdn (api.mycompany.com)? Or are there reasons not to use a single fqdn for all of our APIs?
Any input will be greatly appreciated.
REST doesn't care what spellings you use for your URI
My concern with these URIs is that they're not hierarchical, but more like a way to group endpoints together. Nor is "userinfo" a resource
Identifiers being "hierarchical" doesn't (necessarily) promise anything about a hierarchy of resources. The fact that there is a resource identified by /userinfo/users does not imply that there is also a resource identified by /userinfo. Think Key/Value store, not File System.
A Rails developer might recognize /userinfo and /transportation as namespaces.
If so, how would you suggest us publishing our different APIs under a single fqdn (api.mycompany.com)? Or are there reasons not to use a single fqdn for all of our APIs?
In a 2014 interview, Fielding offered this answer about versioning:
It is always possible for some unexpected reason to come along that requires a completely different API, especially when the semantics of the interface change or security issues require the abandonment of previously deployed software. My point was that there is no need to anticipate such world-breaking changes with a version ID. We have the hostname for that. What you are creating is not a new version of the API, but a new system with a new brand.
If you squint at that, it might imply that different API should be on different (logical) hosts.
Does this design break any REST API design patterns?
Nope. There are no "REST API design patterns". And REST doesn't say anything about what URLs should look like. REST says to treat them as opaque. There's an argument that web API URLs should be "hackable", that is, easily understandable and modifiable by a human. I'd argue that your URL structure is hackable. I'm not aware of any persuasive argument that URLs must be hierarchical in nature.
I'm writing an AngularJS application that's communicating with an API, and right now that API is following the REST architecture.
I know the basics of REST, but I've still not understood if REST only covers the CRUD operations? For example, if I'm building a community website and I want to make it possible for people to add each other as friends, is this covered by REST in any way? What about search queries? If not, is there any other architecture that's recommended to follow, or should I roll my own?
Also, should I even be using REST for a community website? There are a lot of cases where it seems like it's not the optimal design, but when I google around I only get results saying that REST is the best practice. For example PUT /api/user/:id wouldn't be very useful, since the only user you're able to update (unless you're an admin) is yourself.
It all depends, REST is just an architectural style and (in many forms unfortunately) is used all over the world. I also follow REST rules in all type of applications but try to stay at the second level of Richardson's Maturity Model. Why? Since I consider HAL, HATEOAS and all the API discoverability as an unnecessary buzz - unfortunately documentation is still very important.
What you need to consider while designing an API is if it's going to public or not. If it's not, you can probably whatever you want/need (of course this is not good idea). If it is going to be public the consistency starts to play a great role - API needs to be designed in such a way that it will be both intuitive and easy to use. E.g. this is not good idea to introduce new endpoint every time you need a new operation - thus following CRUD REST rules seems to be reasonable option. When it comes to to going beyond CRUD - yes, I've created APIs with verbs in endpoints - but it was almost always the last resort and to be honest I don't feel guilty.
I think the question is a bit too broad, but I'll try to answer.
REST only covers the CRUD operations?
No, it covers other operations as well. You have to transform your operation into a HTTP method and a resource. The resource can have identifiers: URIs. An URI with a HTTP method compose a hyperlink. This hyperlink can be followed by the client. You can attach the operation name, etc... to the hyperlink as meta-data, so it can be used by the client to recognize the operation. At least that's how it should work.
What about search queries?
General queries are not supported currently, because there is no standard RDF vocab which could be used to describe a general query. There are non-standard workaround, you can use them or for example a SPARQL endpoint. More fixed queries can be used with URI templates.
Also, should I even be using REST for a community website?
As far as I know facebook uses it for 3rd party clients, so you can develop a facebook application using their REST API. Another advantage that it scales better than SOAP. If you don't need these features currently, then you can use something else you are more familiar with.
When writing a RESTful API that needs to access different environments such as a lab/test database and a production database, what's the best practices around setting up the API?
Should there be a #PathParam?:
/employee/{emp_id}/{environment}
/{environment}/employee/{emp_id}/
Should there be a #QueryParam?:
/employee/{emp_id}/?environment="test"
/employee/{emp_id}/?environment="prod"
Should there be a field in the payload?:
{"emp_id":"123","environment":"test"}
{"emp_id":"123","environment":"production"}
In fact I see two ways to handle this. The reason to use one or the other corresponds to what is the most convenient to implement in your RESTful application.
Using a path parameter
With this approach, it should be a path parameter at the very beginning of the resource path. So URL would be like this: /{environment}/employee/{emp_id}. Such approach is convenient if you have several applications deployed under different root paths. For example:
/test: application packaged with the configuration for the test environment
/prod: application packaged with the configuration for the production
In this case, applications for each environment are isolated.
Using a custom header
You could also a custom header to specify on which environment to route. Github uses something like that to select the version of the API to use. See this link: https://developer.github.com/v3/#current-version. It's not exactly the same thing but you could have something like that:
GET /employee/{emp_id}
x-env: test
A reverse proxy could handle this header and route the request to the right environment.
I'm not convinced by the approach within the payload since an field environment isn't actually a part of the representation for element resource employee. Regarding the query parameter approach, it's similar since such parameters apply to the request on the resource.
Hope it helps you,
Scenario: We are creating/desiging a REST service to help us configure a system (and it's network, etc), but we run into some problems related to designing this API. We would like to configure the hostname of the system using a REST call/
Challenge: Because most APIs and design guidelines are related to lists of entities and not just a single one, I can't decide on how the rest API should look like.
Currently we are considering using something like:
GET /system/0
PUT /system/0 {....}
Problem: There is just one system entity so it doesn't feel good to identify this using 0 because there is only one of it.
Are there any REST guidlines about how this should be done?
Actually, REST does not enforce a particular format for the URL, you can even have an URL like /569284d7-1b59-4343-92d4-90e8753bcbd7 and it's OK. In REST the server guides the client through state changes, it's not about the client knowing what URLs to access.
Most web API's are created in a CRUD style, with hierarchies of resources like your example /system/0, /system/1 because it's easier to understand and implement (might not always be RESTful depending on how tight the coupling of the client is to the URLs, but it serves most needs so people chose to do it like that).
So my advice would be to keep it simple and not over-think it. Using /system/0 is just fine, even if now you have only one system.
Just my 2 cents!
I am working on a experimental website (which is accessible through web browser) that will act as a front-end to a restful interface (a sub-system). The website will serve as an interface between a user and the restful interface, as it will make http requests to the restful interface for almost all database operations. Authentication will probably be done using openid and authorization for the database operations will be done via oAuth.
Just out of curiousity, is this a feasible solution or I should develop two systems that accesses the database in parallel (i.e. the website has its own data access logic, and the restful interface has another data access logic)? And what are the pros/cons if I insist on doing it this way (it is just an experiment project for me to learn things like how OpenID and oAuth work in real life anyway) besides there will be more database queries and http requests generated for each transaction?
Your concept sounds quite feasible. I'd say that you'll get some fairly good wins out of this approach. For starters you'll get a large degree of code reuse since you'll be able to put other front ends on top of the RESTful service. Additionally, you'll be able to unit test this architecture with relative ease. Finally, you'll be able to give 3rd party developers access to the same API that you use (subject possibly to some restrictions) which will be a huge win when it comes to attracting customers and developers to your platform.
On the down side, depending on how you structure your back end you could run into the standard problem of granularity. Too much granularity and you'll end up making lots of connections for very little amounts of data. Too little and you'll get more data than you need in some cases. As for security, you should be able to lock down the back end so that requests can only be made under certain conditions: requests contain an authorization token, api key, etc.
Sounds good, but I'd recommend that you do this only if you plan to open up the restful API for other UI's to use, or simply to learn something cool. Support HTML XML and JSON for the interface.
Otherwise, use a great MVC framework instead (asp.net MVC, rails, cakephp). You'll end up with the same basic result but you'll be "strongerly" typed to the database.
with a modern javascript library your approach is quite straightforward.
ExtJS now has always had Ajax support, but it is now able to do this via a REST interface.
So, your ExtJS user interface components populate receive a URL. They populate themselves via a GET to the URL, and store update via POST to the URL.
This has worked really well on a project I'm currently working on. By applying RESTful principles there's an almost clinical separation between the front & backends - meaning it would be trivial undertaking to replace other. Plus, the API barely needs documenting, since it's an implementation of an existing mature standard.
Good luck,
Ian
woow! A question from 2009! And it's funny to read the answers. Many people seem to disagree with the web services approach and JS front end - which has nowadays become kind of standard, known as Single Page Applications..
I think the general approach you outline is quite feasible -- the main pro is flexibility, the main con is that it won't protect clueless users against their own ((expletive deleted)) abuses. As most users are likely to be clueless, this isn't feasible for mass consumption... but, it's fine for really leet users!-)
So to clarify, you want to have your web UI call into your web service, which in turn calls into the database?
This is exactly the path I took for a recent project and I think it was a mistake because you end up creating a lot of extra work. Here's why:
When you are coding your web service, you will create a library to wrap database calls, which is typical. No problem there.
But then when you code your web UI, you will end up creating another library to wrap calls into the REST interface... because otherwise it will get cumbersome making all the raw HTTP calls.
So you essentially created 2 data access libraries, one to wrap DB and the other to wrap the Web service calls. This basically doubles the amount of work you do, because for every operation on a resource, you will end up implementing in both libraries. This gets tiring real fast.
The simpler alternative is to create a single library that wraps access to the database, as before, then use that library from BOTH the web UI and web service.
This is assuming that your web UI and web service reside on the same network and both have direct access to the backend database server (which was the case for me). In this setup having both go directly to the database is also a lot more efficient then having the UI go through the web service.