This is a general RESTful API design question. We are trying to solve the following case with the most common approach possible.
We have a resource, let's say: /licenses/5123
The resource has an expiration date which needs to be updated to an expired state. Of course the easiest thing to do would be to just expose the expiration_date and have the client set it to the new date but that is not desired.
To update the resource, we're using PUT method and would like to specify the type of update this will be. In other words, is the update action 'expire' or 'extend' or 'whatever'.
I considered a few option:
implement custom http method - but I don't like extending HTTP protocol beyond its standards
add action url parameter and specify the value: PUT /licenses/5123?action=expire
since there are other params in the body of the request in JSON format, add action param into the JSON request.
implement custom http header for the type of update this is
Please share your opinion and/or provide any references to online resources that may be describing such cases. I can't imagine this is a unique case.
Thank you very much!
Generally option 2 and 3 are preferred. There is no real need to do something custom with HTTP actions or custom headers.
PUT is a reasonable action method for updating a license like you describe. Putting the details of the update in the JSON request body sounds reasonable (Option 3), and that's what I would do.
Option 2 is my preferred choice.
I think going with option 2 has been my common best practice, it's clean, efficient and readable. Most of the time I strive for readability and maintainability over all else as I may not be the developer debugging, fixing or extending the code in the future.
Doing anything with either the HTTP protocol or headers always feels like a 'hack'. I think it's going above and beyond and will require more effort than the problem is most likely worth (which scraps solutions 1 and 4).
A potential issue with option 3 is that you could be confusing business logic with your data which leads to coupling and potential upgrade issues.
Related
I have a question to RESTful services. In REST the POST method is used to create an entity.
And GET is used to query entities. Right?
As I read in another posts it is not allowed in HTTP to send a GET request with a body.
But when I want to send Json to make a query, what is the best way? Are there any best practices or how do you solve such json queries?
Thanks for your answers
In REST the POST method is used to create an entity. And GET is used to query entities. Right?
Not really. GET is used to fetch representations of resources. POST is deliberately vague -- anything not worth standardizing can use POST.
when I want to send Json to make a query, what is the best way?
There is no best way to do it, just trade offs.
The basic plot of HTTP is that you GET representations of resources. If the resource you want doesn't exist, you create a new one. So the "REST" flow would look something like sending a request to the server to create a "the answer to my query" resource, and then using GET to obtain the current representation of that resource. Which is great, because we can fetch the latest representation of that resource any time we're worried that our copy is out of date. Other people with the same query can use the same resource, so we can use a general-purpose cache to take a lot of the work. The end result is "web scale".
OK, not that great, because we learned that sending information over insecure channels is a bad idea; but we can put a general-purpose caching proxy in front of our server, and get some scale that way.
But "create a new resource" is a lot of ceremony when you only expect to need the query once.
Creating a new resource was using POST in this situation anyway, so why not return a representation of the solution right away? And the answer is, go right ahead! that works great... but doesn't give you any cache support at all. You are effectively performing a remote call under the guise of modifying a resource.
Also, POST doesn't promise idempotent semantics -- on an unreliable network, requests can get lost, and general purpose components won't know that in this particular case it is harmless to just repeat the same request.
PUT has idempotent semantics... but it also has very specific opinions about the contents of the payload that don't match "query" at all.
You can dig through other standardized methods, but there aren't really any good fits. The only methods that are close are SEARCH and REPORT, which are coupled to WebDAV semantics.
You can invent your own non standard method; but general purpose components won't understand it.
You can standardize a new method with the semantics you need, but that's a lot of work.
Or you can just use POST.
Remember, the web took over the world using nothing more than GET and POST. So it's probably fine.
In a separate SO question, I asked how to populate a Maximo field using a db function:
Take value from FieldA, send to a db function, and return value to FieldB
A Stack Overflow community member was kind enough to answer the question and provided this advice:
And all that said, you should just use the automation script to do
what you have the database function doing, if at all possible. To be
more blunt, what you are wanting to do is not considered good
practice. So, make sure to include in your script's comments your
justification for not following good practice.
If we assume that there aren't any out-of-the-box methods for doing what I want (Spatial Query), then why would referencing a database function from Maximo be a bad practice?
(Bear in mind that I'm new to the IT industry. I would benefit from layman's terms.)
I can be a little verbose, so I'll apologize up front for that. And it may seem like I'm wandering, but I'll try to bring it back together at the end.
As I said in my answer to your first question, Take value from FieldA, send to db function, return value to FieldB, calling a stored procedure (or stored function or whatever) from an automation script is not "good" practice. That isn't to say, dogmatically, that it shouldn't ever be done, but to say that, as a rule, it should be avoided. When making an exception to the good practice rule is the best way to solve a particular problem, your code should document why you chose (or were forced) to make an exception. And I stand by that answer to your first question, which made no mention of a special circumstance.
If there are no out-of-the-box configuration options for doing what you want, such as crossovers or relationships or domains or etc in Maximo, then your next option should be in-product customization options (also known as "small 'c' customizations), if they exist. It so happens that in the case of Maximo you have "automation scripting" or "autoscripting" in Python or JavaScript, with all (Java) classes in the JVM's / server's classpath at your disposal (possibly including Maximo Spatial's Java class methods), for an in-product customization option. Using examples from Maximo 76 Scripting Features, you can even figure out how to call RESTful APIs, like those exposed by ESRI's ArcGIS, over HTTP or HTTPS.
If in-product (small "c") customizations don't work don't work well enough (such as causing performance problems), then it is generally acceptable, though not supportable, to customize the product itself (aka a big "C" customization). (Generally acceptable, as many companies would accept that rationale for developing a big "C" customization, but not supportable, as the vendor will ask you to remove your Customization and reproduce your problem if a problem is found and if it is at all conceivable that your Customization could be contributing to the problem in any way.) In the case of Maximo, writing your own Java classes or stored procedures are generally considered big "C" customizations.
In the case of Maximo, and you could probably generalize that to any COTS product, updating Maximo data from a stored procedure is considered exceptionally bad practice. This is because such updates are not subjected to Maximo's business rules and logic, which can lead to data integrity problems, support problems, and more. In particular, triggers often assume that Maximo has made database updates in a particular order (parent data being inserted before child data, for example) when its documentation explicitly disclaims commitment to such order. (If it doesn't anymore, it used to.)
All that in mind, if out of the box Maximo doesn't provide a configuration for doing what you need, and if you can't use autoscripting to do what you want, even with access to all of Maximo's and Java's libraries (in that order of preference), then it would be acceptable to use an automation script to call a database function to calculate a value for you to store via Maximo. In fact, in that scenario, calling a function from your script would be far better than having a trigger set the value, because, assuming you update Maximo via it's API, such as mbo.setValue("attribute","value"), your script will still leave the auditing, security, validation, data integrity, and other business rules in operation. As a bonus, any professional Maximo consultants (like me) you bring on to help with projects will waste less time (read: your money) trying to figure out what you are doing and why so they don't break it.
I hope that helps.
I am writing a REST API. However, one of the requirements is to allow the caller to determine if an action may be performed (so that, for example, a button can be enabled or disabled, etc.)
The action might not be allowed for several reasons - perhaps user permissions, but possibly because, for example, you can't delete a shared object, or you can't create an item with the same name as another item or an array of other business rules.
All the logic to determine if something can be deleted should be determined in the back end, but the front end must show this in the GUI.
I am trying to find the right pattern to use for this in REST, and am coming up a bit short. I could create a parallel API so for every entity endpoint there was an EntityPermissions endpoint, but that seems to be overkill. I could also do something like add an HTTP header that indicates that the request was only to check permisisons, not perform it, but that seems a bit dubious, and likely to mess up the http cache.
Can anyone point me to the common pattern for doing something like this? Does it have a name? Or a web page that discusses it? I'm sure everyone has their own ideas on this (like my dumb ideas) but I this seems to be a common enough requirement that I figure there must be a common pattern for it. But google didn't help much.
There's going to be multiple opinionated answers about this. I'll share mine. Might not be the best for your problem, but it's a valid solutions.
If you followed the real definition of REST, you would be building a hypermedia/HATEOAS-style webservice. Urls would not be hardcoded, they would be discovered and actions would be discovered by the existence of a link.
If an action may not be performed, you can just hide the link. If a user fetches the next resource they just see all the available actions right there.
A popular format for hypermedia API's is HAL. You might decorate the links further with more information from HTTP Link hints.
If this is the first time you heard of hypermedia API's, there might be a bit of a learning curve. The results of learning this can be very beneficial though.
I am new to programming and am trying to find some documentation on creating a GET REST API in php that can accept query paramters in the url. I have been looking for documentation and there seems to be a lot out there but not sure what I should focus on. I am looking for the API to take a url like this:
rest.php?format=json&action=courses
Once this url is posted I would like to make a query to my database to retreive the courses. When a url like this is make:
rest.php?format=json&action=students&course=id
I would like to query my database based on parameters set in the url. Can someone please point me in the right direction.
REST specifications are pretty vague in this regard.
However, if you have too many parameters then it is ok to have the method set as POST instead as per best practices.
There are many aspects that influence the way REST is implemented in the application. Totally depends upon the usecases and the way developer wants it to be, still there are certain REST Standards which will help you to keep your application adhere quality checks.
REST STANDARDS
Hope you can use this to relate to your scenario.
In the case of query params, they are usually recommended when you can take the risk of exposing the information and is usually used with GET calls. Instead you can use POST call and define the information in payload which can accommodate more data as well there is no risk of exposing information which you don't want.
Hope this clarifies the issue, if not please feel free to ask
Let's say we have a site where we have a list of items. On each of these items you can start a couple of different process that will result in somekind of output related to the item in question. How should you design for the most appropriate use of the http verbs? What I would like to have is multiple links per item and each link trigger one of the actions, but in my scenario that doesn't match the HTTP-VERB get, which will be used if I am using links. On the other hand, I don't want to have buttons which all are in a separate form with different actions.
It's somewhat hard to explain but hopefully you understand, it should be some best practices to apply here.
You should NOT use GET. GET requests should be safe which means they are intended only for information retrieval and should not change the state of the server. (i.e. things like logging are OK, but things that actually update the state of the application are a no-no.) Think of a crawler going over your application. Anything you wouldn't mind a crawler going through is fine for GET, but that doesn't sound like your situation (because you said, "start a couple of different processes", but I could be misinterpreting your use case).
That leaves PUT, DELETE and POST. PUT and DELETE must be idempotent, meaning that multiple identical requests should have the same effect as a single request. So if you had a request that updated a person's name, for example, if you called it once or 100 times, the person's name would still be the same, so it is idempotent.
POST is the most flexible verb. If the processes you are kicking off are not safe or idempotent (or even if they are) you can use POST, which simply doesn't guarantee anything about safety or idempotency. The disadvantages there are:
If you use POST when GET is more semantically correct, it is less communicative of the intent of your request, since POST usually means you are sending a payload.
You just couldn't take advantage of the web's caching infrastructure that makes it so scalable.
In the past, I have used POST with query args to specify custom actions. It made sense in my use case because I had a majority of custom actions needing to pass a payload. Since you do not want to use buttons, you can use GET with query args to specify the different actions, but you have to be very careful that the action you are taking does not have any side effects and is idempotent. As noted in the comment by #jhericks below, there are many things in the network that assume that GET's are safe and may repeat GET's.
From a pure RESTful perspective though, this is not ideal. Your items will have a specific URI and GET on the URI will return the items representation. Running actions on the item is effectively a change in the state of the item representation and that should be done with a POST(or a PUT depending on who you ask and if your web server supports PUT). In real life though, using query args is an easy work around and it may make sense to your use case.
Im not sure i fully understand your question.
But here's a quick paragraph which might help you.
REST is about making smart clients and simple servers. GET, PUT, DELETE represent the basic operations of file access at the lowest level. What you should be doing is completely ignoring anything the server can offer and be offloading that work onto clients.
So, the question is, why is the server being triggered to do many things. why can't the client do all of these things itself.
Mike Brown