Apache 301 Redirect and preserving post data

47,922

Solution 1

Update circa 2021 The original answer here was written before 307 status code redirect worked consistently across browsers. As per Hashbrown's answer below, the 307 status code should be used.

Old Answer POST data is discarded on redirect as a client will perform a GET request to the URL specified by the 301. Period.

The only option is to convert the POST parameters to GET parameters and tack them onto the end of the URL you're redirecting to. This cannot be done in a .htaccess file rewrite.

One option is to catch POST requests to the url to be redirected and pass it off to a page to handle the redirect. You'd need to do the transposition of the parameters in code then issue the redirect header with the parameter appended new url that way.

Update: As pointed out in the comments to this answer, if you do redirect to another URL specifying POST parameters and that URL is also accessed without paramters (or the params are variable), you should specify a link to the canonical URL for the page.

Say the POST form redirects transposed to the following GET resource:

   http://www.example.com/finalpage.php?form_data_1=123&form_data_2=666

You would add this link record to the head section of the page:

   <link rel="canonical" href="http://www.example.com/finalpage.php" />

This would ensure all SEO value would be given to http://www.example.com/finalpage.php and avoid possible issues with duplicate content.

Solution 2

Using a 307 should be exactly what you want

307 Temporary Redirect (since HTTP/1.1)
In this case, the request should be repeated with another URI; however, future requests
should still use the original URI.[2] In contrast to how 302 was historically implemented,
the request method is not allowed to be changed when reissuing the original request. For
instance, a POST request should be repeated using another POST request

- Wikipedia

Share:
47,922
Daniel Cook
Author by

Daniel Cook

Updated on October 02, 2021

