Nav: [Workbook](../workbook.md) :: [Generating Responses](../generating_response/generating_response.md) # Handling Cookies - [Cookie](#cookie) - [Cookie Porperties](#properties) - [Write and Read Cookies](#set_get) - [How to set a cookie](#set_cookie) - [How to read a cookie](#read_cookie) - [Examples](#examples) ## Cookie A [cookie](http://httpwg.github.io/specs/rfc6265.html) is a piece of data that can be stored in a browser's cache. If you visit a web site and then revisit it, the cookie data can be used to identify you as a return visitor. Cookies enable state information, such as an online shopping cart, to be remembered. A cookie can be short term, holding data for a single web session, that is, until you close the browser, or a cookie can be longer term, holding data for a week or a year. Cookies are used a lot in web client-server communication. - HTTP State Management With Cookies - Personalized response to the client based on their preference, for example we can set background color as cookie in client browser and then use it to customize response background color, image etc. Server send cookies to the client >Set-Cookie: _Framework=EWF; Path=/; Expires=Tue, 10 Mar 2015 13:28:10 GMT; HttpOnly%R Client send cookies to server >Cookie: _Framework=EWF ### Cookie properties - Comment: describe the purpose of the cookie. Note that server doesn’t receive this information when client sends cookie in request header. - Domain: domain name for the cookie. - Expiration/MaxAge: Expiration time of the cookie, we could also set it in seconds. (At the moment Max-Age attribute is not supported) - Name: name of the cookie. - Path: path on the server to which the browser returns this cookie. Path instruct the browser to send cookie to a particular resource. - Secure: True, if the browser is sending cookies only over a secure protocol, False in other case. - Value: Value of th cookie as string. - HttpOnly: Checks whether this Cookie has been marked as HttpOnly. - Version: ## Write and Read Cookies. To send a cookie to the client we should use the [HTTP_HEADER] class, and call ```h.put_cookie``` feature or ```h.put_cookie_with_expiration_date``` feature, see [How to set Cookies]() to learn the details, and the set it to response object [WSF_RESPONSE] as we saw previously. We will show an example. To Read incomming cookies we can read all the cookies with ``` cookies: ITERABLE [WSF_VALUE] -- All cookies. ``` which return an interable of WSF_VALUE objects corresponding to the cookies the browser has associated with the web site. We can also check if a particular cookie by name using ``` WSF_REQUEST.cookie (a_name: READABLE_STRING_GENERAL): detachable WSF_VALUE -- Field for name `a_name'. ``` feature. ### How to set Cookies Here we have the feature definitions to set cookies ```eiffel deferred class interface HTTP_HEADER_MODIFIER feature -- Cookie put_cookie (key, value: READABLE_STRING_8; expiration, path, domain: detachable READABLE_STRING_8; secure, http_only: BOOLEAN) -- Set a cookie on the client's machine -- with key 'key' and value 'value'. -- Note: you should avoid using "localhost" as `domain' for local cookies -- since they are not always handled by browser (for instance Chrome) require make_sense: (key /= Void and value /= Void) and then (not key.is_empty and not value.is_empty) domain_without_port_info: domain /= Void implies domain.index_of (':', 1) = 0 put_cookie_with_expiration_date (key, value: READABLE_STRING_8; expiration: DATE_TIME; path, domain: detachable READABLE_STRING_8; secure, http_only: BOOLEAN) -- Set a cookie on the client's machine -- with key 'key' and value 'value'. require make_sense: (key /= Void and value /= Void) and then (not key.is_empty and not value.is_empty) ``` Example of use: ```eiffel response_with_cookies (res: WSF_RESPONSE) local l_message: STRING l_header: HTTP_HEADER l_time: HTTP_DATE do create l_header.make create l_time.make_now_utc l_time.date_time.day_add (40) l_header.put_content_type_text_html l_header.put_cookie_with_expiration_date ("EWFCookie", "EXAMPLE",l_time.date_time, "/", Void, False, True) res.put_header_text (l_header.string) res.put_string (web_page) end ``` ### How to read Cookies Reading a particular cookie ```eiffel if req.cookie ("EWFCookie") = Void then do_something end ```` Reading all the cookies ```Eiffel across req.cookies as ic loop print (ic.item.name) end ``` ### Example The following EWF service shows a basic use of cookies. 1. It display a message to first-time visitors. 2. Display a welcome back message if a visitor return. 3. A visitor page, counting the number of visits to the page (track user access counts). 4. A cookie with an expiration of 120 seconds. 5. A cookie with an session level, valid in browser session. ```eiffel note description : "Basic Service that build a generic front to demonstrate the use of Cookies" date : "$Date$" revision : "$Revision$" class APPLICATION_EXECUTION inherit WSF_EXECUTION create make feature -- Basic operations execute (req: WSF_REQUEST; res: WSF_RESPONSE) -- Execute the incomming request local l_message: STRING l_header: HTTP_HEADER l_time: HTTP_DATE l_cookies: STRING l_answer: STRING do -- all the cookies create l_cookies.make_empty across req.cookies as ic loop l_cookies.append (ic.item.name) l_cookies.append("
") end if req.path_info.same_string ("/") then create l_header.make create l_answer.make_from_string (web_page) if req.cookie ("_EWF_Cookie") = Void then -- First access the the home page, find a cookie with specific name `_EWF_Cookie' l_answer.replace_substring_all ("$header_title", "Hey, thanks for access our cool site, this is your first acess") l_answer.replace_substring_all ("$cookies", l_cookies) create l_time.make_now_utc l_time.date_time.day_add (40) l_header.put_cookie_with_expiration_date ("_EWF_Cookie", "EXAMPLE",l_time.date_time, "", Void, False, True) else -- No a new access l_answer.replace_substring_all ("$header_title", "Welcome back, please check all the new things we have!!!") l_answer.replace_substring_all ("$cookies", l_cookies) end l_header.put_content_type_text_html l_header.put_content_length (l_answer.count) res.put_header_text (l_header.string) res.put_string (l_answer) elseif req.path_info.same_string ("/visitors") then create l_header.make create l_answer.make_from_string (visit_page) if req.cookie ("_visits") = Void then -- First access the the visit page, find a cookie with specific name `_visits' l_answer.replace_substring_all ("$visit", "1") l_answer.replace_substring_all ("$cookies", l_cookies) create l_time.make_now_utc l_time.date_time.day_add (40) l_header.put_cookie_with_expiration_date ("_visits", "1",l_time.date_time, "/visitors", Void, False, True) else if attached {WSF_STRING} req.cookie ("_visits") as l_visit then create l_time.make_now_utc l_time.date_time.day_add (40) l_answer.replace_substring_all ("$visit", (l_visit.value.to_integer + 1).out ) l_answer.replace_substring_all ("$cookies", l_cookies) l_header.put_cookie_with_expiration_date ("_visits", (l_visit.value.to_integer + 1).out,l_time.date_time, "/visitors", Void, False, True) end end create l_time.make_now_utc l_time.date_time.second_add (120) l_header.put_content_type_text_html -- This cookie expires in 120 seconds, its valid for 120 seconds l_header.put_cookie_with_expiration_date ("_Framework", "EWF",l_time.date_time, "/", Void, False, True) -- This is a session cookie, valid only to the current browsing session. l_header.put_cookie ("Session", "Cookie",Void, "/", Void, False, True) l_header.put_content_length (l_answer.count) res.add_header_text (l_header.string) res.put_string (l_answer) end end feature -- Home Page web_page: STRING = "[ EWF Handling Cookies

$header_title

Visitors

Cookies for the home page

$cookies
]" visit_page: STRING = "[ EWF Handling Visit Page

The number of visits is $visit

Cookies for the Visit page

$cookies

Back to Home
]" end ``` Nav: [Workbook](../workbook.md) :: [Generating Responses](../generating_response/generating_response.md)