Patterns when designing REST POST endpoint when resource has a computed property - api

I have a resource, as an example a 'book'.
I want to create a REST POST endpoint to allow consumers to create a new book.
However, some of the properties are required and computed by API, and others were actually taken as they are
Book
{
name,
color,
author # computed
}
Let's say the author is somehow calculated in API based on the book name.
I can think of these solutions each has its drawbacks:
enforce consumer to provide the author and just filter it (do not take into account as an input) # bad because it is very unpredictable why the author was changed
allow the user to provide author # same problem
do not allow the user to provide an author and show an exception if the user provides it
The last solution seems to be the most obvious one. The main problem I can see is that it is inconsistent and can be bizarre for consumers to see the author later on GET request.
I want my POST endpoint to be as expressive as possible. So the POST and GET data transfer objects will look almost the same.
Are there any simple, expressive, and predictable patterns to consider?

Personally I'm a big fan of using the same format for a GET request as well as a PUT.
This makes it possible for a client to do a GET request, add a property to the object they received and immediately PUT again. If your API and clients follow this pattern, it also means it can easily add new properties to GET requests and not break clients.
However, while this is a nice pattern I don't really think that same expectation exists at much for 'creation'. There's usually many things that make less less to require as a property when creating new items (think 'id' for example), so I usually:
Define a schema for PUT and GET.
Define a separate schema for POST that only contains the relevant properties for creation.
If users supply properties not in the schema, always error with a 422.

some of the properties are required and computed by API
Computed properties are neither required nor optional, by definition. No reason to ask consumers to pass such properties.
do not allow the user to provide an author and show an exception if the user provides it
Indeed, DTO should not contain author-property. Consumers can send over network whatever they want, however it is the responsibility of the API-provider to publish contract (DTO) for consumers to use properly. API-provider controls over what properties to consider, and no exception should be thrown, as the number of "bad" properties that can be sent by consumers is endless.
So the POST and GET data transfer objects will look almost the same
Making DTOs of the same resource look the same is not a goal. In many cases, get-operation exposes a lot more properties than post-operation for the same resource, especially when designing domain-driven APIs.
Are there any simple, expressive, and predictable patterns to consider?
If you want your API to express the fact that author is computed, you can have the following endpoints:
POST http://.../author-computed-books
GET http://.../books/1
Personally, I wouldn't implement that way since it does not look natural, however you can get the idea.

I want my POST endpoint to be as expressive as possible. So the POST
and GET data transfer objects will look almost the same.
Maybe just document it instead of relying explicit stuff like it must be almost the same as the GET endpoint.
E.g. my POST endpoint is POST /number "1011" and my GET endpoint is GET /number -> 11. If I don't document that I expect binary and I serve decimal, then nobody will know and they would guess for example decimal for both. Beyond documentation another way of doing this and to be more explicit is changing the response for GET to include the base {"base":10, value:"11"} or changing the GET endpoint GET /number/decimal -> 11.
As of the computed author I don't understand how you would compute it. I mean either a book is registered and the consumer shouldn't register it again or you don't know much about the author of it. If the latter, then you can guess e.g. based on google results for the title, but it will be a guess, not necessarily true. The same with consumer data, but at least that is what the consumers provided. There is no certainty. So for me it would be a complex property not just a primitive one if the source of the information matters. Something like "author": {name: "John Wayne", "source": "consumer/service"} normally it is complex too, because authors tend to have ids, names, other books, etc.
Another thought that if it is weird for the consumers instead of expected, then I have no idea why it is a feature at all. If author guessing is a service, then a possible solution is making the property mandatory and adding a guessing service GET /author?by-book-name={book-name}, so they can use the service if they want to. Or the same with a completely optional property. This way you give back the control to the consumers on whether they want to use this service or not.

Related

Differentiating between 404 types

