Dismiss Notice
Join Physics Forums Today!
The friendliest, high quality science and math community on the planet! Everyone who loves science is here!

HTTP Redirect to a POST URI?

  1. May 10, 2010 #1
    So, most of the time, when I want to do a redirect using HTTP headers, I do something like this:

    Code (Text):
    Status: 302 Moved Temporarily
    Location: [PLAIN]http://www.foo.com/bar.cgi[/PLAIN] [Broken]?param=1
    [/URL]

    And, that's all well and good-- but what if I want to redirect the browser to make the same request as a POST? Essentially, I want something like this:

    Code (Text):
    Status: 302 Moved Temporarily
    Location: [PLAIN]http://www.foo.com/bar.cgi[/PLAIN] [Broken]
    Request-Method: POST
    Content: param=1
    Or, something like that. Obviously, that doesn't work. And everything I'm managing to Google gives me the answers to other questions. Anyone?

    DaveE
     
    Last edited by a moderator: May 4, 2017
  2. jcsd
  3. May 28, 2010 #2

    harborsparrow

    User Avatar
    Gold Member

    are you trying to do URL re-writing?
     
  4. May 28, 2010 #3
    I think re-writes are at the webserver level, which won't help. This is at the script level-- the HTTP headers that the script returns.

    I'm trying to force the client's browser to immediately request a new page using a POST request rather than a GET. I'd rather that the client's browser not display the data being passed, and rather it weren't logged. It's not really a security issue, so much as a potential GET limitation.

    If I want to redirect someone to a page that requires (for example) 1 megabyte's worth of parameters, that's WAY more than a GET is required to support. In other words, it'll overflow the GET request, and the data will be gone, because neither the browser nor the webserver will support the request, and it'll fail.

    However, there's no data limit to a POST request. If I want to redirect someone to a page that takes a megabyte of data, no problem, so long as their browser makes a POST.

    So, the only way I can think to do this is HTML content rather than HTTP headers. For example, I could write a standard HTTP response, with HTML content, and contained therein, a huge JavaScript snippit that immediately directs the client's browser to do the necessary POST. But that requires the browser to have JavaScript enabled, requires some extra finagling, and probably adds more delay in the time it takes to do.

    Preferably, I can just have the option of redirecting the browser using the HTTP headers-- I've just never seen them use POST's before, so I'm wondering if it's strictly impossible, or just obscure.

    DaveE
     
  5. May 29, 2010 #4

    harborsparrow

    User Avatar
    Gold Member

    What happens with this? Does the browser use POST or GET when it honors the redirect due to a meta http-equiv="refresh" ash shown in the following page? I really don't know--could find out if I had time to install a sniffer:

    <html>
    <head>
    <meta http-equiv="refresh" content="3;URL=http://somewhere.com"> [Broken]
    </head>
    <body>

    In 3 seconds, you should be redirected.

    </body>
    </html>
     
    Last edited by a moderator: May 4, 2017
  6. May 29, 2010 #5
    Nope, uses a GET. That "content" tag is misleading, since it's not the actual content of the query, it's the content of the meta tag. I don't know of a way to make a meta-refresh do a POST...

    DaveE
     
  7. May 29, 2010 #6

    Hurkyl

    User Avatar
    Staff Emeritus
    Science Advisor
    Gold Member

    davee: what is the problem are you really trying to solve? What is the problem for which you thought HTTP redirects would be a solution for?


    (I'm going to baldly assert that redirects are quite likely not a good solution for whatever problem you're trying to solve, especially given the extra information you've provided)
     
  8. May 29, 2010 #7

    harborsparrow

    User Avatar
    Gold Member

    Maybe you can use a Javascript trick--try making the page use a timer and then callback as POST via a Javascript AJAX call...
     
  9. May 29, 2010 #8

    harborsparrow

    User Avatar
    Gold Member

    Some AJAX examples are here: http://harbormist.com/cis700_07/examples.html [Broken]
     
    Last edited by a moderator: May 4, 2017
  10. May 29, 2010 #9
    I'm writing a login system for my own custom web application. So, embedded in most every CGI within the application is the login piece.

    Now, what happens when your login expires? Let's say you logged in, and then left your browser sitting on "Page A" in the middle of the application. Now, you come back after the login expires. Your page is still there, so you click one of the links to "Page B" with parameters 1, 2, 3. Well, "Page B" checks your login and finds out it's expired. So what does it do? It sends you to the login page. Actually, it usurps the call, and shows the login screen on the same URL that "Page B" was on. Now, you log in. Where does it take you next?

    If you're kind to your users, you take them back to "Page B", with parameters 1, 2, 3. You could just take them back to the "home" area or wherever you want. But if you're nice, you take them where they were trying to click. And the way that I do that is by saving all the parameters in hidden fields on the login screen.

    Anyway, submitting the login form sends the browser to a login verification CGI, which authenticates the user, and then attempts to send them back on their merry way to "Page B" with parameters 1, 2, 3. And you do that with HTTP redirects, because other methods aren't as good. Generally for two reasons:

    1) Users can disable meta-refreshes, JavaScript, plugins, etc. Some browsers also don't support them (like some mobile devices or more primitive text-based browsers).

    2) The "bounce" page is generally NOT saved in the browser history with HTTP redirects, whereas meta-refreshes, JavaScript, etc, ARE kept. So if a user tries to navigate with the "Back" button, they can't get beyond the redirect page (although browsers these days typically allow you to "jump" through your history). If they go back to the redirect page, they just get bumped forward again.

    That second reason is also the recommended method of form submission for things like credit card information, etc, because again, the user's browser is very unlikely to hit it again since it's not in the browser history. If it DID try to navigate to the page again, and decided not to use a cached copy, it would submit the request again, possibly double-billing a credit card (or doing whatever action you DON'T want your users to repeat). In this particular instance, it's not a big deal, since all it would do is re-log them in. But in general, there are a lot of cases where using an HTTP redirect really IS the preferred way of doing things for the above reasons.

    [edit]Actually, now that I think about it, you probably DON'T want them to be able to just log in again by re-posting. That would allow someone to snag the browser and just do a re-post of the form to reload, and thereby log them in. Of course, if the browser saves the username/password, they're screwed anyway, but that's not a security hole I can circumvent, without doing something crazy.[/edit]

    But back to the issue at hand. Using HTTP redirects (the way I'd prefer to do things), I only know how to force a GET query. But... if instead of parameters 1, 2, 3, let's say there were 500 different parameters! That's enough to overflow the GET query, and it means that the subsequent call to "Page B" won't be complete. Depending on the browser and webserver, I'm not really sure HOW it would handle this. I had thought it was about a 1K limit, but looks like it's more like 2K-8K generally. But regardless, it's certainly possible to go beyond that limit.

    Now, there are a lot of ways to handle this:

    1) If possible, use HTTP redirects using a POST to get the user back to their desired location.

    2) I could say screw it, and impolitely force the user to their "home" area, losing their desired path. (This can annoy users if, say, they spent a long time filling out a form and then lost the information, forcing them to fill it out again)

    3) I could redirect using meta-refreshes, JavaScript, or what-have-you.

    4) I could rebuild the Login module so that rather than forcing you to the authentication CGI, it just keeps you on the existing CGI, but gracefully passes back all the parameters (passed exactly as they were on the original form), so that the successful login results in a near duplication of their former attempt.

    5) I could also rebuild the Login module to store the POST parameters in a time-indexed file, and pull them out of there on the subsequent page request-- but that requires integrating my login module with the parameter processing, which is pretty sketchy.

    Now, I figured the best option was #1. And I think I'd opt for #4 before I resort to #3 or #2. After all, I'm hoping I can re-use this login system in the future, so I'd like it to be as useful going forward as possible.

    So, that's what I'm shooting for. If it's possible, great! If it's not, then oh well, I'll figure something else out.

    DaveE
     
    Last edited: May 29, 2010
  11. May 29, 2010 #10

    Hurkyl

    User Avatar
    Staff Emeritus
    Science Advisor
    Gold Member

    I don't think options (1) and (3) even solve your problem: nowhere are you redirecting a POST request. Instead, you are trying to hold on to the POST data, so that it can be sent along with the login data after the user re-logs in.




    Anyways, my first thought is "Eep! 500 parameters? :bugeyes:"? Can you not store the data in a HTTP session? Then you just need to configure the server so that the data in the sessions still persist even after a login expires.

    Even if not, you could start a session immediately upon the failed login to hold onto the POST'd data so that the login script can be passed it along to the correct script on successful login.

    I confess I've been spoiled by working with things like J2EE or Django, so I don't know what limitations you have when CGI scripting. :frown: I guess my last suggestion is using the framework to do your option (5) for me.


    If you don't have sessions and can't rely on javascript, I think options (4) and (2) are your only ones. (4) has the advantage of being very straightforward. :smile: (but... maybe you have to worry about the case where the POST data shouldn't be sent in the clear?)
     
  12. May 29, 2010 #11
    Well, I'm just throwing numbers around there-- more likely than 500 distinct parameters, it would be one REALLY BIG parameter.

    That's pretty much option #5-- it's more efficient bandwidth-wise, but it means a bunch more complexity in the code. I might end up doing it anyway, but it's much easier (and still works, even though it's less elegant) to do an HTTP redirect, so I figured I'd ask if it was even possible.

    Well, it's not that I can't implement a JavaScript version, or that I don't trust it-- it's probably sufficient because this isn't intended to be a professional application. But it still doesn't answer my question of curiosity: can you use HTTP redirects to do a POST? If it's possible, that's great, and I'll do it. If not, I can do something else. But certainly I haven't ever seen it done.... But nothing I managed to Google seemed to suggest that it was or wasn't actually possible, so I figured I'd ask.

    DaveE
     
  13. May 30, 2010 #12

    harborsparrow

    User Avatar
    Gold Member

    This is a difficult thing to do; people have been struggling to get all the nuances of this right since there was a www. This is one good reason to get and use a framework that has already solved this problem. Of course, trying to do it yourself, you will learn things, but you'll also kill a ton of time and still have bugs (that you don't know about until they occur). Microsoft websites do this for you; they provide a framework that is simple to use and just works (several options in fact). Why re-invent the wheel?
     
  14. May 30, 2010 #13
    Probably the same silly reasons programmers re-invent the wheel all the time:

    1) There are annoyances I have with the systems that are available
    2) I'll spend just as much time learning the new system as I will making my own
    3) Making my own guarantees I'll be more familiar with the code

    In this instance, I want a system that provides me a back-end login system in Perl, because I'll be writing the rest of my applications in Perl. I don't know of any open-source Perl login systems, so I'm writing one.

    Chances are, though, that any system I find, I would also find annoying. 99.9% of all login systems don't allow you to use special characters in your login name, restrict you to something like 8 or 12 characters, and have yet-another-bizarre set of restrictions for passwords. "You must use 3 categories out of lower-case letters, numbers, upper-case characters, and special characters". Or, "You can't use any special characters". Or, "Your password can't contain any one of a list of dictionary words". Or "Your password must be at least 8 characters". Etc. I hate that.

    Another thing is portability. They require specific database types, specific modules, and other things that I'm not really sure I'll have when I switch hosting. I'm going for a pure Perl implementation that would work on whatever type of hosting I get-- probably even Windows.

    In my professional life, I have to admit, I've helped write (or totally written) 4 different login systems, some of which have been integrated with off-the-shelf or open-source systems in different aspects. Again, all Perl. We did some research to find really good pre-built systems, but we didn't really find anything we liked. The ones we ARE using we still don't like. In fact, one of them (CAS), thanks to its shortcomings, we wound up totally re-implementing ourselves because it wasn't robust enough.

    Anyway, it's not my intention to defend the fact that I'm re-inventing the wheel. I'm doing it for fun. And I'll admit if you can show me an already-existing wheel that I like, maybe I'll use that instead of my own. But chances are, I'll just stick with what I'm doing. I was just asking a question about HTTP redirects, because I didn't know. I also asked fellow web developers at work, and they similarly didn't know. So it seems like nobody seems to know the answer, thanks to its wacky and obscure nature. And that's fine-- if nothing else, I appreciate the input, even if it's just validating the fact that it's obscure enough not to be commonly known.

    DaveE
     
  15. May 30, 2010 #14

    Hurkyl

    User Avatar
    Staff Emeritus
    Science Advisor
    Gold Member

    I still don't see how a redirect would work.
    1. User posts data to www.website.com/myapp[/URL]
      [*] Server returns a login page
      [*] User posts login data to [PLAIN]www.website.com/something[/URL]
      [*] Server returns ???[/list]
      By step 3, the POST data has already been lost; there's nothing you can return in step 4 that would allow the user's browser to repost it.
     
    Last edited by a moderator: Apr 25, 2017
  16. May 30, 2010 #15
    Basically, it works by re-submitting the POST data:

    1) User requests page X with POST data.

    2) Server detects expired login, and so presents the user with the login form. Embedded in the login form is the POST data. Page X's login form submits to script L (for "login")

    3) User requests page L with username/password, and all POST data (re-posted)

    4) Server examines the login. If invalid, effectively go to step 2. If valid, page L (the currently requested page) posts a "Status: 302" header, directing the user's browser to go back to page X, with the correct POST data.

    5) User's browser requests page X, again with the POST data specified from step 4.

    6) Server gets page X, with POST data as was initially intended.

    DaveE
     
  17. May 31, 2010 #16

    Hurkyl

    User Avatar
    Staff Emeritus
    Science Advisor
    Gold Member

    Upon successful validation, rather than having the login code render a response, why not pass the request directly to the intended script?


    Or even better, if the login stuff really is a module, then have the intended script look like (in pseudocode)
    Code (Text):

      if not login_module::validate(request) then
        return login_module::generate_expired_login_response(request)
      else
        // handle the request normally
      end if
     
    I had been assuming you were already doing something like that, and it was the interval from 2 to 4 that you were having trouble implementing.
     
    Last edited: May 31, 2010
Share this great discussion with others via Reddit, Google+, Twitter, or Facebook