[Looking for Charlie's main web site?]

Posting a form to itself without trickery, using an empty ACTION attribute

Did you know that if a form has an empty ACTION attribute (or none at all), it will post back to itself (to the page that presented the form)? This can be very useful, and it's a lot easier than more complicated code that struggles to build the ACTION attribute to hold the current filename and any query string.

In the first iteration of this entry, I referred to the two approaches of either providing an empty ACTION or none at all, but as the comments below show, the former violates the HTML spec. So let's stick with the notion of an empty ACTION. Same result, though.

How often have we all seen code along the lines of:

<form action="<cfoutput>#cgi.script_name#?#cgi.query_string#</cfoutput>" method="post">
...

or more involved:

<cfset action=CGI.SCRIPT_NAME>
<cfif CGI.QUERY_STRING NEQ "">
   <cfset action=action & "?" & xmlformat(CGI.QUERY_STRING)>
</cfif>
<form action="<cfoutput>#action#</cfoutput>" method="post">
...

All this could be replaced very simply with:

<form method="post" action="">
...

The form will post back to itself. I'll offer another post that shows a unique way to take advantage of this. In any case, I hope that this observation may help some folks.

Is this reliable?

Now, there are some who will argue that this is a violation of the HTTP HTML spec, and so it may be, but I've never found a browser in which it didn't work.

Again, a clarification over what I wrote originallyhere. As was refined in the comments below, it's a violation to have *no* ACTION, but it's perfectly legit according to the URI spec (section 4.2 at http://www.ietf.org/rfc/rfc2396.txt) to have an empty ACTION, which is interpreted as a "same-document reference. (Thanks, Christopher Bradford, for that info.) Given that, even the following cautions seem needless, but I'll leave them for any still concerned.

If you have any hesitation, because you have to support multiple browsers and you can't test all possibilities, I'll understand if you choose to pass on this. But certainly if you only need to support browsers you can test, then if it works as expected, enjoy.

If anyone reading this can offer where this is the case, I'd appreciate hearing it. If you want some simple code to test, try this:

<form method="post" action="">
   <input type="Submit">
</form>
<cfif cgi.request_method is "post">
   Posted to itself
</cfif>

If it shows the text within the IF, then it worked as expected.

What about query string info?

You may wonder about the earlier more involved examples that showed passing the query string, in case any had been passed to the form. No problem. This technique passes any query string along just fine. Try it yourself (add ?test=test to the form and view in the debugging info that it's still in the URL scope after submission.)

Again, I'll offer another post that shows a unique way to take advantage of this in doing login authentication.

Comments
I can think of a few reasons for not going this route:

Knowing it is a violation of the HTTP spec alone is enough for me to not use this technique. While it may work on every browser today, it may not work on IE 8 or FF 3 if they decide to be more standards compliant. I really do not want to fix countless forms in the future.

The next developer that comes along may not have read this blog post, and wastes his time trying to figure out where the form posts to. ( "I just searched through 3 embedded js files and still don't see where the form posts to!")

Adding cgi.script_name?cgi.query_string is trivial.
# Posted By Gus | 1/2/07 9:10 PM
I'll add that, for those who aren't aware, a CFFORM with no method defaults to post and a CFFORM with no action not only posts to itself but does in fact pass the query string (URL variables) to itself again ;)
# Posted By Simon Horwith | 1/2/07 11:04 PM
Well, Gus, before throwing the baby out with the bathwater ("it violates the spec so I won't use it"), I'd like to challenge any who argue that it does to point out how it does. I was only reiterating what I've heard some argue. I haven't seen the conclusive evidence.

And even if someone found it, I'd think it would still have to be evaluated against similar "against the spec" features that we may all use. I mean, we can be purist about it, but if someone could show that there are other similar "anti-spec" things that are widely used (and that we might ourselves use) then I would think that mitigates the concern for purity. But to each his own, of course.
# Posted By Charlie Arehart | 1/3/07 10:45 AM
Thanks, Simon, for your observation about CFFORM. I do want to point out something pertinent to this discussion however. In 6.1, such a CFFORM (without an ACTION or METHOD) does indeed build the kind of no-action form I discuss here. As of 7 (at least in the 7.02 I'm testing) I see that it does build the ACTION with both the filename and any querystring.

I suppose one may argue that they did this in response to the very concern that Gus has raised. If anyone at Adobe happens to be reading this and can report why it was changed that could help the argument (though the simple fact that CFFORM now does it isn't enough motivation in and of itself for me to argue against the no-action approach). Again, just my opinion.
# Posted By Charlie Arehart | 1/3/07 10:49 AM
Oh, and let me add something in response to Gus. You say "Adding cgi.script_name?cgi.query_string is trivial", and that's true, but I should have mentioned that was motivated to write all this by a discussion on a mailing list where someone was finding that the cgi.script_name value was coming up with an unexpected string being prepended to it that made the form submission fail. I recommended to him this no-action approach, and it solved the problem for him, so I decided to blog about the approach in general, but just forgot to mention that it was addressing a challenge with his script_name value (since he's not yet resolved why it was providing an incorrect value).
# Posted By Charlie Arehart | 1/3/07 10:52 AM
Charlie,

According to the HTML 4 spec Section 17.3 the Acction is a required attribute of the form element:
http://www.w3.org/TR...

Having said that, I think there are myriad reasons to ignore the specs, I just think eliminating a form action is not a very good reason to do so as it is so easy to comply with the spec. Most of the time when the spec is ignored it is due to poor or non-compliance to the spec by browsers, thus workarounds are used. This is different than the case being discussed.

There are exceptions to every rule, but as a rule I would continue to recommend providing an action to html forms.
# Posted By Gus | 1/3/07 12:49 PM
How could this be a violation of the HTTP spec? HTTP isn't involved at this point; just HTML (and while it is a violation of the HTML spec to *omit* the action attribute, it can be an empty string with the same result). The *browser* is the entity that translates an empty action into the request, and the browser is making a valid HTTP request. So there is no violation of a spec. In fact, the URI syntax explicitly specifies:

4.2. Same-document References

A URI reference that does not contain a URI is a reference to the
current document. In other words, an empty URI reference within a
document is interpreted as a reference to the start of that document,
and a reference containing only a fragment identifier is a reference
to the identified fragment of that document. Traversal of such a
reference should not result in an additional retrieval action.
However, if the URI reference occurs in a context that is always
intended to result in a new request, as in the case of HTML's FORM
element, then an empty URI reference represents the base URI of the
current document and should be replaced by that URI when transformed
into a request.

It seems that this is reliable, consistent, and standards-compliant behavior.
# Posted By Christopher Bradford | 1/3/07 12:57 PM
I'd recommend you never do:

<form action="<cfoutput>#cgi.script_name#?#cgi.query_string#</cfoutput>" method="post">

You must check cgi.query_string doesn't contain <script> tags or whatever else XSS you can think of...

I use replace(cgi.query_string,"<","","ALL") in the blogCFC on my site..
# Posted By Geoff | 1/3/07 1:06 PM
Gus, thanks for your offer to the link in the HTML spec.

Christopher, thanks for your clarification that I misspoke in saying some had called it a violation of the HTTP spec. As Gus showed, the HTML spec says it should be there.

But you make a great point that if CAN be there and be empty. In case anyone would ask, what's the URL for that? I tried to find it but could not readily.

So it seems that while one could argue that you should not leave it off, you can leave it with an empty value (which I said, but did not show, in the blog entry). That's a fine clarification.

Finally, Geoff, you, too, make a great point. In fact, I was going to offer code that did address that, doing an xmlformat(cgi.query_string) but decided to leave it out as I was arguing that the querystring appending was unneeded. But yes, if one does leave it, then it's wise to consider security concerns.

(Indeed, this argues yet another reason to just leave it blank and leave it to the browser to pass along whatever is sent. As for whether the ultimate action page should further validate the input URL variables for potentially bad data, that's an entirely different subject that I'd rather not open for discussion in this comments of this blog entry.)
# Posted By Charlie Arehart | 1/3/07 1:21 PM
Here's the link to the URI spec:

http://www.ietf.org/...
# Posted By Christopher Bradford | 1/3/07 1:50 PM
Thanks, Christopher.
# Posted By Charlie Arehart | 1/3/07 2:02 PM
This might be a little late in the conversation, but I have used this technique in CFML and ASP going back the last 4-5 years with no issues at all. I have always just not included the attribute at all, but going forward I will include the attribute but I will just leave it blank.
# Posted By Rudi Shumpert | 1/4/07 7:52 AM
I always do it as "form action="" method=...."

My pages validate too.

It does the same thing, but you are using the required attribute.
# Posted By Kevin Sargent | 1/4/07 1:22 PM
Thanks Rudi and Kevin for your confirmation of success using an empty ACTION. I'm really glad to see that, and thanks to everyone involved in the discussion. I'll revise the entry to remove the reference to leaving it off, but fortunately 99% of the entry will remain valid and useful to folks. :-)
# Posted By Charlie Arehart | 1/4/07 3:09 PM
Just a note:

Recently in a rushed coding frenzy I did:

action="?mcp=1234-4567-7890&id=whatever" method="post"

instead of putting them as hidden form fields.

It does work in most browsers, the form submits to itself, and you can read the url vars and form vars. It does NOT work in safari, and probably should NEVER be done anyways. Just something I learned, and do not do in production!
# Posted By Kevin Sargent | 1/9/07 1:43 PM
Kevin, I don't see anything in either the HTTP or URI spec that suggests that a query string (the part after ?) is not permitted in the URI value for a FORM ACTION. What's making you want to assert "do not do it in production"?

If it's just the failure in Safari, might that rather be an error in Safari?

And I guess I'd also ask if it's specific to the self-referencing form of ACTION being discussed here. I mean, even if you provided a filename, are you saying that you should not use a query string on an action?

I'm not saying you should. Just looking for clarification, for future readers, especially if someone can point to a definitive document on the topic.
# Posted By Charlie Arehart | 1/9/07 3:29 PM
My problem was with using a querystring only, no filename.

Using a filename would have been a standard relative path.

I didn't get a chance to check all browsers, I develop in FF, check in IE. A few people I work with have Macs, and noticed this problem.

"Do not do it in production" - simply because you can make it work in all browsers without breaking standards by adding the filename. Not to say query string only is not standard (I don't know either way) (might be only a safari bug?) But if you know it breaks a browser, and you can make it work while upholding standards, that's probably the way to think about doing it.

To clarify, as soon as I specified filename or used a absolute path, it worked fine in safari too.
# Posted By Kevin Sargent | 1/9/07 8:36 PM
to further clarify: action="" also was fine in safari

action="?id=3&this=that" broke in safari with the action url being formated like
domain.com/filename.cfm?id=3&this=that?id=3&this=that
# Posted By Kevin Sargent | 1/9/07 8:38 PM
Kevin, I don't mean to keep pouring water on your resistance to this approach. I mean, to each his own, but did you read that URI standard document that Christopher offered? Offering no filename for the action *should* cause the browser to create a "a standard relative path". You assert that using no value for filename in the action helps you avoid "breaking standards", but the points above clarify that specifying no value is within the standards.

Now you raise a good point. If the use of just a querystring fails on Safari, then it's certainly worth thinking twice before using it. It's still unclear if doing so is against the standard. Just because it fails on Safari doesn't make it "non standard" (nor is it clear that doing it makes your code "uphold standards".

I'm being a bit pedantic. I do appreciate your pointing out the challenge and solution, and thank you for bringing it up. Each can decide for themselves how to respond to all this.
# Posted By Charlie Arehart | 1/9/07 10:51 PM
thanks for responding.

I am in agreement with your post! I just thought I would point out that a querystring only may cause problems in safari, and to avoid that problem is simple, and doesn't break standards (not a hack just for safari.)

All Good!
# Posted By Kevin Sargent | 1/10/07 1:37 AM
This is an easy solution, but not one to depend on. A non-conforming user agent may refuse to submit the form entirely.

I'm currently working on a form where I've tried to get away with the empty action attribute. I tested it on my cell phone, but it refuses to submit the form; instead, it throws an "Invalid web address" error.

I recommend a full-blown URI for the action attribute.

(My cell phone UA string: Nokia6030b/2.0 (m3.35) Profile/MIDP-2.0 Configuration/CLDC-1.1 UP.Link/6.3.0.0.0)
# Posted By Travis Estill | 1/12/07 10:33 PM
Did you actually test this? On multiple web servers? using html?

On Apache/1.3.37 this results in a 405 error
The requested method POST is not allowed
# Posted By Experienced | 11/14/07 11:44 PM
@Experienced, can you kindly clarify who you're asking your question of? Was it me? or someone making a comment?

And if me, then what part of my original post are you referring to? My original suggestion that you need not include any Action? Or my update about leaving it empty?

To answer your questions, yes of course I "actually tested it", but no, I'll admit not against multiple web servers (sorry, just didn't think of that), but yes of course I was using HTML. What else might you think I was using? Seems an odd (almost surly) question.

Also, as the commenter previous to you had said, this could also be affected by browsers, so I'll ask you, what browser were you using? If we're going to get to the bottom of any aspect of this which doesn't apply to all, let's do it across the board.

I have to say I don't care much for your tone. Do you know me? (Or even if you're responding to a commenter, do you know that person?) You just sound awfully accusatory, like you're trying to prove a point, or assert that I've wasted your time (or that of others). Chill out. I was sharing a tip, and one that's helped me out (and others) quite a bit over the years. If it's not a perfect tip, that's indeed what the comments are for. But I'm here trying to help people. I'd like to ask you to do the same.
# Posted By Charlie Arehart | 11/15/07 4:32 AM

@Experienced, can you not interpret what it is saying? It is in plain English - it says that the POST method is not allowed - that doesn't mean that it happened because of you leaving your action attribute empty - Apache/1.3.37 obviously is not set up to allow post requests to your specific page, or that it is set up to reject post requests to that specific page, this has nothing to do with the action attribute! To work around the problem, you should google to try and find out how you can allow post requests to your specific page, or maybe use GET, or whatever
# Posted By will | 4/24/08 8:20 PM
BlogCFC was created by Raymond Camden. This blog is running version 5.005.