I know the 404 vs 204 debate has been beaten to death, and I understand the argument for using 404 when there is no record in the table corresponding to a REST endpoint request, but it feels like there should be some way of differentiating between "This endpoint is malformed" and "there is no record in the table." For example if I have an endpoint like this:
https://mycloudfront.cloudfront.com/api/my-table/{userId}
Is there a recommended way of configuring error handling on the backend to differentiate between "no resource found because there is no entry for userId" and "no resource found because there is no table named my-table" or "no resource found because there is no cloudfront distribution named mycloudfront"?
I ask, because it would be nice on the frontend to inform the end user whether or not their request did not produce the desired result because they have no data in the table (in which case I would display a message encouraging them to take an action that would generate data) or because something went wrong (in which case I would display an error message).
it would be nice on the frontend to inform the end user whether or not their request did not produce the desired result because they have no data in the table
That's what the response body is for.
Except when responding to a HEAD request, the server SHOULD send a representation containing an explanation of the error situation, and whether it is a temporary or permanent condition. RFC 9110.
Status codes are metadata in the transfer-of-documents-over-a-network domain (Webber, 2011) - the information indicates to general purpose web components (browsers, proxies, caches, spiders....) the semantics (meaning) of the fields and response body (ex: does the message include a representation of a resource or a representation of an error?)
Bespoke HTTP message handlers (and human operators) are expected to look for information in the body (ex: a 404 for a web page returns a picture of a fail whale and a bunch of links to different resources that might clarify what's gone wrong).
You can also leverage ideas like web linking (RFC 8288), if you want to describe relationships between the error and other resources.
Problem Details (RFC 7807) describes a standardized JSON schema for communicating error information, if you want a JSON representation but prefer not to do all of the schema design yourself.
First and foremost, REST has no endpoints but resources.
there should be some way of differentiating between "This endpoint is malformed" and "there is no record in the table."
By "This endpoint is malformed" I guess you probably mean the request issued to the server doesn't conform to the HTTP specification. As voice already mentioned, HTTP status code are coordination metadata for the outcome of the transportation and not necessarily the outcome of your business logic. Of course you need to come up with a mapping for problems you noticed while applying your business logic to the HTTP transport domain.
Unfortunately, REST is polluted with false assumption and believes. Plenty of people seem to think of it as HTTP based CRUD mostly done with JSON payloads. But this is just a very tiny fraction of what REST really is. At its heart it is a technique used in distributed computing to help decouple clients from server to allow the latter to evolve freely in future. Clients on the other hand are build with the inherent design decision of a possible change in mind and therefore get much more robust towards change in the end.
So, how does REST help to decouple clients from servers?
First, the spelling of a URI is not of importance. The URI needs to be a valid one but that's it basically. Clients shouldn't parse the URI or try to extract some knowledge off the URI nor does a URI pattern like /api/user/1 and /api/user/1/stuff mean that both of those URIs are somehow related. That's what link-relations are there for.
Next, in order to teach a client what an URI returned by the server is good for URIs should come with one or multiple link-relation names, which should either be based on registered ones or at least follow the Web Linking extension mechanism, which basically is just a further URI that does not necessarily need to point to a valid resource. Treat it like a predicate in a (SemWeb) ontology.
Use forms similar to HTML, like HAL-forms, JsonForms or Ion, if your server needs further input from clients. Forms also teach clients on what HTTP methods to use, which URI to send the request to, what media-type to encode the request in and of course a description of the properties the resource has and/or the server expects input for. This information is enough to let a client send valid HTTP requests in terms of the transport domain to the server. Note that this does not mean that there won't be any issues then. Requests still might fail to reach the server due to internet outage on whatever end, the request being routed badly and exceed the maximum number of allowed hops and so on but depending on the HTTP method used for sending the request a client might automatically reissue a request once it hit its timeout threshold.
In order to increase interoperability of any peer in a REST ecosystem REST has a strong focus on media types. Think of it as the binding contract between a client and a server which should be negotiated between both of them. This guarantees that both are capable of exchanging "messages" both understand and are able to process. One of the difference to regular RPC services here though is that RPC services are usually restricted to one payload mechanism while REST supports more or less an unlimited amount of payloads, depending on its support for various media-types. Media types are a human-readable description on how payload should be encoded and processed and also contains information, besides the syntax description of allowed elements, a semantic description on the purpose of the respective elements. A payload issued for plain application/json doesn't teach a client really what the properties of the respective JSON objects used in the payload mean nor does it really support URIs in first place. Note however that issuing a plain JSON request to the server is fine if the client was "instructed" that way using a form the client was acting upon. The server here just expects that kind of payload then. Just look at how a typical HTML document is build up and read up on some of the tag definitions that are used within the HTML document and you might get the gist of this paragraph.
Especially about the latter two points Fielding himself was quite vocal about in his famous rant:
A REST API should spend almost all of its descriptive effort in defining the media type(s) used for representing resources and driving application state, or in defining extended relation names and/or hypertext-enabled mark-up for existing standard media types ...
So, back to the actual question at hand. Is "there is no record in the table" really a business logic error? You could also design it to return what's currently available there and return an empty list. This at least spare you the hazzle of mapping that business error onto the transportation domain in that case.
If you want or need to express a business logic failure to the client you should, as voice also recommended before, look into application/problem+json (or its XML alternative application/problem+xml) which define properties such as type of failure, general title, status and details among others. The respective type the response is issued for may define further properties specific to that type that are part of the payload. I.e. you may define an extension type of http://acme.com/problem/validation and this extension type defines that the payload needs to contain a target-ref property to identify the element that failed the validation check as well as a property for the actual error message.
In the end some general recommendations in terms of REST are:
Design the interactions of client and servers first as if you'd interact with a typical human-focused Web page and then translate the interaction steps onto the application domain. REST in the end is nothing more than a generalized approach for how we humans interact on the Web for decades. REST is basically Web surfing for applications rather than humans. As we humans follow an outlined state machine of i.e. Amazon.com to order some books, computers can do the same. Therefore design the whole interaction between client and server as state machine that clients just follow along and may exit at certain points
Allow servers to teach clients what they need to know using various form-support and use link-relations to set given URIs in context to the current resource

Akka.Net: Transparently Passing Along Contextual Information for Auditing/Authorization

Background
We have very strict auditing requirements and want to be able to correlate every action our system takes on behalf of the user to a specific authentication operation (sign-on). In addition to these strict auditing requirements, we also have some complex authorization requirements unsolvable by simple claims based authorization.
Considering both of these together led me to wondering the feasibility of using an 'envelope' type design, where messages sent stemming from a user request are wrapped in an envelope containing the necessary information, such as their auth token and info about the sending machine. Now, it would be fairly simple enough to add a property for this token to every message, but that seems tacky and since its a rather cross-cutting concern, I would rather it not pollute every protocol in the system, which is why I'm thinking the envelope idea is worth considering. This approach would also require the cooperation of every actor in the system and my goal is to have this be transparent to actors who don't need any of this information, but also make the information available in case actors do need it. In the case of actors needing it, it's also OK if they just accept the envelope type directly.
Imagined Solution
Overview
Wrap each Tell operation in an envelope used to transport required contextual information
Perhaps implemented w/ a custom actor ref provider and actor ref wrapping the ones configured
Unwrap envelope, if exists, on each receive operation
Custom mailbox
Would also handle sending a message to the auditing service
How to make the contextual information available to the actor?
Can we add to the actor's Context object somehow?
Also acceptable for actor to accept the envelope type/not use custom mailbox in this case
Discussion
In order to make this all transparent, my initial thinking is to 'intercept' the send/receive operations. I understand enough akka.net to implement a custom mailbox and I think this would be the way to go for this kind of approach, but I'm open to other ideas. The mailbox would perform the unwrap and make the contextual information available to the actor in case it's required (99% of the time it's not, likely better to just accept the envelope directly when it is required to be explicit). The mailbox would also handle fulfilling the auditing requirement by sending a message to the auditing service w/ the required information, which not only includes the contextual information from the request, but also local machine information to know where/who did the processing.
The part I'm second guessing myself on is intercepting the send operation (Tell). Since IActorRef instances are created via a configured IActorRefProvider and since this guy handles the Tell operation (via it's created IActorRef instances), I think it makes sense to write a custom IActorRefProvider and a custom IActorRef. Both would wrap the implementations that are configured (decorator pattern), and the custom IActorRef would provide the required behavior in it's Tell method. For webapi apps (only entry point for users), it would pull the required contextual information from HttpContext (one custom ref provider) and for backend apps (another custom ref provider), it would pull the required contextual information from the current message's context. I'm not sure how to add data to the actor's Context property, but I'm assuming it is possible.
With these two pieces in place, the contextual information would effectively be passed along, from actor to actor, and service to service. So even if a message is 20 actors down the line, if it was initially instigated by a user via the REST API, it would still have that contextual information, thereby allowing a full and complete audit and tracing of each action our system takes back to a specific sign on.
What I'm Hoping For
The primary thing I'm hoping for with this post is validation that this is a reasonable approach to take, and if not, why not and alternate suggestions for achieving the desired behavior. Also very welcomed would be any code samples for custom mailboxes/actor ref/actor ref providers and extra cookies if they're doing something similar to what I'm trying to accomplish here. Another welcomed tidbit is how to do the mailbox configuration so I don't need to manually update all of my Props with the custom mailbox implementation. Akka.net configuration is definitely a weaker point of mine, particularly the deployments section, so any core knowledge/articles/advice here is greatly appreciated!
Thanks for taking the time to read this! Any and all help is much appreciated!
Other StackOverflow Issues:
The answers provided in these issues require the cooperation of every actor. Ideally this is all transparent and actors that don't need to use this contextual information can be written as if it didn't exist.
Passing Contextual Information
How to elegantly log contextual information along with every message
There were a couple others I viewed [can't find them right now for some reason], but they all either required cooperation or global shared state [isn't that what akka avoids? :p]
Phobos, a proprietary observability library for Akka.NET, wraps all messages inside a distributed tracing context - which can be aggregated back together again in an off-the-shelf tracing system that supports OpenTracing, such as Jaeger / Zipkin / Azure Application Insights.
You can append custom data to each of the traces that are captured inside your actors via the Context.GetInstrumentation() method inside any of your actors' - custom data can include tags that might include a unique userId, a transaction Id, and so on. That's all part of the OpenTracing specification.
Disclosure: I work for Petabridge, the makers of Phobos. It's proprietary and costs money to use, but it's purpose built to offer this type of decentralized, but complete tracing out of the box.
Alternatively, if you didn't want to use Phobos you might be able to accomplish this using a custom messaging protocol for context propagation and structured logging with the Akka.Logger.Serilog library.

Can we pass parameters to HTTP DELETE api

I have an API that will delete a resource (DELETE /resources/{resourceId})
THE above API can only tell us to delete the resource. Now I want to extend the API for other use cases like taking a backup of that resource before deleting or delete other dependant resources of this resource etc.
I want to extend the delete API to this (DELETE /resources/{resourceId}?backupBeforeDelete=true...)
Is the above-mentioned extension API good/recommended?
According to the HTTP Specification, any HTTP message can bear an optional body and/or header part, which means, that you can control in your back-end - what to do (e.g. see what your server receives and conventionally perform your operation), in case of any HTTP Method; however, if you're talking about RESTful API design, DELETE, or any other operation should refer to REST API endpoint resource, which is mapped to controller's DELETE method, and server should then perform the operation, based on the logic in your method.
DELETE /resources/{resourceId} HTTP/1.1
should be OK.
Is the above-mentioned extension API good/recommended?
Probably not.
HTTP is (among other things) an agreement about message semantics: a uniform agreement about what the messages mean.
The basic goal is that, since everybody has the same understanding about what messages mean, we can use a lot of general purpose components (browsers, reverse proxies, etc).
When we start trying to finesse the messages in non standard ways, we lose the benefits of the common interface.
As far as DELETE is concerned, your use case runs into a problem, which is that HTTP does not define a parameterized DELETE.
The usual place to put parameters in an HTTP message is within the message body. Unfortunately...
A payload within a DELETE request message has no defined semantics; sending a payload body on a DELETE request might cause some existing implementations to reject the request
In other words, you can't count on general purpose components doing the right thing here, because the request body is out of bounds.
On the other hand
DELETE /resources/{resourceId}?backupBeforeDelete=true
This has the problem that general purpose components will not recognize that /resources/{resourceId}?backupBeforeDelete=true is the same resource as /resources/{resourceId}. The identifiers for the two are different, and messages sent to one are not understood to affect the other.
The right answer, for your use case, is to change your method token; the correct standard method for what you are trying to do here is POST
POST serves many useful purposes in HTTP, including the general purpose of “this action isn’t worth standardizing.” -- Fielding, 2009
You should use the "real" URI for the resource (the same one that is used in a GET request), and stick any parameters that you need into the payload.
POST /resources/{resourceId}
backupBeforeDelete=true
Assuming you are using POST for other "not worth standardizing" actions, there will need to be enough context in the request that the server can distinguish the different use cases. On the web, we would normally collect the parameters via an HTML form, the usual answer is to include a request token in the body
POST /resources/{resourceId}
action=delete&backupBeforeDelete=true
On the other hand, if you think you are working on an action that is worth standardizing, then the right thing to do is set to defining a new method token with the semantics that you want, and pushing for adoption
MAGIC_NEW_DELETE /resources/{resourceId}
backupBeforeDelete=true
This is, after all, where PATCH comes from; Dusseault et al recognized that patch semantics could be useful for all resources, created a document that described the semantics that they wanted, and shepherded that document through the standardization process.

some doubts related to REST API [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 2 years ago.
Improve this question
Can we say Like Rest API we have SOAP, XML RPC, JSON RPC, GRAPH QL I mean Rest is just a type of API?
Is Rest is just a mechanism to share data between applications by using HTTP methods?
REST can share data between applications only with HTTP there is no alternative?
What is the relation between REST & CRUD exactly? we are saying HTTP: POST is CRUD: CREATE my question is HTTP: POST will just post the data to server and it's business logic's headache to CREATE A NEW RESOURCE in the server side but how we all are saying HTTP: POST is nothing but CRUD: CREATE here HTTP: POST is just helping to share the data only right then how it is related to CRUD: CREATE? If that is the case we can create a new resource with HTTP: GET by writing business logic right then why so many sites are saying REST is a mechanism to do CRUD operations... But it should be REST is a mechanism to help in Sharing the data between applications right?!!! (I have doubt similarly with HTTP: DELETE, GET, PUT aswell)
Last but not least... what exactly Representational state transfer mean? could you please answer this with a very low level general answer instead of definition.
Can we say Like Rest API we have SOAP, XML RPC, JSON RPC, GRAPH QL I mean Rest is just a type of API?
REST stands for representation state transfer and is just an architectural style, not a technology or protocol. According to Robert C. "Uncle Bob" Martin an architecture is about intent and the intention behind REST is the decoupling of servers and clients in a distributed system.
REST basically just defines a set of constraints that when followed correctly allow servers to change at any time without breaking clients as clients will just depend on the data given by the server and not on any external data or documentation. REST can be regarded as Web surfing for applications. The main premise should always be that a server teaches a client on how certain things can be achieved.
On the Web a server can i.e. teach a client on the supported properties of a resource through the help of HTML forms. Not only does a client learn that way what a server expects as input, it also learns what HTTP operation should be used to send the data to the server, the endpoint URI to send the request to as well as, usually implicitly given, also the media type to convert the input to, which is application/x-www-form-urlencoded usually by default, which transforms an input like the HTML example below for first and lastname to something like this:
fName=Roman&lName=Vottner
Is Rest is just a mechanism to share data between applications by using HTTP methods?
REST itself is protocol agnostic meaning that it is not tide to HTTP itself and could just work on other transport protocols as well. Though the common perception many developers have is that it is based on HTTP. After all, as Jim Webber put it, HTTP is just a transport layer whose domain is the transfer of files or data over the Web. All HTTP does is to send one document from one machine to the next and any business rules we conclude from sending/receiving a request are just a side effect of the actual document management. It is therefore always better to think of a request as a whole document and the HTTP operation define how the document should be stored on the current machine, especially when such a document is already available, instead of thinking of a service method invocations. The latter one is a typical RPC view.
REST can share data between applications only with HTTP there is no alternative?
HTTP is just a transport layer used in a REST architecture. The architecture cares more on the interaction model between client and servers than on the technical nuances of HTTP. As REST itself is transport protocol agnostic it could be used with other, maybe proprietary protocols as well.
What is the relation between REST & CRUD exactly? we are saying HTTP: POST is CRUD: CREATE my question is HTTP: POST will just post the data to server and it's business logic's headache to CREATE A NEW RESOURCE in the server side but how we all are saying HTTP: POST is nothing but CRUD: CREATE here HTTP: POST is just helping to share the data only right then how it is related to CRUD: CREATE? If that is the case we can create a new resource with HTTP: GET by writing business logic right then why so many sites are saying REST is a mechanism to do CRUD operations... But it should be REST is a mechanism to help in Sharing the data between applications right?!!! (I have doubt similarly with HTTP: DELETE, GET, PUT aswell)
Fielding's thesis on the REST architecture style does not contain the term CRUD at all. The term REST nowadays is heavily misused as people probably didn't bother to actually read the thesis, which admittingly is a bit abstract, and just follow what some people thought may be REST but was actually RPC. Nowadays, if a typical stakeholder talks about REST they usually think of a JSON-based HTTP CRUD-API whose supported endpoints are defined in some Web documentation (Swagger, OpenAPI, ...) and where the HTTP operations for POST (= Create), GET (= Read), PUT (= Update), Delete (= Delete) are supported by default. However, this is unfortunately far from the truth. Though people are just to accustomed with their (wrong) definition and don't see or don't care about the actual problem in their misusage. They don't care about a long-lasting service as in 2-5 years the next-gen technology is here that allows to reduce the number of lines of codes even more and if a new "version" of a service is needed, this usually goes hand in hand with a technology switch also, to justify the "cost of change" somehow.
Last but not least... what exactly Representational state transfer mean? could you please answer this with a very low level general answer instead of definition.
Probably the easiest way to grasp how the interaction in a REST architecture should be is by analyzing typical interaction on the Web, the big cousin of REST. You, as a user, usually start by opening your browser (= client) and typing in some URL in the search bar. Next a Web page is rendered on your screen. Behind the curtain a couple of things happened. Besides the whole connection management and any eventual TLS handshake your browser sent at least one GET request to the target server. On sending the GET request, the client included information on his capabilities, i.e. through the Accept HTTP header. This header is used on the server side to decide which representation format to generate and send to the user. On the Web this might be something like text/html or application/xhtml+xml or if some report is generated might be something like application/pdf or application/vnd.ms-excel or the like, depending which representation format fit the data best.
The representation format itself is now a concrete instance of a document following a certain media type specification. I.e. the HTML forms specification defines the supported elements within a <form>...</form> tag pair as well as describes the semantics of each of the elements. The concrete instance may now define a form as such:
<form action="/action_page.php" method="get">
<label for="fname">First name:</label>
<input type="text" id="fname" name="fname"><br><br>
<label for="lname">Last name:</label>
<input type="text" id="lname" name="lname"><br><br>
<input type="submit" value="Submit">
</form>
which should only use elements and attributes defined within the specification else a receiver of that document might not be able to process it correctly.
This process of telling the server which document types a client supports and allowing the server to chose a fitting representation is called content type negotiation and allows the exchange of arbitrary, type-less documents. Of course, both parties need to support and understand at least one common media type to be able to interact with each other. This is similar to a Frenchmen who does not understand a word of Chinese and a Chinese one that does not understand any word of French who need to communicate (for whatever reason), if both speak English they will be able to communicate.
There are loads of different media types already available that all server different purposes. Depending on your needs an all-purpose one, such as text/html, might be sufficient, others such as application/json or even application/hal+json might though lack support for certain needed elements. Existing media types might not support needed elements. In such a case extending such media types and registering those is probably easier than creating a whole media type from scratch.
REST assumes that a resource (i.e. a remote document) contains some internal data, its state. This state can be represented in many different ways. Think of some monthly sails figures. You might ship the data either in a HTML table, as CSV data, as Excel file, as PDF or yet a different representation format. Regardless of the chosen media type to marshal the data in, the actual data at least should express the same. Instead of questioning which media type you want to support, you should better ask how many different ones you want to support as this just increases the likelihood that other clients may interact with your server also.
edit:
I got all the points except 4th point... Could you please elaborate a bit.. So is it just a mechanism that helps in sharing the data between applications by using HTTP methods? we can say like that?
CRUD is a typical term in the context of persistence, especially with databases. REST or more formally the REST architecture itself treats persistence as internal detail. A typical user usually does not care whether some data is persisted into a DB, a local file system or is kept just in memory. All s/he cares is that the server can process it or for storage services also return the same data that was sent to the server.
In regards to the mapping of CRUD to the HTTP operations, if you take a look at HTML you might see that it only supports POST and GET operations. So anything related to C, U or D are performed with POST which is defined to process the enclosed representation according to the resource's own semantic. With POST you are basically allowed to do anything, even retrieving data if you like.
However, HTTP defines certain properties for the respective operations:
safe
idempotent
cacheable
The first property is a promise to clients that a well-behaved server should not alter the state of a resource upon requesting. The second one is a promise in regards to automatic retry attempts caused by i.e. temporary connection issues. And the latter one allows clients to store responses locally and reuse these instead of requesting the same resource again, if the cached content is "fresh-enough".
GET and HEAD are both safe, idempotent and cacheable, meaning that a client can request resources with such an operation without being hold accountable for any eventual changes. Think of a Web spider that is invoking arbitrary URIs all the time to learn new pages over time. If a GET request on a URI would trigger an order of a Pizza or the like, it is basically the server's fault and not the clients one if a crawler would order Pizzas every time such URIs are called.
PUT and DELETE are only idempotent, which basically allows a client to automatically resend a request in case of a network issue as the outcome of the operation leads to the same result regardless whether the request was processed once or multiple times in a row. Note that this property does not consider changes done by other clients to that resource between a resend. Such data would of course be overwritten.
The remaining operations (POST, PATCH, CONNECT, TRACE) are neither of these.
While technically it is sufficient to only use POST for each request, the above mentioned properties should trigger an inner intention to use them, when appropriate. However, as before mentioned, not the client should chose which operation to perform but the server should tell a client which HTTP operation it should use.
In regards to POST vs. PUT, both operations should behave similar on creating a resource. Both need to add a Location header within the response that teaches a client about the location of the new resource. PUT however, in contrast to POST, replaces the current representation of the requested resource with the one provided in the request body. So it already targets the respective resource while for a POST request the server defines where the resource is created. It is allowed to perform certain sanity checks and also to transform the representation to fit the representation format of the current one. It is also allowed to have side effects, i.e. think of Git where a commit creates a new entry on top of the current branch and moves the HEAD to the new commit.
PUT is probably considered as update operation as the replacement of the document more or less has the effect of an update. If no representation was yet available this just has the effect of the creation (including the location header). In the past, unfortunately, many developers used PUT incorrectly by performing a partial update instead of really replacing the whole document. While the spec states that a partial update could be achieved by overlapping resources (i.e. share parts of the same data in multiple resources), the usage of PATCH, which also is used incorrectly most of the time, may be better from a performance standpoint on larger resources.
Due to POSTs definition, one can do anything with it, though historically a document upload in HTML was triggered through this operation that is basically a resource creation on the server side. That POST is used for many other things as well though is not that important for that CRUD paradigm.
In regards to your concerns about the right terminology, most people, according to my experience, simply do not care. They just want to get the job done ASAP and move on. As roughly 90% of the users seem to understand a pretty similar concept when talking about REST (even though this view is flawed) which usually resolves around JSON, HTTP, CRUD, Swagger/OpenAPI, ... they usually only look for quick-win-solutions and more or less agreement on their thought process.
As HTTP (0.9-1.1) is a plain text protocol sending a GET request is not much different from a POST or PUT request, so technically you can create resources with GET request or support payloads on GET requests (semantics of the payload is undefined according to the spec). That's why I mentioned well-behaved client/servers above. In such a case, however, due to the safe property of GET, if you as a server maintainer violate the HTTP protocol you are the one to blame in case something "unexpected" is happening (crawler is ordering 500 Pizzas).

WCF service design question

Is it ok from your real-world-experience to define service contract with one method which will accept some object as a form of request and return some other object as a result of that request. What I mean is instead of having method for creating, deleting, editing and searching customers I would have these activities encapsulated within DataContracts and what service would do after receiving such DataContract would be take some action accordingly. But service interface would be simple as that:
interface ISomeService
{
IMessageResult Process(IMessageRequest msg);
}
So IMessageRequest would have filed named OperationType = OperationTypes.CreateCustomer and rest of fields would provide enough information for the service that it could create Customer object or record in database or whatever. And IMessageResult could have field with some code for indication that customer was created or not.
What I'm trying to achieve by such design is an ability to easy delegate IMessageRequest to other internal services that client side wouldn't even know about. Another benefit I see is that if we will have to add some operation on customers we only provide additional DataContract for this operation and don't have to change anything on service interface side (I want to avoid this at all costs, I mean not new operations but changing service interface :)
So, what do you think? Is it good way of handling complicated business processes? What are pitfals, what could be better.
If I duplicated some other thread and there are some answers to my question please provide me with links because I didn't find them.
Short answer: yes, this could be a very good idea (and one I have implemented in one form or another a couple of times).
A good starting point for this type of approach are the posts by Davy Brion on what he calls the request/response layer. He consolidated his initial ideas & thoughts into a very usable OSS project called Agatha, which I am proposing at a customer site as I write this.
This is exactly what we're doing here where I work. It works great and is easy for all the developers to understand, and really easy to wire up new methods/class/etc.