Monday, May 30, 2016

The Mechanics of Web Sessions

Web developers use sessions almost everyday, but not all know how it really works, this post will cover some important questions about web server sessions, so it would be easier to debug your session problems.


No TL;DR for you today, sorry, but here’s a table of contents.


What is a web server session?

A session in general is some data that’s shared between two or more devices.

A web server session is used to exchange connection-specific temporary information between the server and the browser for the duration of the browsing session.

A session is used to tell the server which client has sent the request so it knows what data it will send to that client.

What is a web server session, really?

A web server session is some data structure that usually stores key-value pairs of data that’s stored and managed on the web server, it can be stored in a file, cookie, database or other storage options (including the RAM).
That data structure, say, a file, is created for each user and stores whatever is the backend (PHP, Python, etc..) tell it to store, but most importantly it carries the session ID, that’s unique for each connection (browser session).

How exactly does that “exchange” happen?

As soon as you hit a web page, the server receives your request for that particular page, it sends you the page content along with your “randomly” generated session ID (usually in a cookie).
That cookie carries your session ID back and forth between all your requests for the current browsing session so that the server knows who you are and persists your information across subsequent requests.
So basically that sookie is like a fingerprint for your browser for the current session.

Screen Shot 2016-05-27 at 11.37.30 PM.png


The cookie name is different between languages and frameworks (In this image it’s the default Laravel session cookie name) , you can set its name to your liking, what matters is that its value is the session ID that server had assigned to your browser at that time.

Let’s take an example like when you log into an application, the server hands the session information to the backend language, e.g. PHP, so that it stores that you are logged in (stores your user ID that is in the database, for example) in the session so that you don’t have to login at every request.

Session exchange diagram


So, how does the server know which session file is mine?


At every request, your browser sends back your session ID (in the form of a cookie or in URL parameters, whichever is the method) to the server along with the request to the web page to tell the server that it’s really you from before.

The server compares the session ID you just sent it with the session IDs it has stored for all the clients and it gets your specific information and makes it available to your backend programming language to process the request (get your information from the database using the user ID in your session and feed that into you a user-specific profile page, for example) and send you back your requested page, and your session ID cookie with a Set-Cookie header.



Screen Shot 2016-05-28 at 12.13.52 AM.png


This goes on until the session is destroyed;

Logging out, closing the browser or a timeout, for example, are all session destroyers.

When does this “Session ID” get created?

In general, your session is created when there’s a mismatch between the session IDs that are exchanged between the browser and the server, including missing ID from either ends.

  • With the first page you open in a web application, the request for that web page is sent without the session ID cookie, so the server knows that it should start giving you a name (session ID) which you use after that to tell it that it’s the same you.
  • You open another browser (or use a new private window), explaining why in a moment.
  • The session is deleted on the server.

When I open another browser tab or window, why is the server still identifying me?

The session cookie is stored by the browser, usually the browser keeps this kind of information until you close it, so all tabs and windows of the same browser still have the cookie stored and accessible because it’s the same browsing sessions.

But when I open a private (incognito) window of the same browser, I’m not logged in, my session is not there.

According to browser specifications for private browsing and how it works, private browsing is treated as an independent entity, it’s an -almost- totally independent browsing session with an “empty cookie jar”, so it doesn't have access to your cookies from before.

“Remember me” ?

So, if the session ends when you close the browser window, how do sites that have a “remember me” checkbox save the session information even after closing the browser?

Session cookies don’t have an expiry date on them, so the browser knows that it should destroy it when it’s closed.

On the other hand, the “remember” me cookie has an expiration date in the future (say, after two weeks) so it keeps the cookie from being deleted when the browsing session ends.


That’s it. As usual, please correct my mistakes, point out missing information and ask questions.

References

Wednesday, May 25, 2016

"Unexpected token ILLEGAL" when getting markup from the server?