Comments

  • Daniel Cook
    Daniel Cook over 2 years

    I have implemented SEO URLs using Apache 301 redirects to a 'redirect.cfm' in the root of the website which handles all URL building and content delivering.

    Post data is lost during a 301 redirect.

    Unable to find a solution so far, have tried excluding post method from rewrites - worst case scenario we could use the old type URLs for post methods.

    Is there something that can be done?

    Thanks

  • Daniel Cook
    Daniel Cook over 11 years
    Thanks, I'm going to assume doing such a thing could make login forms display the username/password in the browser URL bar. I am steering myself towards updating each form to post to the calculated dynamic SEO URL.
  • Ray
    Ray over 11 years
    @DanielCook You could also put the POST variables in a session if the redirect is to a same domain url and you don't want them in the URL. Just don't forget to force flush the session before issuing the redirect. I don't think GET parameters affect SEO of a URL however, it would just be visually ugly.
  • Daniel Cook
    Daniel Cook over 11 years
    Thanks, maybe this will work. Apache sends all post requests to 'redirectPost.cfm', this stores form data in session.form and redirects the URL (losing post data). Once the 'redirect.cfm' picks it up it writes all session.form data back into the form scope before delivering the content.
  • Daniel Cook
    Daniel Cook over 11 years
    Doh, just realised a redirect to 'redirectPost.cfm' would lose the post data. Perhaps another type of redirect, 307? keeps the post data, I will have to look that up.
  • Ray
    Ray over 11 years
    @DanielCook you don't redirect to your redirect handler page, you just serve it up the do a single redirect on that page. No rediect 30x preserves post parameters
  • Daniel Cook
    Daniel Cook over 11 years
    I had confused myself, I'm clear now. thanks, I will try it out.
  • daniel.gindi
    daniel.gindi over 11 years
    @Ray I'm afraid you are mistaken, about the SEO thing. Any system will treat the full URL as unique. That includes also the url parameters (aka "query string"). So /index?1 and /index?2 are different urls. And they ARE different. That's the reason that google will treat them as actual different urls.
  • chrismarx
    chrismarx over 10 years
    This works, and you can keep the efficiency of the 301 redirects by just applying 307 redirects to POST requests only
  • Daniel Cook
    Daniel Cook about 10 years
    I've had a look at the above, trying to get an idea for what's possible. An example suggestions Standard URL: example.com/… Rewrite URL: example.com/list/fruit/asc/30/1 However my URLs will be domain.com/folder1/folder2/folder3/index.cfm?id=12345 and resolve to domain.com/area/id-title-of-the-article/ The information is not available in the DB and will require some DB queries to ascertain title and area.
  • Ray
    Ray almost 10 years
    @daniel.gindi Thanks for noting the ambiguity. I think I wasn't clear in my comment. I didn't mean URLs with different get parameters are treated as the same resource for SEO purposes. I completely agree to your point /index?1 != index?2. What I meant to convey was I didn't think similar URLs one using GET params vs. on not had any affect on SEO value. For example choosing between closely formed urls /index?id=1 vs. just /index for a page I don't think either would have major SEO affect one way or the other.
  • Ray
    Ray almost 10 years
    @daniel.gindi Also, I'm not applying all URL stucture choices are SEO equal. For example /index?id=19283b&post=2211 vs. /articles/great-dallas-restaurants, assuming the article is about great restaurants in dallas, MIGHT have better overall SEO impact using the second URL.
  • daniel.gindi
    daniel.gindi almost 10 years
    @Ray I'm afraid you are mistaken again, about the first point. Even if two urls are very similar, Google will kick you in the butt about having two urls with the similar content. You will have to declare them canonical. But about the second point is correct, A url with contextual info in the URL itself is better from an SEO point of view.
  • Ray
    Ray almost 10 years
    @daniel.gindi I think I need to be clearer. I'm not suggesting having two active urls to the same source--that has major SEO implications and you have to be careful and flag one canonical as you mention. The comments I made were only intended to address the factors to think about when you are choosing a single URL to use for a specific resource, when between picking one URL structure or the other, which would be better from an SEO standpoint or what would probably not affect SEO much at all.
  • daniel.gindi
    daniel.gindi almost 10 years
    @Ray Yes that is a different matter. I was addressing the different Urls that will be created by converting POST forms to GET
  • Ray
    Ray almost 10 years
    @daniel.gindi I think if the initial request being redirected is a POST, there shouldn't be any SEO impact. I think the only URLs listed or followed in search engines like google are those in anchor tags (that are all GET requests). No legit crawler should submit requests as POSTs to a form url, so no crawler should be redirected to the new final URL with appended get parameters, so search engines should never 'see' the URL with the parameters in them. I know people suspect google of submitting forms, but I've never come across a POST url in my searches.
  • daniel.gindi
    daniel.gindi almost 10 years
    @Ray What really happens is that your browser, say Chrome, is seeing those URLs because you have visited them. Chrome sends "anonymous statistics", which includes the URLs to crawl. We have observed this behaviour in the past and got used to putting a ROBOTS file in every site that is not in production yet, because Google got to know the URLs even before us...
  • Ray
    Ray almost 10 years
    @daniel.gindi interesting. I've heard of such statistics in chrome as well as anything google analytics may be sending back. Still, I'm not yet convinced these actually get indexed if the actual url is not crawlable but behind a 301 from a POST request. I'm definitely not an authority on this, so I will start keeping an eye out for these showing up in my webmaster tools as indexed pages. I don't think it's outside the realm of reason they could since all the data is going to the same source, google.
  • daniel.gindi
    daniel.gindi almost 10 years
    @Ray Well, from my (and friends') experience - they actually do it. As long as the URL exists, and you did use it (even if coming from a "form") - it is crawlable, and Google will find it. There IS a solution though, using either ROBOTS or adding CANONICAL tags to the pages.
  • Ray
    Ray almost 10 years
    @daniel.gindi I see your point. I agree CANONICAL (without the GET params) can ensure the final redirected URL to will limit SEO juice to only one permutation of the URL. If google is detecting using such urls, using canonical will protect you. If they're not, it doesn't hurt as it still clarifies things. Will update my answer to include this detail. Thanks!
  • daniel.gindi
    daniel.gindi almost 10 years
    @Ray well now I feel comfortable upvoting your answer, it's safe now ;-)
  • Skippy le Grand Gourou
    Skippy le Grand Gourou over 8 years
    @chrismarx How do you do that ?
  • chrismarx
    chrismarx over 8 years
    I added this: RewriteCond %{REQUEST_METHOD} =POST and then on the next line, this: RewriteRule /my-app/(.*)$ /$1 [R=307]
  • Fred
    Fred almost 8 years
    Yes it works for me too. But something is really weird: with exactly the same rules, by changing R=301 by R=307, the RewriteRule doesn't work the same!
  • dmmd
    dmmd over 7 years
    Man, this really saved me hours of lurking around. Just adding some keywords to whoever may be having issues with Laravel or Lumen and its Redirect Trailing Slashes If Not A Folder. Also, this answer is particularly useful to people developing a API.
  • Aditya Nagrath
    Aditya Nagrath almost 7 years
    This saved me on redirecting a rest api temporarily while apps deploy.
  • Felipe Francisco
    Felipe Francisco about 6 years
    After trying 301, 308 and 302, your answer saved me! Thanks, man!
  • ElOjcar
    ElOjcar almost 6 years
    Yes sir! Perfect answer!!
  • Adriano Pedro
    Adriano Pedro over 5 years
    Hello, What about the request IP. I mean the origin of the request? Is it preserved?
  • Liam James
    Liam James over 4 years
    Hi. I would really appreciate your response. I have a page that redirects: bvop.org/project-management-certification Unfortunately when it redirects the new URL looks like this: bvop.org/projectmanagement/?project-management-certification It contains the original URI after a weird ? character for a query parameter. I need to remove these but I cannot. Do you have any idea?
  • Diego Favero
    Diego Favero about 4 years
    [2] - Saved My day !
  • koras
    koras over 3 years
    This is the solution. I believe it could be marked as the answer since it's the behavior expected in the question.
  • Nathan B
    Nathan B over 2 years
    So no option to indicate a 307, or something else, which is permanent, to the browser to reissue a POST request to a different URL?
  • Ray
    Ray over 2 years
    @NathanB This answer (and question) is quite old. Looks like modern browsers now support the 307 properly as noted in Hashbrown's answer. Will update.
  • Nathan B
    Nathan B over 2 years
    I think there still is a problem in some browsers. Firefox for example. For some browsers sending 307 resulted the browser convert to GET request, which obviously created critical problem for some users.
  • Ray
    Ray over 2 years
    MDN indicates that current firefox should respect the method and body redirect: developer.mozilla.org/en-US/docs/Web/HTTP/Status/307 , but I've not personally tested.