How to POST to HTTPs?

34,238

you can change the form's action with javascript:

var form = document.getElementById("post-form");
form.action = location.href.replace(/^http:/, 'https:');

But there are some security considerations, and I would suggest you to redirect your form's url to https. And although you could do it from javascript, you should never trust javascript when it gets to security, so do it from the server (it's also faster, the page doesn't have to be loaded, only the http header)

Share:
34,238
mistertodd
Author by

mistertodd

Any code is public domain. No attribution required. జ్ఞా <sup>🕗</sup>🕗 Yes, i do write i with a lowercase i. The Meta Stackexchange answer that I am most proud of

Updated on July 09, 2022

Comments

  • mistertodd
    mistertodd almost 2 years

    Assume i have a form that right now is doing a post:

    <form id="post-form" class="post-form" 
          action="/questions/ask/submit" method="post">
    

    You'll notice there is no site in the action, the browser follows where it got the page from.

    The browser follows current domain rules when posting

    If the current page is...                then the browser will POST to
    =======================================  =============
    http://stackoverflow.com/questions/ask   http://stackoverflow.com/questions/ask/submit
    https://stackoverflow.com/questions/ask  https://stackoverflow.com/questions/ask/submit
    

    But I want to ensure that the browser will always go to the secure page:

    http://stackoverflow.com/questions/ask   https://stackoverflow.com/questions/ask/submit
    

    Normally you would try something like:

    <form id="post-form" class="post-form" 
          action="https://stackoverflow.com/questions/ask/submit" method="post">
    

    Except that requires knowing the domain and virtual path name of hosting site (e.g. stackoverflow.com). If the site were changed:

    • stackoverflow.net
    • stackoverflow.com/mobile
    • de.stackoverflow.com
    • stackoverflow.co.uk/fr
    • beta.stackoverflow.com

    then the form action would have to be updated also:

    <form id="post-form" class="post-form" action="https://stackoverflow.net/questions/ask/submit" method="post">
    
    <form id="post-form" class="post-form" action="https://stackoverflow.com/mobile/questions/ask/submit" method="post">
    
    <form id="post-form" class="post-form" action="https://de.stackoverflow.com/questions/ask/submit" method="post">
    
    <form id="post-form" class="post-form" action="https://stackoverflow.co.uk/fr/questions/ask/submit" method="post">
    
    <form id="post-form" class="post-form" action="https://beta.stackoverflow.com/questions/ask/submit" method="post">
    

    How can I instruct the browser to go to https version of a page?


    Hypothetical syntax:

    <form id="post-form" class="post-form" action="https://./questions/ask/submit" method="post">
    

    302, 303, 307

    Originally 302 Found was the code to tell the user agent to go someplace else. The intention was that browsers would simply try again at the new location:

    POST /questions/ask/submit
    
    302 Found
    Location: /submitquestion
    
    POST /submitquestion
    

    Unfortunately all browsers got it wrong, and would mistakenly always use GET on the new location:

    POST /questions/ask/submit
    
    302 Found
    Location: /submitquestion
    
    GET /submitquestion
    

    Because browsers got it wrong, two new codes were created:

    • 302 Found: (Legacy deprecated) Try the exact same thing again at the new location; but legacy browsers were switching to GET
    • 303 See Other: Forget whatever the user was doing, and go do a GET on this Location
    • 307 Temporary Redirect: Try the exact same thing again at the new Location (No, seriously, the same thing - i didn't say you could switch to GET. If you were doing a DELETE then go DELETE it over here.)

    For example, if the user agent was in the middle of a POST:

    | Response               | What agent should do  | What many agents actually do |
    |------------------------|-----------------------|------------------------------|
    | 302 Found              | POST to new Location  | GET from new Location        |
    | 303 See Other          | GET from new Location | GET from new Location        |
    | 307 Temporary Redirect | POST to new Location  | POST to new Location         |
    

    Ideally, there would be a way to use 307 Temporary Redirect to tell the user agent to try the POST again on the secure URL:

    POST /questions/ask/submit
    
    307 Temporary Redirect
    Location: https://beta.stackoverflow.com/questions/ask/submit
    
    POST /questions/ask/submit
    

    and i can get away with that well enough server-side in ASP.net:

    if (!Request.IsSecureConnection)
    {
       string redirectUrl = Request.Url.ToString().Replace("http:", "https:");
       Response.Redirect(redirectUrl);
    
       //We don't want to send the client the deprecated 302 code, we want to use 307 telling them that we really want them to continue the POST, PUT, DELETE, etc
       Response.StatusCode = (int)System.Net.HttpStatusCode.TemporaryRedirect;     
       Response.End();
    }
    

    But i don't know if you can specify a full uri in a Location.

  • mistertodd
    mistertodd about 12 years
    That still requires that i change my submit action from "/questions/ask/submit" to "http://beta.de.stackoverflow.net/mobile/questions/ask/submi‌​t" :(
  • Gavriel
    Gavriel about 12 years
    then save that base_url somewhere. You can maybe use <base> for that, but if that has bad side effects, then just print it into a javascript variable: var baseUrl = "beta.de.stackoverflow.net/mobile/"; then you can concatenate form.action = "https://" + baseurl + form.action, OR you can just use location.hostname.