The Internet is About to Become WAY Faster

Earlier this week, the big news in the tech space surrounded the completion of the HTTP/2 Spec.

Gibberish, gibberish, gibberish.

What does this mean for the internet? The short version is: it’s about to become way faster.

Faster is extremely important if you want to make money from traffic to your site. Or, you know, if you use the internet at all. No one wants to wait for a website that just sits there and spins while it’s trying to load. We all hate that. And importantly, Google hates that.

Several years ago, Google invented and implemented the SPDY protocol. Simply, SPDY allows for the compression and efficient transmission of requests between browser and server. I’ll get into the technical details later, but for the sake of summarizing why the Internet is about to get faster… Google’s SPDY technology is the cornerstone of HTTP/2.

Now that the spec is finalized, it goes to editorial for cleanup and publishing… but the nuts and bolts of the spec will not change going forward. That means browsers and servers can start rolling out these changes as soon as… today.

Technical explanation

If you are not interested in the technical explanation for HTTP/2, please skip to the next section. I don’t want you falling asleep and drooling on your keyboard.

In the original days of the internet, there was the HTTP/1.0 spec. This spec defined how clients (browsers) and servers communicated over a network. We still use 1.0 quite a bit today, though 1.1 is the current preferred.

When it comes to HTTP, the concept is simple… a client requests a resource (image, html, mp3, whatever) from a server, the web server interprets the request, goes back into a storage closet, finds the resource, has the requestor sign for it and then sends the resource on it’s way back to the client. A simple understanding is….

BROWSER: “Hey, server… can I get that image named image.jpg? You should find it in this folder.”

SERVER: “Sure, let me go look. Oh, here it is. There you go”

BROWSER: “Thanks, dude”

If the server can’t find the image in the directory, it sends the client a 404 (Not Found), but that’s just a sidenote.

HTTP/1.0’s Problem

The problem with HTTP/1.0 however, was that it only allowed for a single request on a single connection to the server. To put it in another way, The web page has 10 images on it. In order to get those 10 images from the server, it would have to send 10 requests. That creates a lot of requests for the server and if the server wasn’t optimized for that kind of capacity, it could crash… or at least be in the weeds. It was bad all around for bandwidth as well. All of those requests add up to high bandwidth costs!

So God gave us HTTP/1.1.

HTTP/1.1’s Problem

Given this inherent problem with HTTP/1.0, HTTP/1.1 enhanced the original spec by adding the concept of pipelining. Imagine, if you will, a highway tunnel. Generally, there’s no passing in a tunnel. While HTTP/1.0 only allowed a single car through the tunnel at a time, HTTP/1.1 allowed multiple cars in the tunnel, but dictated no passing. And because the web server on the other end of the tunnel can only process requests as they come in, you end up with a stacked up queue of requests waiting to get processed and… you still have the same problem where the server gets in the weeds and slows down.

In both the case of 1.0 and 1.1, server technology evolved to allow concurrency of requests. This gave us multiple lanes in the tunnel, but 1.1 still dictated no passing. So requests in one lane, had to stay in that lane but there could be more than one lane which allowed us to bandaid the inherent weakness in the HTTP/1.x stack.

Enter HTTP/2

When Google started giving SEO benefits to sites based on speed, they also ate their own dog food and invented SPDY. SPDY allows for compression of resources in a much more efficient way if both server and client supported it. It also allowed for single requests to get many resources at a time. That page that had 10 images and had to make 10 requests for those 10 images could now make a single request to get all 10 images at once. Efficiency, I tell you.

As with any working group, the task force that put together HTTP/2 had representation from Google. Google, as a good citizen, shared it’s knowledge and spec for SPDY with the working group and it became the basis of HTTP/2. In fact, Google will now eliminate SPDY in favor of HTTP/2.

In fact, clients are supporting HTTP/2 now. Well, a lot of them are anyway… and that’s because of Google’s implementation of SPDY. Internet Explorer 11+, Firefox 36+, and Chrome all implement SPDY-HTTP/2 support, but none are currently enabled by default. Safari and Mobile Safari will likely soon get the support.

Most web servers also implement SPDY-HTTP/2 with the exception of lighttpd.

What does it mean to me?

