Archives
Visitors
  • 38491This month:
  • 1364Today:
  • 13Currently online:



LeaseWeb CDN

Posts Tagged ‘php’

PHP asset proxy increases website availability

remote_assets

Don’t you hate it when your site does not work, because you linked jQuery from “code.jquery.com” and that site is suffering connection problems? This may also happen with stylesheets or with font files. To counter this problem (but not lose the convenience of remote loaded assets) I created  an “asset proxy” in PHP. It will cache the assets in a cache folder on your web server, so that you do not have to worry about downtime of other services. You can configure how often the cache should be refreshed. When the external source is not available during a refresh the stale cache files will be used and there is no downtime at all!

proxy_assets

Install asset-proxy.php in your webroot. Then replace all references in your HTML from:

 href="http://fonts.googleapis.com/css?family=Droid+Sans:400,700"

to:

 href="/asset-proxy.php/fonts.googleapis.com/css?family=Droid+Sans:400,700"

Make sure you edit the list of allowed hostnames in the header of the PHP file and that you set an appropriate refresh time (in seconds). If the assets are not available upon refresh the stale files are served.

<?php
// hostnames for which "GET" requests can be proxied over "HTTP" (no ssl)
$hostnames = array(
	'fonts.gstatic.com',
	'maxcdn.bootstrapcdn.com',
	'netdna.bootstrapcdn.com',
	'fonts.googleapis.com',
	'ajax.googleapis.com',
);

// maximum age of a file before being refreshed
$refresh_age = 24*3600;

// directory where the cache resides (should exist and not be served)
$cache_dir = '/tmp/cache';

// strip the leading "/proxy.php/" from the URL
$url = substr($_SERVER['REQUEST_URI'], strlen($_SERVER['SCRIPT_NAME'].'/'));

// if there is no URL specified show bad request error
if(!$url || !strpos($url,'/')){
	header('Bad Request', true, 400);
	exit;
}

// get the hostname which should be the first segment (until the first slash)
$hostname = substr($url, 0, strpos($url, '/'));

// if the hostname is not in the list of allowed hostnames show forbidden error
if (!in_array($hostname, $hostnames)) {
	header('Forbidden', true, 403);
	exit;
}

// calculate the cached filename and check whether it already exists
$filename = $cache_dir.'/'.md5($url);
$file_exists = file_exists($filename);

// get the file age if the file exists
if ($file_exists) {
	$file_age = time()-filemtime($filename);
}

// if cache exists and is fresh, let's read the file, else retrieve it with cURL
if ($file_exists && $file_age<$refresh_age) {
	$result = file_get_contents($filename);
} else {
	// set some headers on the cURL call to pretend we are a user
	$sent_headers = array();
	foreach (array('User-Agent','Accept','Accept-Language','Referer') as $header) {
		$key = 'HTTP_'.strtoupper(str_replace('-','_',$header));
		if (isset($_SERVER[$key])) {
			$sent_headers[] = $header.': '.$_SERVER[$key];
		}
	}

	// make sure we do net get chunked, deflated or gzipped content
	$sent_headers[] = 'Accept-Encoding: ';
	$sent_headers[] = 'Cache-Control: max-age=0';
	$sent_headers[] = 'Connection: keep-alive';

	// initialize cURL with the URL, our headers and set headers retrieval on
	$curl = curl_init('http://'.$url);
	curl_setopt_array($curl, array(
			CURLOPT_HEADER => true,
			CURLOPT_RETURNTRANSFER => true,
			CURLOPT_BINARYTRANSFER => true,
			CURLOPT_HTTPHEADER => $sent_headers
	));

	// execute cURL call and get status code
	$result = curl_exec($curl);
	$status = curl_getinfo($curl, CURLINFO_HTTP_CODE);
	curl_close($curl);

	if ($status == 200) {
		// file was successfully retrieved
		if (file_put_contents($filename, $result)===false) {
			// show error on unsuccessful write
			header('Internal Server Error', true, 500);
			exit;
		}
	} else if ($file_exists) {
		// serve stale
		$result = file_get_contents($filename);
		// reset refresh timer
		touch($filename);
	}

}

// split the message in raw headers and body
if (strpos($result,"\r\n\r\n")!==false) {
	list($raw_headers,$body) = explode("\r\n\r\n", $result, 2);
} else {
	list($raw_headers,$body) = array($result,'');
}

// convert raw headers into an array
$raw_headers = explode("\n", $raw_headers);

// parse raw headers into received headers
$received_headers = array();
foreach ($raw_headers as $h) {
	$h = explode(':', $h, 2);
	if (isset($h[1])) {
		$received_headers[$h[0]] = trim($h[1]);
	}
}

