I want to set cookies in laravel blade.php file, not in the controller. How can I set it?
Disclaimer: I will focus my answer on PHP and laravel.
Why not set in controller?
It would really help to know why you cannot / or do not want to set cookies using laravel's cookie Facade in the controller - eg. Cookie::queue, as it's very easy to do!
Here are two ways, from this source.
Via response:
return response(view('welcome'))->cookie('name','value',$min);
Via Queue: Cookie::queue(Cookie::make('name','value',$min)); return view('welcome');
Set-Cookie is a response header, not the body!
Assuming you would set these cookies in PHP , they need to come as part of a response header, and not part of the body (view). This is why you would need to set these in the controller, where you are sending a response!
If you try to use PHP functions to set cookies, you will be met with errors "headers have already been sent"
Per the docs: https://www.php.net/setcookie
setcookie() defines a cookie to be sent along with the rest of the HTTP headers. Like other headers, cookies must be sent before any output from your script (this is a protocol restriction). This requires that you place calls to this function prior to any output, including and tags as well as any whitespace.
To understand what this means, it's helpful to understand the structure of requests and responses:
Requests and Responses are made up of headers and possibly a body.
Note: You can see these in the network tab of your browser's dev tools.
The request headers are like meta data about the request that can tell the server what kind of content is being requested, and who is requesting.
The response headers are like meta data about the response returned that can tell the server what kind of content is being delivered, how long to cache it for, associated cookies that got set.
Example Request Headers:
Content-Type: 'application/json'
Content-Type: 'application/pdf'
Content-Type: 'text/html'
Content-Type: 'text/css'
User-Agent: 'Mozilla/5.0 (<system-information>) <platform> (<platform-details>) <extensions>'
Authorization: 'Bearer <token>'
Example Response Headers:
Content-Type as it may differ from what was requested
Expires: 'Wed, 07 Sep 2022 19:26:49 GMT'
Cross-Origin-Resource-Policy: 'cross-origin'
Date: 'Wed, 07 Sep 2022 19:26:49 GMT'
Content-Length: 0,
Set-Cookie: test_cookie=CheckForPermission; expires=Wed, 07-Sep-2022 19:41:49 GMT; path=/; domain=.doubleclick.net; Secure; HttpOnly; SameSite=none
Notably: - Set-Cookie - tells the browser to add these cookies to application storage (you can view these in application / storage tabs in dev tools)
The response header can have Set-Cookie, not the request header. This makes sense, as usually the cookie information is going to come from the "answer" (response) to the "question" (request) by way of performing some logic, eg - this user is authenticated, here's a cookie to keep their session in place.
Also: Secure & HTTP only Cookies
Cookies can get set with a few options - secure only, and http only. These mean that the cookie must be Set on secure connections (https) and the http only can come from a response and cannot be overridden by JavaScript adjusting (client side)
Example of options for Laravel's Cookie::queue facade:
// $name, $value, $minutes = 0, $path = null, $domain = null, $secure = false, $httpOnly = true
Cookie::queue($name, $value, $ttl, $path, $domain, $secure, $httpOnly);
ttl = "time to live" or how long until it expires eg. 2 minutes
Related
A centain web client that I need to support, is sending back the Cookies header to my application twice in the HTTP headers, this in turn is making PHP unable to read the correct value for the cookie thus ignoring the session.
Here is the relevant part of the request I am seeing:
GET / HTTP/1.1
Cache-Control: max-age=0
Accept-Language: en-US
Cookie: PHPSESSID=49af82ddf12740e6a35b15985e93d91a
Connection: Keep-Alive
Cookie: PHPSESSID=49af82ddf12740e6a35b15985e93d91a
[...] Other irrelevant headers
I have two questions:
Is that a PHP bug? or is the behavior undefined when the client sends that same header twice?
Is there a quick workaround to make things work without having to manually parse the HTTP headers so I can read the right value of the cookie (and session) in my application? Or should I manually parse the HTTP header to set the session to its correct value?
According to the HTTP spec, a double header simply concatenates the values together with a comma, making it:
Cookie: PHPSESSID=49af82ddf12740e6a35b15985e93d91a, PHPSESSID=49af82ddf12740e6a35b15985e93d91a
PHP should be able to parse the cookies, but the behavior of sessions is undefined when there are two session IDs.
I strongly recommend fixing the client. If that's not an option, you'll have to parse the headers manually.
i modified my previous code. you can see my previous post if your intersted setting cookie through curl
But here is a fresh beginning my new code looks linke this
i have a php file using curl like this
<?php
$ch=curl_init();
$url="http://localhost/javascript%20cookies/test_cookies.php";
curl_setopt($ch,CURLOPT_URL,$url);
curl_setopt($ch,CURLOPT_COOKIEFILE,dirname(__FILE__) . "/cookie.txt");
curl_setopt($ch,CURLOPT_FOLLOWLOCATION,1);
curl_exec($ch);
curl_close($ch);
?>
the file test_cookies.php looks like this
<?php
if($_COOKIE['user']==1)
{
header("Set-Cookie:user=1; color=blue");
header("Location:http://localhost/javascript%20cookies/test_cookies.html");
}
?>
the file test_cookies.html has some javascript that checks for cookies and if it finds those cookies then it displays the text accordingly.
the php file with curl code is sending the cookies and the test_cookies.php is setting the cookie and redirecting to the page test_cookies.html but this page is not receiving the cookies and thus it is not not showing the content accordingly.
can somebody tell me whats the problem now?
here are the headers i get displayed in firefox on setting CURLOPT_HEADER to true
HTTP/1.1 302 Found Date: Mon, 16 May 2011 15:03:59 GMT Server: Apache/2.2.14 (Win32) DAV/2 mod_ssl/2.2.14 OpenSSL/0.9.8l mod_autoindex_color PHP/5.3.1 mod_apreq2-20090110/2.7.1 mod_perl/2.0.4 Perl/v5.10.1 X-Powered-By: PHP/5.3.1 Set-Cookie: user=1; color=blue Location: http://localhost/javascript%20cookies/test_cookies.html Content-Length: 0 Content-Type: text/html HTTP/1.1 200 OK Date: Mon, 16 May 2011 15:03:59 GMT Server: Apache/2.2.14 (Win32) DAV/2 mod_ssl/2.2.14 OpenSSL/0.9.8l mod_autoindex_color PHP/5.3.1 mod_apreq2-20090110/2.7.1 mod_perl/2.0.4 Perl/v5.10.1 Last-Modified: Mon, 16 May 2011 12:13:24 GMT ETag: "11000000013d0c-493-4a363950a70f3" Accept-Ranges: bytes Content-Length: 1171 Content-Type: text/html
you can see that there are two set of headers displayed.is this because i am making 2 calls to header?
It is not clear what you are trying to achieve with the code. You'd get better help if you explain why you are doing this. It is probable that your approach is wrong and you could get the ultimate result with a different/simpler approach.
And now to answer your question, this is what happens:
From your browser, you send a GET request to curl.php (the name I use for your first file),
curl in that file checks cookie.txt and finds user=1, so it sends a GET request to test_cookies.php and sends the cookie with the request
test_cookies.php sees that user=1 is true, so it sends a header to curl.php and asks it to set two cookies: user=1 and color=blue (for the first cookie this is pointless, user=1 is already set, but let's ignore this as no harm is done)
You have not set CURLOPT_COOKIEJAR option, so when curl.php receives the set cookie header it does not give a damn (nothing happens)
Next, test_cookies.php sends a redirect header to curl.php, since you have set CURLOPT_FOLLOWLOCATION,1, curl.php sends another GET request, this time to get test_cookies.html
Content of test_cookies.html is returned to curl.php,
curl_exec($ch); causes the returned content (source of test_cookies.html) be echoed back to your browser,
Your browser parses what it received and the javascript is executed. It checks for a cookie named user and does not find one, so it displays content for when there is no cookie (because there isn't).
Now, you may wonder what happens if you add:
curl_setopt($ch,CURLOPT_COOKIEJAR,dirname(__FILE__) . "/cookie.txt");
What happens is that your cookie.txt will be updated in step 4 and will have two cookies; user=1 and color=blue. But this does NOT give you the result you expect. Because header("Set-Cookie:user=1; color=blue"); is instructing curl to set the cookie, and curl does this by storing the cookies in the file you specified in CURLOPT_COOKIEJAR option. So, even though you added that option, when you reach step 8 javascript will not find that cookie, because the browser you use does not know or care about your cookie.txt, it looks somewhere else to check if a cookie exists. In Google Chrome for instance the format is SQLite and for XP the cookies are stored in %USERPROFILE%\Local Settings\Application Data\Google\Chrome\User Data\Default\Cookies.
i will now explain what i was trying to do.
i had an html page that asked for some verification code and then it sent that verification code to a php script which on verifying the code set a cookie and redirected to the same html page.
the html page had some externally linked javascript which on checking the cookie value displayed the content of the page with some tweaking.
i am now writing the code for this
the html file with content and form
test_cookies.html
//some css,javascript and html and then a form
<form method="post" action="http://localhost/javascript%20cookies/test_cookies.php">
the php file which verifies the code
test_cookies.php
if($_POST['value']=="code")
setcookie("user",1);
if($_POST['value']!="code")
setcookie("user",1,time()-1);
header("Location:http://localhost/javascript%20cookies/test_cookies.html");
and now the php file with curl code
curl_cookies.php
<?php
$ch=curl_init();
$url="http://localhost/javascript%20cookies/test_cookies.php";
$post="value=code"; //here i have hard-coded the pst value for a demo but i could have got this from the user
curl_setopt($ch,CURLOPT_URL,$url);
curl_setopt($ch,CURLOPT_POST,1);
curl_setopt($ch,CURLOPT_POSTFIELDS,$post);
curl_setopt($ch,CURLOPT_HEADER,1);
curl_setopt($ch,CURLOPT_RETURNTRANSFER,1);
$res=curl_exec($ch);
curl_close($ch);
preg_match('/Location: (.*)\s/',$res,$location);
preg_match('/Set-Cookie: (.*)\s/',$res,$cookie);
$cookie=rtrim($cookie[0])."; path=/ "; //path needed to be changed because curl_cookies.php and test_cookies.html are in different directories.
header($cookie);
header($location[0]);
?>
this finally worked and the browser is displaying the tweaked content. this thing taught me a lot about http.
Thanks to all who helped me when i was in dark.
Attempting to submit a form with CURL, both via PHP and the command line. The response from the server consists of null content (the headers posted below).
When the same URL is submitted via a browser, the response consists of a proper webapge.
Have tried submitting the CURL request parameters via POST and GET via each of the following command line curl flags "-d" "-F" and "-G".
If the query string parameters are posted with "-d" flag, resulting header is:
HTTP/1.1 302 Moved Temporarily
Date: Thu, 02 Jun 2011 21:41:54 GMT
Server: Apache
Set-Cookie: JSESSIONID=DC5F435A96A353289F58593D54B89570; Path=/XXXXXXX
P3P: CP="CAO PSA OUR"
Location: http://www.XXXXXXXX.com/
Content-Length: 0
Connection: close
Content-Type: text/html;charset=UTF-8
Set-Cookie: XXXXXXXXXXXXXXXX=1318103232.20480.0000; path=/
If the query string parameters are posted with "-F" flag, the resulting header is:
HTTP/1.1 100 Continue
HTTP/1.1 500 Internal Server Error
Date: Thu, 02 Jun 2011 21:52:54 GMT
Server: Apache
Content-Length: 1677
Connection: close
Content-Type: text/html;charset=utf-8
Set-Cookie: XXXXXXXXXXXXXX=1318103232.20480.0000; path=/
Vary: Accept-Encoding
<html><head><title>Apache Tomcat/5.5.26 - Error report</title><style><!--H1 {font-family:Tahoma,Arial,sans-serif;color:white;background-color:#525D76;font-size:22px;} H2 {font-family:Tahoma,Arial,sans-serif;color:white;background-color:#525D76;font-size:16px;} H3 {font-family:Tahoma,Arial,sans-serif;color:white;background-color:#525D76;font-size:14px;} BODY {font-family:Tahoma,Arial,sans-serif;color:black;background-color:white;} B {font-family:Tahoma,Arial,sans-serif;color:white;background-color:#525D76;} P {font-family:Tahoma,Arial,sans-serif;background:white;color:black;font-size:12px;}A {color : black;}A.name {color : black;}HR {color : #525D76;}--></style> </head><body><h1>HTTP Status 500 - </h1><HR size="1" noshade="noshade"><p><b>type</b> Exception report</p><p><b>message</b> <u></u></p><p><b>description</b> <u>The server encountered an internal error () that prevented it from fulfilling this request.</u></p><p><b>exception</b> <pre>javax.servlet.ServletException: Servlet execution threw an exception<br>
</pre></p><p><b>root cause</b> <pre>java.lang.NoClassDefFoundError: com/oreilly/servlet/multipart/MultipartParser<br>
com.corsis.tuesday.servlet.mp.MPRequest.<init>(MPRequest.java:27)<br>
com.corsis.tuesday.servlet.mp.MPRequest.<init>(MPRequest.java:21)<br>
com.corsis.tuesday.servlet.TuesdayServlet.doPost(TuesdayServlet.java:494)<br>
javax.servlet.http.HttpServlet.service(HttpServlet.java:710)<br>
javax.servlet.http.HttpServlet.service(HttpServlet.java:803)<br>
</pre></p><p><b>note</b> <u>The full stack trace of the root cause is available in the Apache Tomcat/5.5.26 logs.</u></p><HR size="1" noshade="noshade"><h3>Apache Tomcat/5.5.26</h3></body></html>
Questions:
What might cause a server to respond different depending on the nature of the CURL request.
How to successfully submit request via CURL?
HTTP/1.1 100 Continue
I had problems associated with this header before. Some servers simply do not understand it. Try this option to override Expect header.
curl_setopt( $curl_handle, CURLOPT_HTTPHEADER, array( 'Expect:' ) );
To add to what Richard said, I have seen cases where servers check the User-Agent string and behave differently based on its value.
I have just had an experience with this and what fixed it was surprising. In my situation I was logging into a server so I could upload a file, have the server do work on it, and then download the new file. I did this in Chrome first and used the dev tools to capture over 100 HTTP requests in this simple transaction. Most are simply grabbing resources I don't need if I am trying to do all of this from the command line, so I filtered out only the ones I knew at a minimum I should need.
Initially this boiled down to a GET to set the cookie and log in with a username and password, a POST to upload the file, a POST to execute the work on the file, and a GET to retrieve the new file. I could not get the first POST to actually work though. The response from that POST is supposed to be information containing the upload ID, time uploaded, etc, but instead I was getting empty JSON lists even though the status was 200 OK.
I used CURL to spoof the requests from the browser exactly (copying the User-Agent, overriding Expect, etc) and was still getting nothing. Then I started arbitrarily adding in some of the requests that I captured from Chrome between the first GET and POST, and low and behold after adding in a GET request for the JSON history before the POST the POST actually returned what it was supposed to.
TL;DR Some websites require more requests after the initial log in before you can POST. I would try to capture a successful exchange between the server and browser and look at all of the requests. Some requests might not be as superfluous as the seem.
I have a basic PHP page being loaded through Varnish with a single ESI include that calls back to the server to set a cookie. The cookie is set with domain access and the like, but when called through ESI the cookie is never set. If you access the ESI include path directly, the cookie is set with no issue. I have even set my Varnish configuration to never cache anything, thinking the VCL could be killing the cookie.
This...
<esi:include src="/init.php?<?=http_build_query($_GET); ?>"></esi:include>
...includes this...
<?php
header("Cache-Control: no-cache, must-revalidate");
header("Expires: Sat, 26 Jul 1997 05:00:00 GMT");
setcookie('superman', 'clark kent', 0, '/', '.whatever.com');
?>
I'm new with Varnish and ESI, so I'm starting to wonder if this is a known limitation (either with ESI or with Varnish's ESI implementation), but I can't find any discussion of my problem online.
An interesting question which has been asked -but not answered- before ( Setting Cookies via ESI:include, how? ). I don't think you can do it this way. With ESI-include, the ESI processor makes a separate request and replaces a part from the body, not the header. In order to make your preferred set-cookie behavior work correctly, the ESI specification should specify how to 'merge' all set-cookie headers.
See chapter six of the ESI spec: http://www.w3.org/TR/esi-lang
When an ESI template is processed, a
separate request will need to be made
for each include encountered.
Implementations may use the original
request's headers (e.g., Cookie,
User-Agent, etc.) when doing so.
Additionally, response headers from
fragments (e.g., Set-Cookie, Server,
Cache-Control, Last-Modified) may be
ignored, and should not influence the
assembled page.
Could you try to convert your set-cookie header in a javascript set-cookie script? This could be included in the body...
I'm writing an "API" for a website which doesn't have it.
Basically, my PHP code logs into the website and grabs the data I need (two different transfers).
At login time, I'm getting a bit of a problem. The website sets a couple of cookies through HTTP, which I'm capturing using CURL's cookie mechanism.
This seems to work out nicely, except that they are also trying to set a cookie via javascript in that same response.
I don't need to parse the javascript since the cookie they set is entirely predictable.
What I need is to somehow tell CURL that this cookie exists, WHILE it stills maintains the other cookies.
Help? :)
After submitting the login details via curl POST, I get to these headers:
HTTP/1.1 200 OKDate: Fri, 20 Aug 2010 09:39:14 GMT
Server: Apache-Coyote/1.1
Content-Type: text/html;charset=ISO-8859-1
Content-Length: 492
Set-Cookie: JSESSIONID=5DE1F32B3668DABB408BBEA10C28DBD5.testmmf1; Path=/merchantlogin
Set-Cookie: loginType=M
Connection: close
And this is the page content:
<script type="text/javascript">
var nextyear = new Date();
nextyear.setFullYear(nextyear.getFullYear() + 1);
document.cookie = 'login=' + document.referrer + '; expires=' + nextyear.toGMTString();
</script>
Notice the Set-Cookie and document.cookie parts.
Generate cookie file via code, and before making request to location witch requires that cookie add it simply through setopt with option CURLOPT_COOKIEFILE
You could set the cookie using curl_setopt and the CURLOPT_COOKIE option first. Of course doing this will erase your other cookies, but they'll be gotten back, right?
If you could get a hold of the current value of CURLOPT_COOKIE, you could append your cookie with a semicolon. But PHP doesn't seem to have a curl_getopt function.