The new HTTP spec is probably not anything you need to worry about at this point. System administrators will want to make sure their web servers are up to date and their TLS certificates are upgraded. Though the working group does not require HTTP/2 to use TLS, I’d expect most server manufacturer’s to require them in their own implementation… for security reasons.

On the client side, HTTP/1.1 still works. The working group was very careful to ensure backwards compatibility with prior versions of the spec. So if your browser makes a 1.1 request to a 2.0 server, the server will still answer in 1.1 with the same limitations I described above.

As developers, we will most likely want to use 2.0 when we can. The finalization of the spec is so new that it remains unclear what that means yet. For instance, what does this mean for the WordPress WP_Http class? Probably nothing in the short terms, but I’d expect enhancements to start rolling in as optional “toys” for developers.

Are you a developer or engineer? What are your thoughts on the new spec?

TUTORIAL: Using WordPress’ Ajax API

WordPress has tons of APIs to do tons of things. It really does. One of the cool ones that I’ve been using a lot lately, has been around for a bit. It’s the Ajax API. Sure, you could write your own Ajaxy thing but why do that when WordPress lets you do it all very simply.

This tutorial will show you how to replicate the functionality that is presented in the “Like” button at Facebook. It assumes that you have WordPress set to require users to be logged in to take such actions. It wouldn’t make much sense for someone to not be logged in for such functionality. Obviously, you could do something else with Ajax (polls? Loading new content?) that doesn’t have the same assumption, but in this case… we’re assuming a user is logged in and the $current_user global is set.

Getting Started

Let’s start with the basic PHP class (you do write good object-oriented code, right?)

1
2
3
4
5
6
7
8
class My_Like_Button {

    function __construct()
    {
    }
}

$my_like_button = new My_Like_Button;

