Wonder how people implement the subj?
Suppose I've no javascript. What URL should bring me to a page for
dangerous operation confirmation?
TIA,
--
Vladimir
Confirmation is a process that is not fully compatible with (pure) REST,
because requests must not be dependent of previous ones. I use DELETE to
actually remove/delete a resource, but exclusively using javascript GUIs
-- having, then a separation between GUI "resources" (html etc forms)
and JSON resources which is data that goes to and from the GUIs.
But if you need one, think of it as a "Deletion resource". POST to
create a "deletion resource". The response is a form containing a nonce
token, has status 201 created and the URI to the new "resource" is
either given through Location header or in the body of response -- the
body which is then a form, containing nonce hidden field and primed for
a DELETE operation, and a button asking to "Confirm".
Perhaps an overkill, but my point is in paradigm shift between "actions"
and restful "resources".
Vlad
Sorry, I hit Reply too fast.
Continuing on what I previously said, the URI can be the same. REST uris
are opaque, have no meaning other than being a location for a resource.
So if you had
/importantdocument/123
You can POST to, for example, /importantdocument/123/delete or
/importantdocument/123?delete=1, to create the "deletion resource",
then DELETE to /importantdocument/123
Vlad
On 01/29/2010 02:39 PM, Vladimir Dronnikov wrote:
But wonder if the same effect can be achieved more reliably (and
elegantly) by means of some kind of guarding decorators applied to
potentially dangerous (mostly destructive) methods?
We have such decorators for authentication/authorization purpose. Have
anyone seen such for confirmation problem?
The rationale here is to help powerful authenticated user not to
execute "# rm -rf /" with one click :)
Regards,
--
Vladimir
That's what I did, only I used:
member={"ask_delete": "GET"}
I think this should be added to Routes. Delete confirmation is
necessary in many interactive applications.
> and redirected my 'Delete' links to this method.
>
> But wonder if the same effect can be achieved more reliably (and
> elegantly) by means of some kind of guarding decorators applied to
> potentially dangerous (mostly destructive) methods?
>
> We have such decorators for authentication/authorization purpose. Have
> anyone seen such for confirmation problem?
Interactive users won't get to the delete action except through the
form. They can't enter it directly into the URL box because that
always produces a GET. Non-interactive agents are accustomed to
producing 'DELETE' requests directly, and wouldn't know what to do
with a form anyway.
You can undoubtedly simulate a confirmation with a decorator, but just
adding a GET URL with a form seems more straightforward.
You can't double up the confirmation form and the delete action on the
same URL, at least not with REST, because GET'ting the same URL
displays the record. So you have to use a different URL for the
confirmation form.
Or you can use Javascript to display a confirmation alert dialog.
That's a kind of "decorator". But it would be bypassed in non-visual
browsers or if Javascript is disabled.
I don't understand Vlad's point:
> Confirmation is a process that is not fully compatible with (pure) REST,
because requests must not be dependent of previous ones.
> But if you need one, think of it as a "Deletion resource". POST to
create a "deletion resource". The response is a form containing a nonce
token, ...
A pure REST client would not use the confirmation, it would just
DELETE the resource directly. The confirmation step, if any, would be
built into the client itself. But there's nothing wrong with adding
additional GET URLs to resources. That's just asking the resource to
show a different "view" of itself. And if the view happens to contain
a form that submits a delete action, so what?
--
Mike Orr <slugg...@gmail.com>
You definitely got me right, Mike.
> Delete confirmation is necessary in many interactive applications.
>>
>> We have such decorators for authentication/authorization purpose. Have
>> anyone seen such for confirmation problem?
>
> Interactive users won't get to the delete action except through the
> form. They can't enter it directly into the URL box because that
> always produces a GET. Non-interactive agents are accustomed to
> producing 'DELETE' requests directly, and wouldn't know what to do
> with a form anyway.
>
That is correct when users are good. Unfortunately, there exist
malicious ones, plus bots.
> You can undoubtedly simulate a confirmation with a decorator, but just
> adding a GET URL with a form seems more straightforward.
>
Confirmation by preliminary GET is _volunteer_. That is the problem
I'm trying to outline.
When confirmation is decorator, even authenticated user _has to_
interact. Consider this as a flavor of CAPTCHA.
(BTW, who can share experience in pylons+captcha?).
>
> Or you can use Javascript to display a confirmation alert dialog.
> That's a kind of "decorator". But it would be bypassed in non-visual
> browsers or if Javascript is disabled.
>
Plus if someone want to bypass it express.
> I don't understand Vlad's point:
>
>> Confirmation is a process that is not fully compatible with (pure) REST,
> because requests must not be dependent of previous ones.
> ...
I think he meant here "(pure) REST must be stateless".
>> ...But if you need one, think of it as a "Deletion resource". POST to
> create a "deletion resource". The response is a form containing a nonce
> token, ...
>
May be "Server-side has a separate queue for queries-for-deletion; to
push such a query, a request should be made as POST <URI>/delete"?
> But there's nothing wrong with adding additional GET URLs to resources.
Of course. A thought has just come: I'd map GET <URI>/delete to
"confirm delete?" and DELETE <URI> to "do delete".
This IMHO looks quite reasonable for standard routes.
> That's just asking the resource to
> show a different "view" of itself.
>
Yes. And to follow DRY principle for confirmation I reuse "show"
template prepended by "Want to delete this record?" and followed by
<form> with delete method.
--
Vladimir
Indeed, but Vladimir's question was without Javascript. It is my belief
that "proper" REST is impossible without javascript because HTML does
not specify anything other than the URL in links. Additionally forms set
the method, but that's about it (plus cookies handled automatically by
the browser).
Therefore I like to separate (Javascript powered) GUI resources from
data resources.
However my suggestion stems from the fact that REST is an architecture,
not a protocol like for example a SOA implementation. And that
architecture requires resources with (original) URIs. Therefore any SOA
implementation can be easily translated to REST if proper resources were
defined. My suggestion was to observe the deletion confirmation as an
additional resource created exclusively for a resource to be deleted.
Naturally, "pure" stateless REST is impossible in practice, if nothing
then because of security considerations. But statelessnes is a
requirement, I would dare say "prescribed" solely because of
scalability. However, traditional "sessions" are not necessarily
unscalable, especially if using a clustered memcached solution. Still,
that depends on the kind of state. Is it application state that is
tracked through sessions, or temporary state of data which can still
allow independent requests? I believe the latter can be perfectly in
line with pure REST.
Alternatively to the "deletion resources", given that REST is all about
transfer of state, the resource to be deleted can be modifed by PUT to
mark itself deletable, then deleted in any of the subsequent, yet
conceptually independent, requests. Personally, I find GET-ing the
confirmation form is in fact simulating a SOA implementation which
breaks pure REST because two adjacent request are dependent.
Vlad
Precisely my point. That or using PUT to alter the state of the document
to deletable, before actual DELETE is issued.
Vlad
To say the truth, I'd even prohibit use of DELETE to actually delete
smth. Deletion is way dangerous operation. Especially when cascading
is on.
When I have more time, I'll dive into versioned storage deep. And (at
first glance) even the following scheme might help: PUT a flag to
<URI> (or just PUT <URI>/delete) marks an object as a candidate for
garbage collector; SQL queries should respect this fact by filtering
out marked records; a time comes and the record is moved to archive
table).
--
Vladimir
While I agree that deletion is a dangerous operation, how dangerous
depending on the data being deleted, I disagree on prohibiting it. In
fact, I believe it is saner to use that verb over POST or gods forbid --
GET (which is, unfortunately, not uncommon)!
Why? Because it is a distinct verb. No doubt about its purpose. The
alternative is to pass a flag through POST which can lead to sloppy
design especially if POST accepts also creation and/or alteration of
data. Complex controller code only increases probability of mistake. I
don't even want to begin a rant on delete via GET.
You mention cascading. I assume foreign key cascading in the db? One of
the mistakes when doing REST is to consider the transactions in the
scope or sense of a database transaction. They are not the same.
However, delete should not be dangerous if you know what you're doing.
Mapping the action to the DELETE verb only facilitates the attention:
there's no doubt about what the action should do, so you proceed with
safeguards. You don't do IFs and IFNOts, checking extra flags to see
what the action might additionally mean (unless it is to represent a
condition of delete, but nothing else).
Additionally, having a "deletion resource" or queue, or marking subject
for deletion before actual deletion is something that can be perfectly
handled by stored procedures and table/row triggers: no soup for you if
the flag/deletion resource is missing! That way you can't even
"accidentally" go to the SQL prompt and to DELETE whatever FROM
wherever, because the trigger would prevent deletion without proper
flag/resource set. Gods forbid that you forget a where clause. :)
Vlad
I don't mind the verb. The statement was "I'd forbid to delete
anything. Better is to just lay the object aside".
> You mention cascading. I assume foreign key cascading in the db? One of
> the mistakes when doing REST is to consider the transactions in the
> scope or sense of a database transaction.
When one operation (paying a bill, say, PUT <>(amount=1)) depend on
another (counting the saldo, GET <>/saldo), the whole scheme becomes
rather synchronous -- thus transactions -- and they heavily resemble
database's ones.
> They are not the same.
Definitely. Databases are optional.
> However, delete should not be dangerous if you know what you're doing.
> Mapping the action to the DELETE verb only facilitates the attention:
> there's no doubt about what the action should do, so you proceed with
> safeguards. You don't do IFs and IFNOts, checking extra flags to see
> what the action might additionally mean (unless it is to represent a
> condition of delete, but nothing else).
>
> Additionally, having a "deletion resource" or queue, or marking subject
> for deletion before actual deletion is something that can be perfectly
> handled by stored procedures and table/row triggers: no soup for you if
> the flag/deletion resource is missing! That way you can't even
> "accidentally" go to the SQL prompt and to DELETE whatever FROM
> wherever, because the trigger would prevent deletion without proper
> flag/resource set. Gods forbid that you forget a where clause. :)
>
Right. But real applications rarely do delete something. Besides, the
real world doesn't cascade.
--
Vladimir
Agreed, though a RESTful transaction would be something like the
proposed "Reliable HTTP" where the client can be sure whether the
operation was completed or not.
> Right. But real applications rarely do delete something. Besides, the
> real world doesn't cascade.
>
Content management systems should have deletion available. Though I
agree, better mark it unavailable, or move to an archive table than
actually remove the resource.
I don't quite understand what you mean by the real world not cascading?
Vlad
Beware of the RESTafarians. REST solves a certain set of problems,
and its best realization seems to be ATOM. But the "don't use cookies
or sessions" argument fails to provide alternatives for logging in or
restricted access, and makes result sets needlessly cumbersome. You
end up putting the result ID (which is really a kind of session ID) in
the URL. Or you transmit the whole data to the client and back through
request variables, which is unfeasable with large data sets. And it's
impossible if the client shouldn't actually see the raw data. And
having random result IDs still doesn't answer the question of whether
the current request should have access to that result set. So
complete statelessness is impossible or at least unreasonably
cumbersome.
I also notice that all of the most popular social networks abuse query
strings horribly, worse than any of us would ever do, yet that hasn't
caused the sites to crash or their users to boycott them because their
URLs are bad. So REST is not necessary to make the world go round and
the sun come up.
Still, REST is a good ideal, and it's worth moving closer to it when
feasable. But its biggest advantage is for noninteractive clients
which don't want to know the particular site's idiosyncracies. Its
benefit to interactive sites is less certain, especially those that
are heavy on user accounts, result sets, and shopping carts.
--
Mike Orr <slugg...@gmail.com>
More generally, a request activates a temporary "permission to delete
this resource" flag. This will be necessary for some cases. It's not
RESTful. But the two requirements are contradictory, so one will have
to supercede. Either it's acceptable to delete the resource at any
time (without confirmation), or it's not. If it is, a simple DELETE
action is sufficient. If not, the delete has to be protected behind a
confirmation or nonce.
--
Mike Orr <slugg...@gmail.com>
The sessions argument is often misunderstood, imho. The way I see it,
Fielding proposed it as a guide primarily to allow scalability.
Conveying as much information as possible into the HTTP protocol itself
-- as opposed to application protocol present in the request content --
is actually beneficial on many levels, for example it allows data
partitioning on the HTTP layer, before the request even reaches the
application for processing. Which, in turn, facilitates scalability.
However cookies are part of HTTP. They do not necessarily contain
application state. A session, for that matter, need not contain
application state, but client state validated server-side. Or temporary
state of data behind "regular" URIs. In short: it's a matter of how you
observe it.
Traditionally, session data is kept in files local to the server. That
is not scalable, I agree. But move it to a memcached cluster and it
becomes scalable. And at that point, it becomes no different than the
"regular" data behind URIs, which is, in order to be scalable, also in a
distributed storage container, a.k.a a database cluster.
If scalability is the only concern, then, the session data observed as
temporary resources which only particular clients should interact with
is fully RESTful. If purism and strict following of Fielding's rules is
of concern, then RESTful application can never be anything other than
simple public services where security is not an issue.
> I also notice that all of the most popular social networks abuse query
> strings horribly, worse than any of us would ever do, yet that hasn't
> caused the sites to crash or their users to boycott them because their
> URLs are bad. So REST is not necessary to make the world go round and
> the sun come up.
>
In REST the URIs are "opaque", as they say. That means that the URI has
no meaning to the client other than being a unique ID for a resource. It
can be called /page/view/123, or /asdkjh45kua8kr. The theory here states
that resources should link between themselves. A "pure" RESTful client
should not have to know how to construct the URI, but the result set
should contain enough URIs for it to function properly.
When the client creates a resource, the RESTful response should say 201
and provide a link to it, not just the primary key for client to
construct the link. And that satisfies the "self-descriptiveness"
requirement of REST. With that, any client that understands HTTP can
come along, create a resource and will understand what 201 + Location
means, because it is inherent to HTTP.
REST makes a point here that apps should not reinvent the wheel with a
protocol built additionally to the HTTP itself, if HTTP itself can carry
out the action. I agree with the not inventing the wheel thing, but I
also understand there are situations where you can't just follow "pure"
REST.
> Still, REST is a good ideal, and it's worth moving closer to it when
> feasable. But its biggest advantage is for noninteractive clients
> which don't want to know the particular site's idiosyncracies. Its
> benefit to interactive sites is less certain, especially those that
> are heavy on user accounts, result sets, and shopping carts.
>
Agreed. :)
Vlad
I feel compelled to say after reading this entire thread that this
doesn't have to be unRESTful. REST doesn't mean sticking slavishly to
ATOM - isn't workflow via hyperlinks what HATEOAS is all about?
Regards,
Mike
m...@asplake.co.uk
http://positiveincline.com
On Jan 29, 9:33 pm, Mike Orr <sluggos...@gmail.com> wrote:
> On Fri, Jan 29, 2010 at 10:18 AM, Vladimir Dronnikov
>
> Mike Orr <sluggos...@gmail.com>
I agree with putting resource IDs into the URL rather than query
parameters as much as possible. That's what I meant about social
networks abusing query parameters.
/photos.php?imageid=123&friendid=456&someotherid=789&sort=alpha&start=144
> In REST the URIs are "opaque", as they say. That means that the URI has
> no meaning to the client other than being a unique ID for a resource. It
> can be called /page/view/123, or /asdkjh45kua8kr.
Well, from a machine point of view, OK. But I also think URLs should
be human readable, and each component should contain the one on its
right. I got those ideas from the REST literature.
--
Mike Orr <slugg...@gmail.com>
Suppose A buys B manufactured by C. When A or C go out of scope (die,
e.g.), it doesn't mean the end of B, right?
--
Vladimir
It all depends on what the resource is. Often with /A/B/C, C is a
logical subcategory of B, and B of A. So if B ceases to exist, all C's
disappear too.
I would not necessarily assume that database cascading is related to
URL cascading. It's up to the client to determine whether to delete
that particular resource. It's up to the server to determine whether
it should also cascade to delete some other resources too.
I have applications where the client is never allowed to delete
anything because it's meant to be a permanent record. And others where
the client can't create or delete, but only edit, because all creation
is done offline.
map.resources (and I guess REST/Atom) assume you can always create and
delete anything at any time, unless you get a forbidden error. So
that's another thing I'd like to add to it, suppressing certain
actions.
--
Mike Orr <slugg...@gmail.com>
Hmm. Consider Toyota has manufactured a dozen of certain cars. I
_hardly_ imagine if Toyota drops (ever:) those dozen of cars will
_immediately_ disappear too.
Personally, I think cascade-on-deletion is just a convenient way to
simplify sql queries which otherwise should constantly be aware of
possible NULL dereferences. So cascade-on-deletion is totally due to
sql misfeature in this area.
In contrary, cascade-on-update has applied sense, since no object
ceases due to this operation.
--
Vladimir
Consider a site of incidents (i.e., situations you're responding to or
have responded to) containing entries (reports of specific things
you've done, photos, etc). Deleting an entry should not affect the
incident. But deleting the incident should delete all entries because
they refer to an incident which doesn't exist, one which you've
specifically said you don't care about.
--
Mike Orr <slugg...@gmail.com>
On 01/30/2010 04:43 PM, Vladimir Dronnikov wrote:
> Personally, I think cascade-on-deletion is just a convenient way to
> simplify sql queries which otherwise should constantly be aware of
> possible NULL dereferences. So cascade-on-deletion is totally due to
> sql misfeature in this area.
>
It's not a misfeature, it's a requirement for normalized datasets where
orphans should not exist. Note the keyword here is normalized dataset,
which requires relations between tables. So it is a consequence of a set
rules in a given system: B should exist only if A exists. And in order
for the system to work properly, cascades should occur. The system here
is a database, and the rule is Informational Integrity.
All this, however, is perhaps specific to information technologies and
hardly translated into macro world of physical, or in your example with
the cars. Though there is cascade on certain levels even on physical
world. Your car will "die" (in time) if the buyer disappears so there's
no one to take care of it, or the manufacturer disappears and there's no
more support (no spare parts). But if you say that other manufacturers
and auto shops can pick up the support, so can database rows, if rules
require or allow it.
On the quantum level, there is cascade with entangled pairs. Update or
delete one, the other will respond equally.
However your analogy is wrong because the system of ABC does not require
the same set of rules. If it did require, let's say in form of a law
that said all cars should be destroyed if their manufacturer
disappeared, then it would cascade also, because the rule of the system
says so. Another example: DRM. If the certificate issuer disappears, you
can't view DRM'ed content.
Vlad
Again, deleting an incident has no sense (in applied world) since the
incident _has_ _physically_ occured!
In your example the incident with all related stuff should be marked
'archived' and thus go out of scope.
Of course, in _sql world_ the above technique is best implemented as
DELETE ... CASCADE.
That's the point, IMHO.
--
Vladimir
And all the above is theory. Humans just need to stick to Aristotle'
logic, or they start to melt.
> All this, however, is perhaps specific to information technologies and
> hardly translated into macro world of physical, or in your example with
> the cars. Though there is cascade on certain levels even on physical
> world. Your car will "die" (in time) if the buyer disappears so there's
> no one to take care of it, or the manufacturer disappears and there's no
> more support (no spare parts). But if you say that other manufacturers
> and auto shops can pick up the support, so can database rows, if rules
> require or allow it.
>
> On the quantum level, there is cascade with entangled pairs. Update or
> delete one, the other will respond equally.
So states the _proven_ physical law. No artificial cascading here just
for convenience. (However, who knows, may be the higher "ratio" thinks
in sql terms? :)
>
> However your analogy is wrong because the system of ABC does not require
> the same set of rules. If it did require, let's say in form of a law
> that said all cars should be destroyed if their manufacturer
> disappeared, then it would cascade also, because the rule of the system
> says so.
Of course, if "it did require". But it didn't. So here we again try to
impose a pure artificial constraint just to keep dataset normalized
and thus to stick to a convenient model.
> Another example: DRM. If the certificate issuer disappears, you
> can't view DRM'ed content.
... which pretty certainly doesn't mean the content itself _does_ disappear too.
.
I'd like to ask you what exact response codes which CRUD operations
should return in REST? How good the codes other than 200 is supported
(in sense of considering them as success) by jQuery?
TIA,
--
Vladimir
It's not just theory. It is a consequence of a system with rules. Humans
also live in a system with rules and must obey them, like it or not.
Even the greatest anarchist will eventually succumb to the rules imposed
by Entropy.
So if a rule says B should disappear when A does, it is a normal state
for the system obeying those rules. The rules, however, may be imposed
by nature or man, the principle remains.
> So states the _proven_ physical law. No artificial cascading here just
> for convenience. (However, who knows, may be the higher "ratio" thinks
> in sql terms? :)
>
Cascading on a foreign key is not a "convenience", it is a rule of
normalized relational dataset that requires informational integrity.
Whether it is "artificial" or not depends on the interpretation of
artificial.
If you do not require informational integrity then you will design your
system with no foreign keys. You can also bunch everything in a single
table and forget normalization. And therefore no relations and no
cascades. It all depends on the desires of the programmer or DBA.
Similarly with a file system. You can have indices that point where
files and corresponding sectors are. They are convenience because
without them the application would have to scan entire disc to find its
files. But a FAT table is not a convenience. It is a relation between
position of a "file" and its data on disc. Without it, the application
cannot find its data because there is no pointer to it. This is a
relation not unlike foreign keys.
That the data is not deleted when the file (pointer) is is just a matter
of performance. Secure systems that require deletion of data will delete
both the pointer and the data because it is normal operation within the
rules of the system. Nothing artificial there, just the requirements of
a system.
> Of course, if "it did require". But it didn't. So here we again try to
> impose a pure artificial constraint just to keep dataset normalized
> and thus to stick to a convenient model.
>
You can build tables with no foreign keys and therefore no cascades. The
cascades are only there if you impose a set of rules on your tables. And
it is only as artificial as the entire IT concept: namely, nature didn't
build them, we did. Machines understand only binary. It is the dev who
gives meaning to the data and hence imposes rules so the machine can
understand the relations.
It all boils down to the rules saying: I have two tables, their rows are
related. If a row in table A is gone, the corresponding row in table B
should too. Why? Because the designer of the system sees a meaning that
the machine does not. If the machine were an AI it would probably delete
row B without the program telling it to cascade, because the machine
understood the relation (after learning of one).
Machines of nature work similarly. A simple rule says that the cell
needs power. So it happens that in the evolutionary dataset one
important relation emerged: that between mitochondria (A) and the cell
(B). It says that A provides power for B. Another rule says if there's
no A, B dies. The underlaying hardware (pure atoms and molecules)
couldn't care less and see the relation as "artificial", from their
point of view, because they don't "understand" the relation.
And if you really want to get philosophical (and I see I've gone that
way already, heh), I recommend: http://arxiv.org/abs/0801.0337 :)))
> ... which pretty certainly doesn't mean the content itself _does_ disappear too.
>
Given strong enough encryption it is as good as dead. A file with random
bits, for all that anyone without the key cares.
Vlad
Well, the only case where deletions occur is when the incident should
not have been there in the first place or is a duplicate of another
record.
--
Mike Orr <slugg...@gmail.com>