// set certain headers for the output
foreach (array('Content-Type','Content-Encoding') as $header) {
	if (isset($received_headers[$header])) {
		header($header.': '.$received_headers[$header]);
	}
}

// replace the absolute URL's in the output
foreach ($hostnames as $hostname) {
	$body = preg_replace('/(https?:)?\/\/'.str_replace('.','\.',$hostname).'\//',
		$_SERVER['SCRIPT_NAME'].'/'.$hostname.'/', $body);
}

// set the new content length properly
header('Content-Length: '.strlen($body));

// echo the contents of the body
echo $body;

Best thing since sliced bread.. ;-) And only 128 lines of PHP code! Source code is on Github:

https://github.com/mevdschee/asset-proxy.php

 

AmsterdamPHP talks Docker at LeaseWeb

amsterdam_phpNext Thursday (December 18th) Robin Speekenbrink will be talking at LeaseWeb about Docker and virtualization in his talk titled “Meet the Phockers”.

Docker is an open platform for developers and sysadmins to build, ship, and run distributed applications. Consisting of Docker Engine, a portable, lightweight runtime and packaging tool, and Docker Hub, a cloud service for sharing applications and automating workflows, Docker enables apps to be quickly assembled from components and eliminates the friction between development, QA, and production environments. As a result, IT can ship faster and run the same app, unchanged, on laptops, data center VMs, and any cloud.- docker.com

At LeaseWeb we are very proud to be hosting this event. It was quickly “sold out” even though we had 100 seats available. One of the reasons the talk is so popular is that LeaseWeb has about 40 software developers that are all very interested in Docker technology themselves. So from yesterday another 25 seats are available. On the meetup site you can sign up and reserve a seat!

The schedule

19:00 - 19:30: Welcome Drinks 
19:30 - 20:30: Talk 
20:30 - 20:45: Raffle 
20:45 - 23:00: Social, drinks and Pizza

The location

You can easily find the location of LeaseWeb as it is near the IKEA in Amsterdam and it is situated in the corner of the A2 and A9 highways. To get directions and find the exact location you can use Google Maps. Or enter the following address in your satnav:

LeaseWeb Netherlands B.V.
Luttenbergweg 8
1101 EC Amsterdam
tel +31 20 316 288

Free as in free beer…

We have ordered lots of large pizza’s and we have juice, soda, draft beer and wine in our canteen. So please visit us, meet the nice people at LeaseWeb and enjoy our beautiful building and free parking.

Meetup link: http://www.meetup.com/AmsterdamPHP/events/168161902/

10 reasons why PHP is better than Python

“There are only two kinds of languages: the ones people complain about and the ones nobody uses” – Bjarne Stroustrup,

People wonder: Did he really say that? Yes, he did. If you wonder who Bjarne Stroustrup is: He created the C++ programming language. Many people believe that Python is “pretty cool” and PHP is “really bad”. But as we all know, there is truth in the saying:

It’s a poor carpenter who blames his tools.

I believe both good and bad software can be written in any language. And I should probably also quote Joel Spolsky who calls “language wars” a “fruitless debate”. But nevertheless, if you program in PHP and run into one of these Python “evangelists”, then the following list may come in handy.

10 reasons why PHP is better than Python

  1. Python hosting, hard to find and expensive, while cheap PHP hosting is everywhere.
  2. Python cannot be mixed with HTML (needs a template library), while PHP can.
  3. Python has no proper encapsulation (private keyword), while PHP has.
  4. Python is hardly used in the real world, while something as big as Facebook is built on PHP.
  5. Python has a great community, but it is not comparable to PHP’s.
  6. Python has some books and tutorials, but PHP has way more of them.
  7. Python does not have the live docs (famous forum-like reference manual) like PHP has.
  8. Python does not have a steep learning curve, but PHP is still easier to learn.
  9. Python indentation for code blocks is prone to errors, while PHP uses curly braces.
  10. Python lexical scoping is a mess (‘global’ and ‘nonlocal’ keywords fix this), while PHP behaves as expected.

To wrap up

PHP has come a long way. Today it is a mature language that executes fairly speedy. Agreed that it has some quirky naming of it’s built-in functions, but hey.. that’s the price you pay for backwards compatibility.

Hint: Make sure to also check out this page on Python.org that is a good reference when comparing Python to PHP.

 

Wikipedia client for the command line

wped

Don’t you want the power of Wikipedia at your fingertips when you are logged into your Linux server? With this tool you can! It is build with PHP/Curl and is based on the Wikipedia API.

Wikipedia (open)search API

Wikipedia allows us to program software that takes advantage of their huge database of articles and definitions. They do this by exposing an API. I implemented their “opensearch” API call to search for articles. We are not doing anything unintended. Wikipedia made the API to allow people to build useful (or less useful, you decide) tools like this one. They do ask people to behave nicely in their Wikipedia API Etiquette, so read them and behave!