This code is just a basic skeleton that provides a constructor (the __construct() method, which I’ll use later. It also instantiates a new My_Like_Button object and assigns it to the $my_like_button variable for use in the global scope. Obviously, you can use whatever strikes your fancy for the class name or the global variable.

Building the HTML for the Like Button

Next, we need the basic HTML structure that will be used in our theme for the Like button. For the sake of simplicity, I’m not providing any CSS, but feel free to do as you wish. We need to add this as a new method in our class.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
function like_button()
{
    if( !is_user_logged_in() )
        return false;
       
    global $current_user;
       
    $html = '<form action="" method="post">
        <input type="hidden" name="like_post_id" id="like_post_id" value="'
. get_the_ID() .'">
        <input type="hidden" name="like_user_id" id="like_user_id" value="'
. $current_user->ID . '">
        <input type="button" name="like_this_post" id="like_this_post" value="Like" />
    </form>'
;
    return $html;
}

This form provides two hidden form fields using get_the_ID() and the $current_user object. Having done this (and after ensuring there is a logged in user), we can now drop this into our theme in the Loop as a template tag:

1
<?php echo $my_like_button->like_button(); ?>

Sending the Ajax Request with jQuery

This is useless by itself. We need something to handle the Ajax. But before we get there, we need to understand how Ajax works within the WordPress context.

All requests must go to wp-admin/admin-ajax.php. Forget the confusion about why you would send a front-end Ajax request to the back-end. You just do.

On the back-end, you’ll have to define functions that will hook into the Ajax API to let WordPress know how to handle the request. More on that in a minute. Let’s build some jQuery to send this to admin-ajax.php.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
function js()
{
    wp_enqueue_script( 'jquery' );
    wp_print_scripts();
    ?>
    <script>
    jQuery(document).ready(function(){
           
        jQuery('#like_this_post').click(function(){
            var like_post_id = jQuery('#like_post_id').val();
            var like_user_id = jQuery('#like_user_id').val();
           
            jQuery.post(
                '<?php echo get_option('siteurl') . '/wp-admin/admin-ajax.php' ?>',
                {
                    action      : 'register_like',
                    user_id     : like_user_id,
                    post_id     : like_post_id,
                    _wpnonce    : '<?php echo wp_create_nonce('nonce-register_like'); ?>',
                },
                function(response) {   
                    alert(response);
                }
            );
               
        });
    });
    </script>
    <?php
}

This is just a PHP function that we can use to throw some jQuery (using the .post() method for our Ajax call) into the head. Note the nonce. You must include this for security. Additionally, you must have an action set. The action is used by WordPress to route the Ajax request.

Finally, we’re passing two extra pieces of data – user_id which is the WordPress user ID and the post_id which is the WordPress post ID of the current $post object inside the Loop. Both of these are supplied in the hidden form fields we created earlier.

Let’s add a new method for hooks and call it in our constructor, so that hooks are executed when the object is instantiated:

1
2
3
4
5
6
7
8
9
function __construct()
{
    $this->hooks();
}
   
function hooks()
{
    add_action( 'wp_head', array( $this, 'js' ) );
}

Supplying the Ajax Handler

Having hooked the jQuery into WordPress, we now need something on the other end to handle the request and return something back to our page. For this, let’s create a method called handle_like().

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
function handle_like()
{
    global $wpdb;
    $user_id = (int) $_POST['user_id'];
    $post_id = (int) $_POST['post_id'];
       
    if( !is_user_logged_in() )
        return false;
       
    if( !wp_verify_nonce( $_POST['_wpnonce'], 'nonce-register_like' ) )
        die( 'Go away, asshole!' );
       
    /*
        Here is where we do some sort of database operation to associate
        the Like of the given post with the user who performed the action
       
        Make sure you check for errors. In order to return data, you must
        echo something that the originating page can see. True or false
        only makes sense on this page and not back there.
           
        Typically, you'd output some sort of JSON, XML or plain text.
    */

    $meta_id = add_post_meta( $post_id, 'user_liked', $user_id );
    if( !$meta_id )
        echo "Like not recorded";
    else
        echo "Like recorded";
    exit;
}

In this method, it’s important that all data be sanitized to avoid security problems. I’m performing the most basic of data security here by casting the $_POST variables for the users ID and the post ID to integers.

We’re also checking to make sure the user is logged in. This is why using the built in WordPress Ajax API is actually kind of important. If you build your own Ajax handler, there’s no way to reliable tie in to WordPress to use other APIs like the User API.

Finally, make sure you verify the nonce so you know the request is coming from a legitimate source.

The three security procedures I just listed will largely prevent SQL Injection, ensure authenticated users and eliminate the possibility of Cross Site Request Forgery (CSRF) and generally should be used in all WordPress plugin development.

Simply though, the above method takes the post ID, the user ID and creates a new record in the postmeta table. On success, it will print a success method readable by the original sending page and vica versa on failure.

Note: You must use die() or exit() at the end of the method to make sure the Ajax response exits properly.

Tying the Handler into WordPress

Now that we have a handler method to do our bidding, we need to make sure WordPress knows about it so it routes Ajax requests to the proper place. To do this, we leverage the wp_ajax_{$action} hook.

Remember earlier, while building the jQuery Ajax request, I mentioned that an action POST variable had to be set? WordPress looks to this variable to create a dynamic hook that we can use our new Ajax callback to hook into.

1
add_action( 'wp_ajax_register_like', array( $this, 'handle_like' ) );

Because our action in the js() method was set to register_like, the hook WordPress creates dynamically is wp_ajax_register_like and we can use that to hook our Ajax handler onto.

Wrapping it all Together

Easy right? Use jQuery to send data, wp-admin/admin-ajax.php to receive the Ajax request and pass it on to an appropriate handler function, and send data back to the original page. On the receiving end, you can use normal means to handle the returned data as you wish.

You can download the full code used here at Github.

WordPress.com is Hiring ;-)

Heh.

If you’re looking for work and can grok this, you might want to head over to WordPress.com and apply for a job. ;-)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
[root@technosailor.com ~]# telnet wordpress.com 80
Trying 76.74.254.126...
Connected to wordpress.com (76.74.254.126).
Escape character is '^]'.
GET / HTTP/1.1
Host: wordpress.com

HTTP/1.1 200 OK
Server: nginx
Date: Wed, 04 Feb 2009 22:00:10 GMT
Content-Type: text/html; charset=UTF-8
Transfer-Encoding: chunked
Connection: close
Last-Modified: Wed, 04 Feb 2009 21:59:53 +0000
Cache-Control: max-age=13, must-revalidate
Vary: Cookie
<strong>X-hacker: If you're reading this, you should visit automattic.com/jobs and apply to join the fun, mention this header.</strong>
X-Pingback: http://wordpress.com/xmlrpc.php
X-nananana: Batcache

Hat Tip: Sean Walberg