RESTful / Crud based approach to controlling an entity behavior that is typically implicit - api

I am modifying a CakePHP application to have an API available on it. My intention is to try to keep keep the endpoints as close to being RESTful / Crud oriented as possible. Although I have a use case that that I am unsure of.
I have the following requests for adding and editing tasks:
PUT /tasks
PATCH /tasks/:id
One of the behaviors of task entity in the system I am working on is that they send emails to the effected users associated with the task, when a save or edit is performed. This allows the various parties surrounding the task to be updated on the status of the particular task.
However the the one issue is that in some uncommon cases the end user will need to be able to toggle if they want an email to be sent on the front end.
What is the proper RESTful / Crud oriented approach to flag the task endpoints to not fire the email in the API request?
There is no record of the email in the application's database and it is nice to have to functionality tied into the task life cycle hooks and called implicitly. So I am not crazy about doing something like creating an /emailTask set of endpoints. It seems like an optional flag in the task request would be cleaner, but might not be maintainable if we begin to have similar needs for other behaviors associated with tasks.
Thanks in advance for the help!

PUT /tasks
If you're intending to use this for adding tasks, use POST instead. PUT /tasks implies that you are overwriting all tasks.
As for side-effects, this to me feels like a decent use-case for a custom HTTP header. Perhaps something like Suppress-Notifications: ?1 ?
Why ?1 as a value? This is going to be the future default for new HTTP headers that specify a boolean:
https://datatracker.ietf.org/doc/html/draft-ietf-httpbis-header-structure-15#section-4.1.9

Related

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

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.

PUT or PATCH when user can modify either partially or completely?

Let's imagine I have an application where users can either completely, or partially, update their profile details in one part of the app.
PUT for all requests
a PUT (for complete updates) and PATCH (for partial updates) for the requests
In the second scenario I could let the frontend decide whether the full or just a part of the profile was updated. However, this would involve both more code on both the front- and backend.
The first method is on the other hand "easier" to implement. However, is it against certain REST specs / principles?
is it against certain REST specs / principles?
It depends on how you mean it.
If you are thinking "all profile changes are performed by sending a complete replacement of the profile resource via an HTTP PUT", then yes, that is aligned with REST principles (specifically, it respects the uniform interface constraint -- you are using the HTTP PUT message the same way it is used everywhere else, which means that general purpose clients can interface with your resources).
On the other hand, if, instead of the complete replacement, you are considering sending a partial replacement via HTTP PUT, then that is not consistent with REST principles (because you are deviating from the standardized semantics of HTTP PUT).
If HTTP had a standardized "partial PUT" method, using this hypothetical method would be consistent with REST principles.
In other words, REST doesn't really say anything about what messages should be included in the "uniform interface". It just says that everybody should use those messages the same way. It's the HTTP standard that says PUT means complete replacement.

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.

developing your own RESTful API

in developing your own RESTful API. does it necessarilly needed to use the four different http methods? GET POST PUT & DELETE?
i was checking the Twitter REST API and saw that they are just using the common methods (GET & POST)
Short answer: No
Long Answer:
REST is not specific to any one protocol, instead it is a style of programming. This is helpful to keep in mind because a RESTful endpoint should be thought of as having specific goals. Your job is to expose the web service in the most RESTful way possible.
When you're making a RESTful API you are not required to use any specific HTTP methods. Instead, REST can be embodied in this guiding principal: That you must expose individually identifiable resources; these resources must be manipulable in their exposed form. Oh and use self descriptive messages.
I'm sure this is a leaky explanation. Try to see, though, that REST becomes much more clear when you have the key idea in mind. RESTful practices expose resources in a way that allows us work with state in a sane manner. The technical details of how to implement a RESTful API can be learned by reading this:
http://en.wikipedia.org/wiki/Representational_state_transfer
After that, read something specific to your language. Fast track: find some RESTful API written in your language and clone it/play with it.
You should use whatever HTTP methods are appropriate for the operations you expose.
For example, you should accept HTTP DELETE requests only for operations that delete things.
If your API does not allow callers to delete things (eg, a traffic or weather API), you should not accept the DELETE verb.
Only if you are going to support those logical operations:
GET - fetch a resource
PUT - update (or create) a resource
DELETE - delete a resource
POST - several uses: create a new resource in a collection, perform some operation that will alter a resource in some one (as opposed to PUTting an entirely new version of a resource)
Most APIs will want to to provide those operations, and will use all those methods. And don't forget HEAD - fetch information about a resource (but not the resource itself).