[thelist] Dealing with double-postings

Bill Moseley moseley at hank.org
Fri Sep 22 08:41:38 CDT 2006

Old topic, but I have an application where (so far) one person
reported some odd behavior.  Looking at the logs I could see that
many of their POST requests were submitted twice at the same time.

That odd behavior makes sense in that context -- they were seeing the
results in their browser of the second post.

The basic problem is, for someone that manages to double-post, to show
them the output from their first post.  So, I'm asking for a sanity
check with an idea below.  Sorry for the length of this message. ;)

I'm not able to easily reproduce the double-posts.   In Firefox I can
click + <escape> + click and generate two requests, but simply
double-clicking on a submit button or image doesn't work.  But perhaps
that user's version of IE produces two requests by double-clicking.

Anyway, my application already uses a unique token on each form so
reloading a form (reposting) is detected and the user will see "Did
you already submit this form?" kind of message.

Unfortunately, due to how my sessions are maintained, the test and
invalidation of the token is not atomic, so it's possible for two
POSTs to slip in.  That's still not a problem for my application as
the second post will tend to generate an error where it's important
that only one post happens.

The "problem" is, as was in the case of the person above, if they do
manage to do a double-post the first post completes the transaction
but in their browser they only see a message that the second post

My questions:

In the past I've used Javascript to disable the form after posting.
It does not solve the problem, but can help.  Anyone doing this in
production and has an example of cross-platform javascript to share?

Assuming I update my token system to avoid the race condition, I
still have the problem of someone not seeing the result of their
first post's output.

How crazy would it be to store the generated page from the first post
and then return it in any later posts using the same token?

That is:

    create table form_token (
        id              serial primary key,
        sessionid       text,  -- don't allow "token hijacking"
        valid           boolean not null default true,
        created_time    timestamp with time zone default now(),
        page_content    text


Then when a form is posted do:

    update form_token set valid = FALSE where id = ? and valid = TRUE;

If that returns that a row (i.e. token was valid) then allow post to
continue and store the returned page in form_token.page_content.

But, if that returns no rows updated (i.e. it was already set not
valid by a previous request) then return from_token.page -- that is
they will see the same page value.

There's still a race condition between setting the token as invalid
and storing the page_content.  I could just have the second post
delay and wait for page_content to not be null.

Use cron to remove old form_tokens.

Or maybe someone has a more elegant and simple solution?


Bill Moseley
moseley at hank.org

More information about the thelist mailing list