I have a test Perl script for cookies, very simple (and simplified a bit) that doesn't work properly:<br /><br /><!--c1--><div class='codetop'>CODE</div><div class='codemain'><!--ec1-->use CGI qwstandard);<br />use CGI::Cookies;<br /><br />if(defined param("on")) # on button clicked<br />{<br />Â Â $c = new CGI::Cookie(<br />Â Â Â Â -name => 'test',<br />Â Â Â Â -value => 1,<br />Â Â Â Â -domain => '.****',<br />Â Â Â Â -path => '/cgi-bin',<br />Â Â );<br />}<br /><br />elsif(defined param("off")) # off button<br />{<br />Â Â # set same variable/settings except value is '0'<br />}<br /><br />print header(-cookie =>[$a]);<br /><br /># start html, head, title, body tags<br /><br />%cookie = fetch CGI::Cookie;<br /><br />if(defined $cookie{test})<br />{<br />Â Â $c = $cookie{test}->value;<br /><br />Â Â # code for form with on|off submit button<br />Â Â # the form POSTs back to this script<br />}<!--c2--></div><!--ec2--><br /><br />Here's how it works<br /><br /># script instance 1 (first page load)<br />cookie value on PC: 0 (let's pretend)<br />cookie value from fetch: 0<br />[I click the 'on' button & submit the form]<br /><br /># script instance 2<br />cookie value on PC: 1<br />cookie value from fetch: 0 (this is the problem)<br />[I click the on button again]<br /><br /># script instance 3<br />both cookie and fetch are '1'<br /><br />So what's happening is, the cookie gets set and there's a (basically) immediate fetch which doesn't match with what I expect until the second time around. I'm baffled, any help will help. <img src="http://www.totalchoicehosting.com/forums/style_emoticons/default/wink.gif" style="vertical-align:middle" emoid="" border="0" alt="wink.gif" /><!--content-->
Basically, the issue is that you're expecting to be able to read a cookie from a user's machine in the same request that you set it in, and cookies just don't work that way. There is one transmission of data from your machine to the server (containing the page request, form data, and any cookies stored for your site), which is then followed by one response from the server to your machine, containing the page to be displayed and any new cookies to be set.<br /><br />'fetch CGI::Cookie;' does not literally fetch a cookie from the user's machine. When you click the submit botton (actually, when you request any page from the web server), the browser automatically sends any cookies it has to the server. The server holds them in memory and provides them to your script when it calls 'fetch CGI::Cookie'.<br /><br />In your second instance, when your script calls 'fetch CGI::Cookie;', it is reading the cookie your browser sent at the time you clicked the submit button - not the cookie you just sent to your machine. This is what's occurring when you run your script:<br /><br /># script instance 1 (first page load)<br /><br />Your machine:<br />- Browser requests page<br />- No form parameters sent<br />- Cookie value '0' sent<br /><br />Server:<br />- Server sees cookie value '0' sent by browser<br />- Script sees no form parameter<br />- Script sends page with form back to browser<br /><br />You then click the 'on' button & submit the form...<br /><br /># script instance 2<br /><br />Your machine:<br />- Browser requests page<br />- Form parameter 'on' sent<br />- Cookie value '0' sent again<br /><br />Server:<br />- Server sees cookie value '0' sent by browser<br />- Script sends (sets) cookie value '1' to your machine<br />- Script reads sent cookie with 'fetch CGI::Cookie' and sees sent cookie value of '0'<br />- Script sends page with form back to browser<br /><br />You then click the 'on' button & submit the form...<br /><br /># script instance 3<br /><br />Your machine:<br />- Browser requests page<br />- Form parameter 'on' sent<br />- Cookie value '1' sent<br /><br />Server:<br />- Server sees cookie value '1' sent by browser<br />- Script sends (sets) cookie value '1' to your machine<br />- Script reads sent cookie with 'fetch CGI::Cookie' and sees sent cookie value of '1'<br />- Script sends page with form back to browser<br /><br />In a nutshell, I'd recommend restructuring your script code so that it first reads any cookies first sent by the browser. If no cookie was found, then create one. Then test for your form parameter (on/off). Set the now existing cookie with appropriate value if necessary, and send it to browser (set cookie). Test cookie value, and have script perform whatever actions you want and send page to browser.<br /><br />Hope this helps...<!--content-->
Great, that's exactly what I needed to know about cookies. In the 'real' script I'm working on I can just set a variable based on which button is clicked and display results that way; next time the page loads it'll read the cookie data.<br /><br />But... Now I'd better examine the rest of the cookies to make sure I understand how they're being interpreted.<br /><br />Thank you!<!--content-->
Basically, the issue is that you're expecting to be able to read a cookie from a user's machine in the same request that you set it in, and cookies just don't work that way. There is one transmission of data from your machine to the server (containing the page request, form data, and any cookies stored for your site), which is then followed by one response from the server to your machine, containing the page to be displayed and any new cookies to be set.<br /><br />'fetch CGI::Cookie;' does not literally fetch a cookie from the user's machine. When you click the submit botton (actually, when you request any page from the web server), the browser automatically sends any cookies it has to the server. The server holds them in memory and provides them to your script when it calls 'fetch CGI::Cookie'.<br /><br />In your second instance, when your script calls 'fetch CGI::Cookie;', it is reading the cookie your browser sent at the time you clicked the submit button - not the cookie you just sent to your machine. This is what's occurring when you run your script:<br /><br /># script instance 1 (first page load)<br /><br />Your machine:<br />- Browser requests page<br />- No form parameters sent<br />- Cookie value '0' sent<br /><br />Server:<br />- Server sees cookie value '0' sent by browser<br />- Script sees no form parameter<br />- Script sends page with form back to browser<br /><br />You then click the 'on' button & submit the form...<br /><br /># script instance 2<br /><br />Your machine:<br />- Browser requests page<br />- Form parameter 'on' sent<br />- Cookie value '0' sent again<br /><br />Server:<br />- Server sees cookie value '0' sent by browser<br />- Script sends (sets) cookie value '1' to your machine<br />- Script reads sent cookie with 'fetch CGI::Cookie' and sees sent cookie value of '0'<br />- Script sends page with form back to browser<br /><br />You then click the 'on' button & submit the form...<br /><br /># script instance 3<br /><br />Your machine:<br />- Browser requests page<br />- Form parameter 'on' sent<br />- Cookie value '1' sent<br /><br />Server:<br />- Server sees cookie value '1' sent by browser<br />- Script sends (sets) cookie value '1' to your machine<br />- Script reads sent cookie with 'fetch CGI::Cookie' and sees sent cookie value of '1'<br />- Script sends page with form back to browser<br /><br />In a nutshell, I'd recommend restructuring your script code so that it first reads any cookies first sent by the browser. If no cookie was found, then create one. Then test for your form parameter (on/off). Set the now existing cookie with appropriate value if necessary, and send it to browser (set cookie). Test cookie value, and have script perform whatever actions you want and send page to browser.<br /><br />Hope this helps...<!--content-->
Great, that's exactly what I needed to know about cookies. In the 'real' script I'm working on I can just set a variable based on which button is clicked and display results that way; next time the page loads it'll read the cookie data.<br /><br />But... Now I'd better examine the rest of the cookies to make sure I understand how they're being interpreted.<br /><br />Thank you!<!--content-->