HTML to text

Instead of making my own wikitext parser, I used the Wikipedia “parse” API call. This call transforms articles from the internal wikitext format to HTML. I use the command line application “elinks” (alternative to the “lynx” text-mode web browser) to convert the HTML to text so it can be displayed on the console. This browser software is configured not to use the network or write files to disk, so you do not have to worry about your privacy.

How does this work?

It is a PHP script that uses Curl. The whole wped script is currently only 70 lines of code. The opensearch call is really easy to implement as you can see below:

$url = 'http://en.wikipedia.org/w/api.php';
$user_agent = 'Wped/0.1 (http://github.com/mevdschee/wped) PHP-Curl';

$curl = curl_init();
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
curl_setopt($curl, CURLOPT_USERAGENT, $user_agent);

$arguments = array(
  'action'=>'opensearch',
  'search'=>$search,
  'limit'=>3,
  'namespace'=>0,
  'format'=>'xml'
);

curl_setopt($curl, CURLOPT_URL, $url.'?'.http_build_query($arguments));
$results = simplexml_load_string(curl_exec($curl));

With this example it should be easy for you to start building your own Wikipedia tool, let me know if you did!

Quickstart

To install, just copy-paste the following lines in your console:

sudo apt-get install php5-cli php5-curl elinks
wget https://raw.githubusercontent.com/mevdschee/wped/master/wped.php -O wped
chmod 755 wped
sudo mv wped /usr/bin/wped

To uninstall use the following:

sudo rm /usr/bin/wped

Congratulations, now you can search for elephants using the “wped” command! And if you need the full article you can use the “-f” flag.

Yes! I need this, fast!

How can you have lived without it? Why would you ever use “wget”, when you can use “wped”? It adds so much fun to all your Wikipedia searches. The source and full instructions are available on my Github account: https://github.com/mevdschee/wped

 

PHP 5.3 is now officially end-of-life (EOL)

PHP 5.3 last regular release (5.3.27) was done in July 2013, back then we read the following statement on the release notes:

Please Note: This will be the last regular release of the PHP 5.3 series. All users of PHP are encouraged to upgrade to PHP 5.4 or PHP 5.5. The PHP 5.3 series will receive only security fixes for the next year. – php.net

So, back then it was not a big deal, since security fixes would be released for one more year (and a year seems very long). But last week PHP 5.3.29 was released and since that year has passed PHP 5.3 is now officially end-of-life (EOL). This means there are no further updates, not even security fixes, as you can read in the release notes:

This release marks the end of life of the PHP 5.3 series. Future releases of this series are not planned. All PHP 5.3 users are encouraged to upgrade to the current stable version of PHP 5.5 or previous stable version of PHP 5.4, which are supported till at least 2016 and 2015 respectively. – php.net

Ubuntu Linux users that run the still supported (and popular) 12.04 LTS release on their web server should not be worried too much: Ubuntu maintainers will backport security fixes until 2017. But running PHP 5.3 might be cumbersome, especially if you want to develop using the latest PHP frameworks or libraries. These often contain “array short syntax” and thus require PHP version 5.4 or higher . The simplest option is to upgrade your Ubuntu 12.04 LTS to 14.04 LTS, since that comes with PHP 5.5. If you decide to stay at 12.04 for a while, you will be stuck with 5.3.10 from the repo, unless you…

Upgrade PHP from 5.3 to 5.4 in Ubuntu 12.04 LTS

This is more or less the only option you have. Since it is not officially supported you have to install a PPA. I normally do not recommend this, since you could mess up your system badly and/or severely endanger the security of your machine. But I must admit that Ondřej Surý’s PPA is a very famous and widely used one, which would make it a bit more trusted. So, I will include the instructions, but you have been warned:

sudo apt-get install python-software-properties
sudo add-apt-repository ppa:ondrej/php5-oldstable
sudo apt-get update
sudo apt-get dist-upgrade

Why you should not upgrade PHP to 5.5 in Ubuntu 12.04 LTS

PHP 5.5 and it’s dependencies are provided by the “ppa:ondrej/php5″ repo. And even though PHP 5.5 is longer supported and more powerful than PHP 5.4, you should probably stick to PHP 5.4. The reason for this is that PHP 5.5 requires Apache 2.4, where Ubuntu 12.04 comes bundled with Apache 2.2 by default. This means that when you upgrade PHP 5.3 to PHP 5.5 you also have to upgrade Apache 2.2 to Apache 2.4 (as a dependency). This could break many things, but it will (most certainly) break your virtual host configuration. So this is something I can’t recommend unless you are really sure what you are doing. Do not upgrade PHP to version 5.5 without having a tested upgrade plan. I’m serious… be very very careful!