Getting “Unexpected token ILLEGAL“ (maybe “Unexpected EOF” in Safari)  when retrieving your HTML from the server and parsing it? Even worse the stack trace is pointing you to some weird place (in my case it’s some line column in jquery.min.js).
Newlines are to suspect here..
The story here is that I was retrieving a form markup with an ajax request from a PHP backend, that’s getting the data from MySQL and filling the form template with the result, sending the form to the browser then placing this markup into a div with jQuery ( $(“#somediv”).html(markup) ).
The form had a textarea and a script that compared the value of that field to some other value, and that was the problem, when the field (textarea value) had a newline, Javascript would just breakdown, so if you have a similar situation, read along..



Why is this happening

Javascript (and every other language for that matter, AFAIK) can’t have line breaks between the quotes of a string, that’s because when JS encounters a line break it will consider that new line an indication that it’s the end of a command (statement - piece of code) and proceeds to the next line imagining it’s a new command and that would make it treat the new quote character as an opening, not closing quote and boom.. that’s why we have the “\n” thingy.


The catch

JS recognizes the “\n” with no problems, but HTML does not, it has a special entity for the line break.
After investigating, I found out that PHP saves the new lines from the textarea as a vertical tab (ASCII code 013) and a backspace (ASCII code 010).
HTML understands the vertical tab (through a special entity) and that’s how newlines can be displayed in a textarea without problems.

I needed not to alter what’s being saved but rather change how it’s displayed.

The solution

The HTML version of a vertical tab is 
 so we need to replace every “013” ASCII character with it’s HTML version before sending it to the browser, we will also get rid of the backspace character because it would cause problems (ASCII code 010).

So, in PHP (in my case) write down the code that will do exactly that..
//Starting off with an empty string the will hold the address after modifications
$newAddress = "";
$address = $row['address']; //Address returned from the database query
//Loop through the string characters
for ($char = 0; $char < strlen($address); $char++) {
    //ord() gets the ASCII code for the current character
    if (ord($address[$char]) == 13){
        $newAddress .= ' &#013;';
    }
    //Getting rid of the backspace character
    elseif (ord($address[$char]) != 10){
        $newAddress .= $address[$char];
    }
}
//$row is what is being used to fill out the form template with data, so that's what’s being placed in the textarea and what’s being compared in the script
$row['address'] = $newAddress;


Just note that the address when used in the script will have &#013; in place of new lines (that shouldn’t be a problem though) .


That’s it, feel free to fill the gaps and ask questions.

Saturday, May 14, 2016

AngularJS with dynamically generated content

This post is about using Angular with dynamically loaded markup (in this particular case it was an entire form).

TL;DR

The problem

Angular can only interact with elements present at its bootstrap time, so it doesn’t know about new generated content from an ajax call for example.


The (real-life) situation is like this, we have a main page that has a button which makes an ajax request when clicked to get the form contents and inject the generated HMTL into a <div> element, no Angular, just jQuery, and yeah, I know it’s not cool, but I’ve mixed Angular and jQuery to solve this problem.
This was a template that must not be changed, and to complicate things further, the toolbar that has the “New entry” button is included with the items grid which - as you guessed- loads with an ajax request after the main page loads (document ready event) ..

The options here are to:
  1. Add the script tags to the form file (template).
  2. Add them to the toolbar that has the “New entry” button.
  3. Add them to the main page.

I’ve chosen the third approach because of the drawbacks of the other two approaches.

The first approach will result in multiple inclusions of the scripts, because every click on the button will inject the HTML of the form template which includes the scripts every time.

The second approach has the same problem, plus, Angular won't see the form as it shows because it loads dynamically, so no advantage here.

The third approach made most sense, it includes the scripts one time when the user clicks the menu entry to open that page, so the only problem here is making angular deal with the newly generated content.


The solution

  • Include the Angular and the app (module) scripts into the main page.
  • Assign the module and the main controller to the wrapper div which also contains a hidden textarea with the ngChange calling the function “recompile”, which we going to define in a moment.
  • After the Ajax request that gets the form contents, insert the generated markup into the textarea and invoke the change event, something like:
    $("#formcontent").val(data).change();

  • At the “mainCtrl” controller, define the “recompile” function:
$scope.recompile = function(){
              $("#the-form-div").html($compile($scope.formcontent)($scope));
              $scope.formcontent = "";
            }



As the Angular documentation mentions about the $compile service:

Compiles an HTML string or DOM into a template and produces a template function, which can then be used to link scope and the template together.

And: The compilation is a process of walking the DOM tree and matching DOM elements to directives.

So basically what’s happening here is the we tell Angular to inspect whatever is inside of the textarea and work its magic on it before showing that to the user.


That’s it, thanks.