<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-298834846183725348</id><updated>2012-01-10T20:34:59.189+05:30</updated><category term='seo'/><category term='rest'/><category term='quality assurance'/><category term='apache'/><category term='i18n'/><category term='lighttpd'/><category term='web-server'/><category term='phing'/><category term='build'/><category term='cache'/><category term='functionality'/><category term='php'/><category term='html'/><category term='phpunit'/><category term='culture'/><category term='reverse proxy'/><category term='performance'/><category term='l10n'/><category term='symfony'/><category term='version control'/><category term='testing'/><category term='varnish'/><category term='web-service'/><title type='text'>Just another blog</title><subtitle type='html'>Blog about my work primarily and life occasionally.</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://arzala.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/298834846183725348/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://arzala.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Anirudhsinh Zala</name><uri>http://www.blogger.com/profile/16341197487842993303</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://2.bp.blogspot.com/-jEmJYVgTwk0/Tu4SjN7xOgI/AAAAAAAAABI/17BzjhETHMM/s220/me.jpg'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>13</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-298834846183725348.post-3645173024149653186</id><published>2010-02-01T13:01:00.000+05:30</published><updated>2012-01-10T20:23:23.472+05:30</updated><category scheme='http://www.blogger.com/atom/ns#' term='functionality'/><category scheme='http://www.blogger.com/atom/ns#' term='quality assurance'/><category scheme='http://www.blogger.com/atom/ns#' term='testing'/><category scheme='http://www.blogger.com/atom/ns#' term='php'/><title type='text'>Quality Assurance guidelines</title><content type='html'>&lt;div dir="ltr" style="text-align: left;" trbidi="on"&gt;&lt;div style="font-family: inherit;"&gt;&lt;span style="font-size: x-large;"&gt;#1 Introduction&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: small;"&gt;This document provides detailed information about Quality Assurance plan for web based software. Intended audience of this document consists of developers, testing team, project manager, stack-holders and clients. &lt;/span&gt;&lt;/div&gt;&lt;div style="font-family: inherit;"&gt;&lt;br /&gt;&lt;span style="font-size: x-large;"&gt;#2 Quality objectives&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;To achieve high quality of code and functionality to it's customers, team can design a detailed QA plan to be followed throughout development life cycle and post-development life span. To achieve this aim, following objectives should be&amp;nbsp; decided by development team.&lt;/div&gt;&lt;ul style="text-align: left;"&gt;&lt;li&gt;No untested code should be shipped to clients.&lt;/li&gt;&lt;li&gt; Test criteria must cover at least 75% of code for testing procedure.&lt;/li&gt;&lt;li&gt;Whatever has been tested is documented for various purposes.&lt;/li&gt;&lt;li&gt;Each functionality of the software must be tested according to requirement specifications and must run in most popular browsers and platforms in similar way.&lt;/li&gt;&lt;/ul&gt;&lt;div style="font-family: inherit; text-align: left;"&gt;&lt;span style="font-size: x-large;"&gt;#3 Management&lt;/span&gt;&lt;/div&gt;&lt;div style="font-family: inherit;"&gt;&lt;br /&gt;&lt;span style="font-size: large;"&gt;#3.1 Team&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Quality Assurance team primarily involves Test manager, Developers and Dedicated &amp;amp; Ad-hoc testers. It directly reports to Project manager and/or Development manager. &lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: large;"&gt;#3.2 Tasks and Responsibilities&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;QA team performs following tasks.&lt;/div&gt;&lt;ol style="text-align: left;"&gt;&lt;li&gt;Doing unit testing;&lt;/li&gt;&lt;li&gt; Doing functionality testing;&lt;/li&gt;&lt;li&gt; Doing usability testing;&lt;/li&gt;&lt;li&gt; Managing testing documentation;&lt;/li&gt;&lt;li&gt; Managing testing guidelines;&lt;/li&gt;&lt;li&gt; Reviewing test cases;&lt;/li&gt;&lt;li&gt; Doing continuous testing for core code;&lt;/li&gt;&lt;li&gt; Providing training to new members;&lt;/li&gt;&lt;/ol&gt;&lt;div style="font-family: inherit; text-align: left;"&gt;Breakdown of above tasks by team members is as follows; &lt;/div&gt;&lt;ul style="text-align: left;"&gt;&lt;li&gt;Developers do unit testing of code and make sure that it doesn't break even after making changes in it for new/updated features;&lt;/li&gt;&lt;li&gt; Dedicated and Ad-hoc testers then test those newly added/updated features in various browsers and tools to make sure that features behave according to requirement specifications;&lt;/li&gt;&lt;li&gt; Test manager checks created unit &amp;amp; functional tests and re-run them as and when needed. He also writes complex test cases to test code and features from various aspects like stress, load bearing, sanity etc.&lt;/li&gt;&lt;li&gt; Test manager is also responsible for preparing testing plans and guidelines for existing and new testers. Test manager also manages documentation of test cases and suits in repository for proof of quality control and easier access.&lt;/li&gt;&lt;li&gt; Development and Test manager together work for running unit tests continuously on test server for consistent quality check.&lt;/li&gt;&lt;li&gt; Training to new tester is usually provided by Test manager as and when needed during development life cycle.&lt;/li&gt;&lt;/ul&gt;&lt;div style="font-family: inherit; text-align: left;"&gt;Details about each task has been provided in following sections. &lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: x-large;"&gt;#4 Testing overview&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Software testing is the process used to help identify the correctness, completeness, security, and quality of developed computer software. Testing is a process of technical investigation, performed on behalf of stakeholders, that is intended to reveal quality-related information about the product with respect to the context in which it is intended to operate. &lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: large;"&gt;#4.1 Unit testing&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;When it comes to source code, unit testing of code is performed in order to be sure that there is no problem at code level. In unit testing, unit is known as a part of code which can be a function, a method or a whole class. In short, unit testing tests code of software into various pieces. Hence successful unit testing shows that software is now ready for functional testing.&lt;br /&gt;&lt;br /&gt;PHPUnit is a member of the &lt;a href="http://en.wikipedia.org/wiki/XUnit"&gt;xUnit family of testing frameworks&lt;/a&gt; and provides both a framework that makes the writing of tests easy as well as the functionality to easily run the tests and analyse their results. &lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: large;"&gt;#4.2 Functionality testing&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Purpose of functionality testing is to test whole system (or software sometimes) using automatic and manual tools. Whole system may include PHP code, JS code, HTML etc. In this type of testing, various components of software are tested together. Software like &lt;a href="http://seleniumhq.org/projects/ide/"&gt;selenium&lt;/a&gt; is used to perform functionality testing. &lt;br /&gt;&lt;br /&gt;Selenium IDE is an integrated development environment for Selenium tests. It is implemented as a Firefox extension, and allows you to record, edit, and debug tests. &lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: large;"&gt;#4.3 User (Usability) testing&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Usability testing is for measuring how well people can use some human-made object (such as a web page, a computer interface, a document, or a device) for its intended purpose, i.e. usability testing measures the usability of the object. Usability testing focuses on a particular object or a small set of objects, whereas general human-computer interaction studies attempt to formulate universal principles. Software like &lt;b&gt;ab&lt;/b&gt; and &lt;b&gt;mysqlprofile&lt;/b&gt; can be used to perform usability testing. &lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: x-large;"&gt;#5 Deliverables&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;QA deliverables include testing guidelines, manual and automated test cases, statistical and coverage reports and overall documentation related to QA. These are well organized and kept in version control for concerned project's application.&lt;/div&gt;&lt;br /&gt;&lt;div style="font-family: inherit; text-align: left;"&gt;&lt;span style="font-size: x-large;"&gt;#6 Testing Guidelines&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Testing guidelines and goals help achieve highest standards in quality control. They have been prepared to assist developers and testers to write effective test cases and to document them for various purposes. &lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: large;"&gt;#6.1 Unit testing&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;To read unit testing related guidelines and principles, read section #4 in &lt;a href="http://arzala.blogspot.com/2009/05/unit-testing-guidelines.html" target="_blank"&gt;this document&lt;/a&gt;.&lt;/div&gt;&lt;div style="font-family: inherit; text-align: left;"&gt;&lt;br /&gt;&lt;span style="font-size: large;"&gt;#6.2 Functionality testing&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;To read functional testing related guidelines and principles, read section #4 in &lt;a href="http://arzala.blogspot.com/2009/02/functional-testing-guidelines.html" target="_blank"&gt;this document&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: x-large;"&gt;#7 Review process&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Review of test cases is checking test cases by test colleagues and/or test manager in order to make sure that those are correct or any misunderstandings in the requirements or anything missed out or not. Since review is a continuous process, test manager regularly checks previously designed test cases and re-run them whenever needed. &lt;/div&gt;&lt;ol style="text-align: left;"&gt;&lt;li&gt;Review process comprises following things: &lt;/li&gt;&lt;li&gt;Completeness- Do test cases contain enough conditions of code and features to be tested?&lt;/li&gt;&lt;li&gt; Accuracy- Are test cases accurately defined and logical? Are there missing elements? &lt;/li&gt;&lt;li&gt; Testable- Are test cases testable?&lt;/li&gt;&lt;/ol&gt;&lt;div style="font-family: inherit; text-align: left;"&gt;&lt;span style="font-size: x-large;"&gt;#8 Continuous testing&lt;/span&gt;&lt;/div&gt;&lt;div style="font-family: inherit; text-align: left;"&gt;&lt;br /&gt;Continuous testing uses excess cycles on a workstation to continuously run regression tests in the background, providing rapid feedback about test failures as source code is edited. It reduces the time and energy required to keep code well-tested, and prevents regression errors from persisting uncaught for long periods of time.&lt;/div&gt;&lt;div style="font-family: inherit; text-align: left;"&gt;&lt;br /&gt;For more information about continuous testing, please refer &lt;a href="http://arzala.blogspot.com/2009/05/phing.html" target="_blank"&gt;this document&lt;/a&gt;. &lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: x-large;"&gt;#9 Training&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Training is important part of any department during software development life cycle. Test manager regularly provides training to QA team to improve testing procedure and to make it as effective as possible.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: x-large;"&gt;#10 References&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: small;"&gt;&lt;a href="http://phing.info/trac/"&gt;http://phing.info/trac/&lt;/a&gt;&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&lt;/div&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/298834846183725348-3645173024149653186?l=arzala.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://arzala.blogspot.com/feeds/3645173024149653186/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=298834846183725348&amp;postID=3645173024149653186' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/298834846183725348/posts/default/3645173024149653186'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/298834846183725348/posts/default/3645173024149653186'/><link rel='alternate' type='text/html' href='http://arzala.blogspot.com/2010/02/quality-assurance-guidelines.html' title='Quality Assurance guidelines'/><author><name>Anirudhsinh Zala</name><uri>http://www.blogger.com/profile/16341197487842993303</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://2.bp.blogspot.com/-jEmJYVgTwk0/Tu4SjN7xOgI/AAAAAAAAABI/17BzjhETHMM/s220/me.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-298834846183725348.post-4740050840247371388</id><published>2009-07-17T13:01:00.000+05:30</published><updated>2012-01-10T20:24:27.827+05:30</updated><category scheme='http://www.blogger.com/atom/ns#' term='build'/><category scheme='http://www.blogger.com/atom/ns#' term='phing'/><category scheme='http://www.blogger.com/atom/ns#' term='php'/><category scheme='http://www.blogger.com/atom/ns#' term='phpunit'/><title type='text'>PHP project build system</title><content type='html'>&lt;div dir="ltr" style="text-align: left;" trbidi="on"&gt;&lt;span style="font-size: x-large;"&gt;#1 Pre-requisites&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Before reading this document, it is required to read &lt;a href="http://arzala.blogspot.com/2009/05/unit-testing-guidelines.html" target="_blank"&gt;unit testing guidelines&lt;/a&gt;&lt;a href="https://gforge2.remres.com/docman/index.php?group_id=157&amp;amp;selected_doc_group_id=253&amp;amp;language_id=1"&gt;&lt;/a&gt;, which is part of this package.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: x-large;"&gt;#2 PHPUnit, CVS and Phing&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;For a typical web based software, our main requirements are to automate several routine tasks like unit testing, updating latest data from version control, loading packages on different servers, cleaning up log files and performing other daily routine task to save manual work.&lt;br /&gt;&lt;br /&gt;Hence here we will have brief look at how &lt;b&gt;Phing&lt;/b&gt; can be used to automate some of the above mentioned tasks. But before that let's see what Phing is and how it works.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: large;"&gt;#2.1 What is Phing&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.phing.info/"&gt;Phing&lt;/a&gt; (PHing Is Not GNU make) is a project build system based on &lt;a href="http://ant.apache.org/"&gt;Apache Ant&lt;/a&gt;. In the context of PHP, where it is not required to build and compile sources, the intention of Phing is to ease the packaging, deployment, and testing of applications. For these tasks, Phing provides numerous out-of-the-box operation modules ("tasks") and an easy-to-use, object-oriented model for adding our own custom tasks. &lt;br /&gt;Phing can be installed using the PEAR Installer, as shown in the following command line:&lt;br /&gt;&lt;br /&gt;&lt;div style="color: #a64d79; font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;$ pear channel-discover pear.phing.info&lt;/div&gt;&lt;div style="color: #a64d79; font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;$ pear install phing/phing&lt;/div&gt;&lt;br /&gt;For other modes of installation and more details read &lt;a href="http://phing.info/docs/guide/current/"&gt;Phing documentation&lt;/a&gt;. &lt;br /&gt;&lt;i&gt;Note: Please do not forget to install other dependencies also that Phing might ask during it's installation.&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: large;"&gt;#2.2 How it works&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Phing uses XML buildfiles that contain a description of the things to do. The buildfile is structured into targets (groups of task/s) that contain the actual commands to perform (e.g. commands to copy a file, delete a directory, perform a DB query, etc.). So, to use Phing, we would first write our buildfile and then run phing specifying the target in buildfile that we want to execute.&lt;br /&gt;&lt;br /&gt;&lt;div style="color: #a64d79; font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;$ phing -f [mybuildfile.xml] [mytarget]&lt;/div&gt;&lt;br /&gt;By default Phing will look for a buildfile named &lt;b&gt;build.xml&lt;/b&gt; (so you don't have to specify the buildfile name unless it is not build.xml) and if no target is specified Phing will try to execute the default target, as specified in the &lt;b&gt;&lt;project&gt;&lt;/project&gt;&lt;/b&gt; tag.&lt;br /&gt;&lt;br /&gt;A valid Phing buildfile has the following basic structure: &lt;br /&gt;&lt;ol style="text-align: left;"&gt;&lt;li&gt;The document prolog, &lt;/li&gt;&lt;li&gt;Exactly one root element called , &lt;/li&gt;&lt;li&gt;Several Phing type elements (i.e. , , etc.), &lt;/li&gt;&lt;li&gt;One or more elements containing built-in or user defined Phing task elements (i.e. , , etc). &lt;/li&gt;&lt;/ol&gt;It is beyond the scope of this document, to explain above structure. Hence please read &lt;a href="http://phing.info/docs/guide/current/"&gt;phing documentation&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: large;"&gt;#2.3 Phing and automated testing&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Phing has several built in tasks to perform various operations. Some of them, for our purpose, are &lt;b&gt;exec, delete, mkdir, coverage-setup, phpunit, phpunitreport&lt;/b&gt; and &lt;b&gt;coverage-report&lt;/b&gt;. &lt;br /&gt;&lt;ol style="text-align: left;"&gt;&lt;li&gt;exec task can be used to execute any command of OS environment and applications; &lt;/li&gt;&lt;li&gt;delete can be used to remove files/folders; &lt;/li&gt;&lt;li&gt;mkdir to make new directories; &lt;/li&gt;&lt;li&gt;phpunit to run unit tests created by developers (as described in &lt;a href="http://arzala.blogspot.com/2009/05/unit-testing-guidelines.html" target="_blank"&gt;this document&lt;/a&gt;); &lt;/li&gt;&lt;li&gt;phpunitreport to generate report about unit tests; &lt;/li&gt;&lt;li&gt;coverage-setup and coverage-report tasks are for providing detailed report of code-coverage analysis. &lt;/li&gt;&lt;/ol&gt;&lt;span style="font-size: large;"&gt;#2.5 Agile documentation&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Continuous testing using Phing is performed everyday on test server and 2 types of documentation is generated at following locations for every project; &lt;br /&gt;&lt;ol style="text-align: left;"&gt;&lt;li&gt;tests/unittests/reports/index.html and &lt;/li&gt;&lt;li&gt;tests/unittests/reports/coverage/index.html (for reporting purpose) &lt;/li&gt;&lt;/ol&gt;Since this document is generated anytime on the fly and gets updated after every run, it doesn't require to add them into version control.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: large;"&gt;#2.6 Guidelines about using Phing &lt;/span&gt;&lt;br /&gt;&lt;ol style="text-align: left;"&gt;&lt;li&gt;Phing has vast application areas hence in beginning it is used for limited tasks only like updating local repository from CVS, running unit tests, code analysis, packaging and unpacking files etc. Later it will be expanded to handle more complex tasks. &lt;/li&gt;&lt;li&gt;Build management system such as Phing, should not be used by individual developers as it affects whole system. Hence it's care is taken by dedicated test/project/development manager. &lt;/li&gt;&lt;li&gt;Phing can be extended to create custom tasks also. But that requires extensive study of it's existing functionality. &lt;/li&gt;&lt;/ol&gt;&lt;span style="font-size: x-large;"&gt;#3 Links&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://phing.info/docs/guide/current/"&gt;http://phing.info/docs/guide/current/&lt;/a&gt;&lt;a href="http://phing.info/docs/guide/current/"&gt;&lt;br /&gt;&lt;/a&gt;&lt;a href="http://www.phpunit.de/manual/3.3/en/build-automation.html#build-automation.phing"&gt;http://www.phpunit.de/manual/3.3/en/build-automation.html#build-automation.phing&lt;/a&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/298834846183725348-4740050840247371388?l=arzala.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://arzala.blogspot.com/feeds/4740050840247371388/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=298834846183725348&amp;postID=4740050840247371388' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/298834846183725348/posts/default/4740050840247371388'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/298834846183725348/posts/default/4740050840247371388'/><link rel='alternate' type='text/html' href='http://arzala.blogspot.com/2009/05/phing.html' title='PHP project build system'/><author><name>Anirudhsinh Zala</name><uri>http://www.blogger.com/profile/16341197487842993303</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://2.bp.blogspot.com/-jEmJYVgTwk0/Tu4SjN7xOgI/AAAAAAAAABI/17BzjhETHMM/s220/me.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-298834846183725348.post-7365872041878319462</id><published>2009-05-26T13:02:00.000+05:30</published><updated>2011-12-30T12:08:06.991+05:30</updated><category scheme='http://www.blogger.com/atom/ns#' term='functionality'/><category scheme='http://www.blogger.com/atom/ns#' term='quality assurance'/><category scheme='http://www.blogger.com/atom/ns#' term='testing'/><category scheme='http://www.blogger.com/atom/ns#' term='php'/><category scheme='http://www.blogger.com/atom/ns#' term='phpunit'/><title type='text'>Unit testing guidelines</title><content type='html'>&lt;div dir="ltr" style="text-align: left;" trbidi="on"&gt;&lt;div&gt;&lt;div style="text-align: left;"&gt;&lt;/div&gt;&lt;span style="font-size: x-large;"&gt;#1 Introduction&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;This document provides detailed information about how to unit test code of PHP based software. Intended audience of this document consists of developers, testing team, project manager and stack-holders.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: x-large;"&gt;#2 What is unit testing&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Unit testing&lt;/b&gt; is a software verification and validation method in which a programmer tests that individual units of source code are fit for use. A unit is the smallest testable part of an application. In procedural programming a unit may be an individual program, function, procedure, etc., while in object-oriented programming, the smallest unit is a class, which may belong to a base/super class, abstract class or derived/child class. &lt;br /&gt;&lt;br /&gt;The goal of unit testing is to isolate each part of the program and to show that the individual parts are correct. Unit testing provides a strict, written contract that the piece of code must satisfy. As a result, it affords several benefits. In this article we will follow &lt;a href="http://www.phpunit.de/"&gt;PHPUnit&lt;/a&gt; as a unit testing software.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: large;"&gt;#2.1 Advantages of unit testing&lt;/span&gt;&lt;br /&gt;&lt;div id="Section2.1"&gt;&lt;/div&gt;&lt;br /&gt;#2.1.1 Facilitates change &lt;br /&gt;&lt;br /&gt;Unit testing allows the programmer to refactor code at a later date, and make sure the module still works correctly (i.e. regression testing). This provides the benefit of encouraging programmers to make changes to the code since it is easy for the programmer to check if the piece is still working properly. Good unit test design produces test cases that cover all paths through the unit with attention paid to loop conditions. In continuous unit testing environments, through the inherent practice of sustained maintenance, unit tests will continue to accurately reflect the intended use of the executable and code in the face of any change. Depending upon established development practices and unit test coverage, up-to-the-second accuracy can be maintained. &lt;br /&gt;&lt;br /&gt;#2.1.2 Simplifies integration &lt;br /&gt;&lt;br /&gt;Unit testing helps eliminate uncertainty in the units themselves and can be used in a bottom-up testing style approach. By testing the parts of a program first and then testing the sum of its parts, integration testing becomes much easier. &lt;br /&gt;&lt;br /&gt;A heavily debated matter exists in assessing the need to perform manual integration testing. While an elaborate hierarchy of unit tests may seem to have achieved integration testing, this presents a false sense of confidence since integration testing evaluates many other objectives that can only be proved through the human factor. Some argue that given a sufficient variety of test automation systems, integration testing by a human test group is unnecessary. Realistically, the actual need will ultimately depend upon the characteristics of the product being developed and its intended uses. &lt;br /&gt;&lt;br /&gt;#2.1.3 Documentation &lt;br /&gt;&lt;br /&gt;Unit testing provides a sort of "living document". Clients and other developers looking to learn how to use the module can look at the unit tests to determine how to use the module to fit their needs and gain a basic understanding of the API. &lt;br /&gt;&lt;br /&gt;Unit test cases embody characteristics that are critical to the success of the unit. These characteristics can indicate appropriate/inappropriate use of a unit as well as negative behaviors that are to be trapped by the unit. A unit test case, in and of itself, documents these critical characteristics, although many software development environments do not rely solely upon code to document the product in development. &lt;br /&gt;&lt;br /&gt;Ordinary documentation, on the other hand, is more susceptible to drifting from the implementation of the program and will thus become outdated (e.g. design changes, feature creep, relaxed practices to keep documents up to date). &lt;br /&gt;&lt;br /&gt;#2.1.4 Separation of interface from implementation &lt;br /&gt;&lt;br /&gt;Because some classes may have references to other classes, testing a class can frequently spill over into testing another class. A common example of this is classes that depend on a database: in order to test the class, the tester often writes code that interacts with the database. This is a mistake, because a unit test should never go outside of its own class boundary. As a result, the software developer abstracts an interface around the database connection, and then implements that interface with their own mock object. This results in loosely coupled code, minimizing dependencies in the system. &lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: large;"&gt;#2.2 Limitations of unit testing &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Unit testing will not catch every error in the program. By definition, it only tests the functionality of the units themselves. Therefore, it will not catch integration errors, performance problems or any other system-wide issues. In addition, it may not be easy to anticipate all special cases of input the program unit under study may receive in reality. Unit testing is only effective if it is used in conjunction with other software testing activities. &lt;br /&gt;&lt;br /&gt;It is unrealistic to test all possible input combinations for any non-trivial piece of software. A unit test can only show the presence of errors; it cannot show the absence of errors. Though these two limitations apply to any form of software test.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: x-large;"&gt;#3 PHPUnit &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;PHPUnit is an excellent unit testing software for PHP programming language based softwares, which is derived from JUnit software (in Java technology). To learn PHPUnit, well understanding of OOP is must. &lt;br /&gt;&lt;br /&gt;Testing with PHPUnit is not a totally different activity from what you should already be doing. It is just a different way of doing it. The difference is between testing, that is, checking that your program behaves as expected, and performing a battery of tests, runnable code-fragments that automatically test the correctness of parts (units) of the software. These runnable code-fragments are called unit tests. &lt;br /&gt;&lt;br /&gt;It is to be clearly kept in mind that unit testing should be performed as soon as coding is finished, and not after days and month. When software's code gets changed, corresponding tests should also get changed and tested. &lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: large;"&gt;#3.1 How PHPUnit works&lt;/span&gt;&lt;br /&gt;&lt;div id="Section3.1"&gt;&lt;/div&gt;&lt;br /&gt;PHPUnit API has several built in methods to perform various kind of testing on your given code. Developer first write certain code according to requirement of software. Then he will need to create certain test cases (or suits) using PHPUnit's built in classes and finally to test those test cases (or suits) to be sure that designed code works properly. &lt;br /&gt;&lt;ol style="text-align: left;"&gt;&lt;li&gt;Test cases (or suits) are nothing but PHP scripts that test code of software using PHPUnit's built in tests. Hence there are 3 components in unit testing: &lt;/li&gt;&lt;li&gt;Software's code&lt;/li&gt;&lt;li&gt; PHPUnit's built in tests and &lt;/li&gt;&lt;li&gt; Test cases (or suits).&lt;/li&gt;&lt;/ol&gt;&lt;span style="font-size: large;"&gt;#3.2 Installing PHPUnit &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;PHPUnit should be installed using the &lt;a href="http://pear.php.net/"&gt;PEAR Installer&lt;/a&gt;. This installer is the backbone of PEAR, which provides a distribution system for PHP packages, and is shipped with every release of PHP since version 4.3.0. &lt;br /&gt;&lt;br /&gt;The PEAR channel (pear.phpunit.de) that is used to distribute PHPUnit needs to be registered with the local PEAR environment:&lt;br /&gt;&lt;span style="color: #a64d79; font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #a64d79; font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;$ pear channel-discover pear.phpunit.de&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;This has to be done only once. Now the PEAR Installer can be used to install packages from the PHPUnit channel:&lt;span style="color: #a64d79; font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #a64d79; font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&lt;br /&gt;# pear install phpunit/PHPUnit&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;After the installation you can find the PHPUnit source files inside your local PEAR directory; the path is usually &lt;b&gt;/usr/lib/php/PHPUnit&lt;/b&gt;. &lt;br /&gt;&lt;br /&gt;Although using the PEAR Installer is the only supported way to install PHPUnit, you can install PHPUnit manually. For manual installation, do the following: &lt;br /&gt;&lt;ul style="text-align: left;"&gt;&lt;li&gt;Download a release archive from http://pear.phpunit.de/get/ and extract it to a directory that is listed in the include_path of your php.ini configuration file.&lt;/li&gt;&lt;/ul&gt;&lt;ul style="text-align: left;"&gt;&lt;li&gt; Prepare the phpunit script: &lt;/li&gt;&lt;/ul&gt;Rename the phpunit.php script to phpunit.&lt;br /&gt;Replace the @php_bin@ string in it with the path to your PHP command-line interpreter (usually /usr/bin/php).&lt;br /&gt;Copy it to a directory that is in your path and make it executable (chmod +x phpunit). &lt;br /&gt;&lt;ul style="text-align: left;"&gt;&lt;li&gt;Prepare the PHPUnit/Util/Fileloader.php script: &lt;/li&gt;&lt;/ul&gt;Replace the @php_bin@ string in it with the path to your PHP command-line interpreter (usually /usr/bin/php).&lt;/div&gt;&lt;span style="font-size: small;"&gt;After successful installation&lt;/span&gt; of PHPUnit, you can use command phpunit &lt;b&gt;/PATH/TO/TESTSCRIPT&lt;/b&gt; to run your tests. For all the available options of this command type &lt;b&gt;phpunit -–help&lt;/b&gt;.&lt;br /&gt;&lt;div style="text-align: left;"&gt;&lt;br /&gt;&lt;span style="font-size: large;"&gt;#3.3 How to learn and use PHPUnit &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Road map of learning and using PHPUnit has been shown below. &lt;br /&gt;&lt;ol&gt;&lt;li&gt;Get good understanding of OOP.&lt;/li&gt;&lt;li&gt; Read whole documentation of PHPUnit software to understand what it is and how it works.&lt;/li&gt;&lt;li&gt; Install PHPUnit to build up testing environment.&lt;/li&gt;&lt;li&gt; Study code of all scripts of PHPUnit software even if at first time, you don't understand much.&lt;/li&gt;&lt;li&gt; Having look at the testing examples provided by PHPUnit, understand how unit testing works.&lt;/li&gt;&lt;li&gt; Now try to build your own test cases of software on which you are working.&lt;/li&gt;&lt;li&gt; After having enough experience of building test cases, try to build test suit that can perform all test at once (which is the goal of the unit testing).&lt;/li&gt;&lt;li&gt; Try to build more complex and fully automated test suits using PHPUnit's extensions and other utilities or by building your own custom extensions according to requirements of your software. &lt;/li&gt;&lt;/ol&gt;To create test cases in your live projects, you may require to reorganize your classes into packages and sub packages. For test cases, you may create new folder test/unittest in your project's main directory and then create test cases (scripts) according to packages and sub packages defined above.&lt;br /&gt;&lt;span style="font-size: large;"&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;br /&gt;&lt;span style="font-size: x-large;"&gt;#4 Guidelines and principles &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Here are guidelines and principles of implementing unit testing to be followed by developer tram. &lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: large;"&gt;#4.1 How to write test cases&lt;/span&gt;&amp;nbsp;&lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;ol&gt;&lt;li&gt;Best way to write test cases is to study an example given here and some more from PHPUnit documentation.&lt;/li&gt;&lt;li&gt; 1st part of test script contains code to include necessary files/fixtures, while 2nd part contain test case class.&lt;/li&gt;&lt;li&gt; In beginning develop simple tests for single method or collection of methods. After having certain experience, build more complex test cases. Finally go to suite level which provides fully automated testing environment.&lt;/li&gt;&lt;li&gt; Create readable tests - write comments in Asserts and in UT. Write descriptive method names (even very long). Use local variables in Asserts. Use constants. UT should be readable like a book. &lt;/li&gt;&lt;li&gt; Test cases must cover at least &lt;b&gt;75%&lt;/b&gt; of code. However this will be shown in reports generated by Phing when such tests are run from there. The danger of not implementing a unit test on every method is that the coverage may be incomplete. Just because we don't test every method explicitly doesn't mean that methods can get away with not being tested.&lt;/li&gt;&lt;li&gt; You may require configuration parameters for database, paths and locations of other dependent software to run unit tests. For that there has been created a common file &lt;b&gt;tests/unittests/config.inc.php&lt;/b&gt; which would be included in your test cases. Since it is common file or all tests, it is normally managed test/build manager. Hence if it is required to update that file, test manager must be consulted.&lt;/li&gt;&lt;li&gt; Moreover this file should be included in your test cases as &lt;b&gt;include_once&lt;/b&gt; or &lt;b&gt;require_once&lt;/b&gt; constructs only otherwise there will be warnings/errors of duplication of code while running all tests together as suite from build system.&lt;/li&gt;&lt;li&gt; If you find difficulties in creating/running tests cases for any of your class method etc., it means it requires regression that is to re-organize structure of class/class package to be able to test them in proper way.&lt;/li&gt;&lt;li&gt; Since &lt;b&gt;private&lt;/b&gt; methods of class can not be tested directly, it's corresponding public method should be tested. However every private method always has a parent public method which uses that private method. For more information visit Links sections.&lt;/li&gt;&lt;li&gt; The concepts that you may need to be consider while building test cases (or suits) are &lt;b&gt;Test-first programming&lt;/b&gt;, &lt;b&gt;Code-coverage analysis&lt;/b&gt;, &lt;b&gt;Refactoring&lt;/b&gt;, &lt;b&gt;Incomplete tests, Agile documentation, Debugging Tests&lt;/b&gt; etc.&lt;/li&gt;&lt;/ol&gt;&lt;span style="font-size: large;"&gt;#4.2 How to organize and run them &lt;/span&gt;&lt;br /&gt;&lt;ol style="text-align: left;"&gt;&lt;li&gt;Developers should maintain hierarchy of classes as well as their equivalent test cases in same way. So for example if class file is grouped as &lt;b&gt;Validate/Numeric.php&lt;/b&gt; then it's corresponding test case should also be grouped as &lt;b&gt;Validate/NumericTest.php&lt;/b&gt; inside folder &lt;b&gt;tests/unittests&lt;/b&gt;. Moreover name of test case class should also follow name of class that is to be tested. Same is true for phpDocumentator tags in test script. That is; tests scripts must be maintained as any other code- like Keep It Simple, Stupid (KISS) &lt;/li&gt;&lt;li&gt;Fixtures (such as images, data files etc.) of test cases should be kept in same folder where test case/s reside/s. However for larger contents, they can be put in separate folder.&lt;/li&gt;&lt;li&gt; All test cases are to be run from project's base directory only as shown in earlier example. This is necessary because it is required to generate agile documentation of unit tests cases and their classes.&lt;/li&gt;&lt;/ol&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-size: large;"&gt;#4.3 Testing instructions &lt;/span&gt;&lt;/div&gt;&lt;ol style="text-align: left;"&gt;&lt;li&gt;Test cases should not be designed in such a way that they require specific order of execution; that is they must run independent of other implementation.&lt;/li&gt;&lt;li&gt; Test cases like to test Mail system, Database, File-system etc. requires additional setup apart from test script. Instructions about such setup and dependencies should clearly be mentioned in text file (like README.txt) inside corresponding test case's package. Such instructions can also contain information about how to run tests cases, other prerequisites, dependencies etc. wherever applicable.&lt;/li&gt;&lt;li&gt; While overall instructions are to be kept at &lt;b&gt;tests/unittests/README.txt&lt;/b&gt; file only.&lt;/li&gt;&lt;/ol&gt;&lt;span style="font-size: large;"&gt;#4.4 Scope of unit testing &lt;/span&gt;&lt;br /&gt;&lt;ol style="text-align: left;"&gt;&lt;li&gt;The crucial issue in constructing a unit test is scope. If the scope is too narrow, then the tests will be trivial and the objects might pass the tests, but there will be no design of their interactions.&lt;/li&gt;&lt;li&gt; Likewise, if the scope is too broad, then there is a high chance that not every component of the new code will get tested. The programmer is then reduced to testing-by-poking-around, which is not an effective test strategy.&lt;/li&gt;&lt;li&gt; It is recommended to write test cases for logical part only i.e static code/data need not to get tested. For complex test cases such as for Database, Mailing etc., it may require certain environmental settings. For that, concerned higher positioned person can be contacted for availability of it.&lt;/li&gt;&lt;/ol&gt;&lt;div style="text-align: left;"&gt;Bottom line of unit testing is that: it all depends upon the test case that you create. The better the cases, that covers all possible areas to be tested, the more worth the test is. If your test is poor, you wont yield advantages of unit testing.&lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;br /&gt;&lt;span style="font-size: large;"&gt;#4.5 What tests should be written&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;While doing unit testing, it is important to know that what kind of tests should be done. There has been provided some insight about type of some tests.&lt;/div&gt;&lt;ol&gt;&lt;li&gt;All positive test: This set of tests ensures that everything works as expected. &lt;/li&gt;&lt;li&gt;All failure test: Use these tests on a one-by-one basis to ensure that every failure or exception case works. &lt;/li&gt;&lt;li&gt;Positive sequence tests: This set of tests ensures that calls in the correct order work as expected. &lt;/li&gt;&lt;li&gt;Negative sequence tests: This set of tests ensures that when calls are made out of order, they fail. &lt;/li&gt;&lt;li&gt;Load tests: When appropriate, you can perform a small set of tests to determine that the performance of those tests is within an expected range. For example; 500 mails should be sent within 10-15 seconds. &lt;/li&gt;&lt;li&gt;Resource tests: These tests ensure that the application program interface (API) properly allocates and frees resources-- for example, opening, writing, and closing a file-based API several times in a row to ensure that no files remain open. &lt;/li&gt;&lt;li&gt;Callback tests: For APIs that have callback methods, these tests ensure that the code runs properly if callbacks are not defined. In addition, these tests ensure that the code runs properly when callbacks are defined but behave inappropriately or generate exceptions.&lt;/li&gt;&lt;/ol&gt;&lt;div style="text-align: left;"&gt;First 4 types of tests are must for every test-case. Rest can be implemented according to requirements in code.&lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;br /&gt;&lt;span style="font-size: large;"&gt;#4.6 Unit testing in the context of team &lt;/span&gt;&lt;/div&gt;&lt;ol style="text-align: left;"&gt;&lt;li&gt;Developers should do unit testing of their developed libraries and dependent libraries only, i.e they don't require to do unit testing of whole library since other code might have other requirement/dependency about which they are not aware of. That means test-suite should be run by Test/Project/Development manager only.&lt;/li&gt;&lt;li&gt; Above positioned persons can use build tools like &lt;b&gt;phing&lt;/b&gt; to automate unit testing process, whenever there are changes in code, without manually running every time. Procedure of using Phing in unit testing and other tasks has been mentioned &lt;a href="http://tbd/" target="_blank"&gt;in this document&lt;/a&gt;.&lt;/li&gt;&lt;li&gt; No untested code should be committed to version control, that is each package should have corresponding test cases.&lt;/li&gt;&lt;/ol&gt;&lt;div style="text-align: left;"&gt;&lt;/div&gt;&lt;span style="font-size: large;"&gt;#4.7 Re-usability of test cases/data&lt;/span&gt;&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Although it may seem like a good idea to throw random data at an interface, try to avoid it because the data is hard to debug. If data is generated randomly on each invocation, you may get an error on one pass that you don't get on another. If your test requires random data, generate the data in a file, then use that file on every run. In this way, you can have noisy data, but still be able to debug errors.&lt;/li&gt;&lt;li&gt; In unit tests since each test case is tightly attached to particular piece of code, it is difficult to write re-usable test cases. However whenever possible, test cases/data should be made re-usable and hence should be kept in test library in order to re-use them for other projects.&lt;/li&gt;&lt;li&gt; To create such library, Version control system can be used to store them in organized way under namespace like unit_test_library. And underneath that, there can be created several pages to describe nature of test case/data and how to use it in other projects. Similar practice can be used for functional test cases.&lt;/li&gt;&lt;/ol&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-size: x-large;"&gt;#5 Links &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.phpunit.de/manual/3.3/en/index.html"&gt;http://www.phpunit.de/manual/3.3/en/index.html&lt;/a&gt;&lt;a href="http://www.phpunit.de/manual/3.3/en/index.html"&gt;&lt;br /&gt;&lt;/a&gt;&lt;a href="http://www.acm.org/ubiquity/views/t_burns_1.html"&gt;http://www.acm.org/ubiquity/views/t_burns_1.html&lt;/a&gt;&lt;a href="http://www.acm.org/ubiquity/views/t_burns_1.html"&gt;&lt;br /&gt;&lt;/a&gt;&lt;a href="http://www.simplifytheweb.com/files/presentation.ppt"&gt;http://www.simplifytheweb.com/files/presentation.ppt&lt;/a&gt;&lt;a href="http://www.simplifytheweb.com/files/presentation.ppt"&gt;&lt;br /&gt;&lt;/a&gt;&lt;a href="http://readyset.tigris.org/nonav/templates/test-suite.html"&gt;http://readyset.tigris.org/nonav/templates/test-suite.html&lt;/a&gt;&lt;a href="http://readyset.tigris.org/nonav/templates/test-suite.html"&gt;&lt;br /&gt;&lt;/a&gt;&lt;a href="http://stackoverflow.com/questions/34571/whats-the-best-way-of-unit-testing-private-methods"&gt;http://stackoverflow.com/questions/34571/whats-the-best-way-of-unit-testing-private-methods&lt;/a&gt;&lt;a href="http://stackoverflow.com/questions/34571/whats-the-best-way-of-unit-testing-private-methods"&gt;&lt;br /&gt;&lt;/a&gt;&lt;a href="http://stackoverflow.com/questions/643898/mocking-methods-used-in-static-methods-phpunit"&gt;http://stackoverflow.com/questions/643898/mocking-methods-used-in-static-methods-phpunit&lt;/a&gt;&lt;a href="http://stackoverflow.com/questions/643898/mocking-methods-used-in-static-methods-phpunit"&gt;&lt;br /&gt;&lt;/a&gt;&lt;a href="http://stackoverflow.com/questions/243274/best-practice-unit-testing-abstract-classes"&gt;http://stackoverflow.com/questions/243274/best-practice-unit-testing-abstract-classes&lt;/a&gt;&lt;a href="http://stackoverflow.com/questions/243274/best-practice-unit-testing-abstract-classes"&gt;&lt;br /&gt;&lt;/a&gt;&lt;a href="http://www.artima.com/weblogs/viewpost.jsp?thread=203994"&gt;http://www.artima.com/weblogs/viewpost.jsp?thread=203994&lt;/a&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/298834846183725348-7365872041878319462?l=arzala.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://arzala.blogspot.com/feeds/7365872041878319462/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=298834846183725348&amp;postID=7365872041878319462' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/298834846183725348/posts/default/7365872041878319462'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/298834846183725348/posts/default/7365872041878319462'/><link rel='alternate' type='text/html' href='http://arzala.blogspot.com/2009/05/unit-testing-guidelines.html' title='Unit testing guidelines'/><author><name>Anirudhsinh Zala</name><uri>http://www.blogger.com/profile/16341197487842993303</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://2.bp.blogspot.com/-jEmJYVgTwk0/Tu4SjN7xOgI/AAAAAAAAABI/17BzjhETHMM/s220/me.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-298834846183725348.post-2183673969158138311</id><published>2009-02-05T13:00:00.000+05:30</published><updated>2011-12-30T15:26:31.715+05:30</updated><category scheme='http://www.blogger.com/atom/ns#' term='quality assurance'/><category scheme='http://www.blogger.com/atom/ns#' term='testing'/><title type='text'>Functional testing guidelines</title><content type='html'>&lt;div dir="ltr" style="text-align: left;" trbidi="on"&gt;&lt;div style="text-align: left;"&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-size: x-large;"&gt;#1 Introduction&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;This document provides detailed information about how to do functional testing of a web based software. Intended audience of this document consists of testing team, developers, project manager and stack-holders.&lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;Please read document &lt;a href="http://arzala.blogspot.com/2010/02/quality-assurance-guidelines.html" target="_blank"&gt;quality assurance guidelines&lt;/a&gt; before reading this document.&lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-size: large;"&gt;#2 What is Functional Testing?&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;a href="http://www.blogger.com/blogger.g?blogID=298834846183725348"&gt;&lt;/a&gt;Functional testing is a testing strategy, which needs little or no need of internal design or code etc. The types of testing under this strategy are totally based/focused on the testing for requirements and functionality of the work product/software application. Functionality testing (FT) is sometimes also called as Black Box testing, Opaque Testing, Behavioral Testing, Closed Box Testing etc.&lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;The base of the FT strategy lies in the selection of appropriate data as per functionality and testing it against the functional specifications in order to check for normal and abnormal behavior of the software.&lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;In order to implement FT Strategy, the tester is needed to be thorough with the requirement specifications of the system and as a user, should know, how the system should behave in response to the particular action.&lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;FT works on TDD methodology, so It should be created once the testers exercised the code for completed stories (functionalities) to verify that functional requirements had been met. It should be synchronized with functionality of the project.&lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-size: large;"&gt;#2.1 Advantages &lt;/span&gt;&lt;/div&gt;&lt;ol style="text-align: left;"&gt;&lt;li&gt;Tester needs little or no knowledge of implementation, including specific programming languages. &lt;/li&gt;&lt;li&gt;Tester and programmer are independent of each other. &lt;/li&gt;&lt;li&gt;Tests are done from a user's point of view. &lt;/li&gt;&lt;li&gt;Will help to expose any ambiguities or inconsistencies in the specifications. &lt;/li&gt;&lt;li&gt;Test cases can be designed as soon as the specifications are complete.&lt;/li&gt;&lt;/ol&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-size: large;"&gt;#2.2 Disadvantages &lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;/div&gt;&lt;ol style="text-align: left;"&gt;&lt;li&gt;Only a small number of possible inputs can actually be tested, to test every possible input stream would take nearly forever. &lt;/li&gt;&lt;li&gt;Without clear and concise functional requirement specifications, test cases are hard to design. &lt;/li&gt;&lt;li&gt;There may be unnecessary repetition of test inputs if the tester is not informed of test cases the programmer has already tried. &lt;/li&gt;&lt;li&gt;May leave many program paths untested. &lt;/li&gt;&lt;li&gt;Cannot be directed toward specific segments of code which may be very complex (and therefore more error prone). &lt;/li&gt;&lt;/ol&gt;&lt;div style="text-align: left;"&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-size: large;"&gt;#3 Implementation&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;For web based software, test cases are first designed into HTML format for reporting, documentation, verification then their corresponding test cases are recorded and executed using &lt;a href="http://selenium.openqa.org/"&gt;selenium&lt;/a&gt; software.&lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;Selenium is an open source tool to do automated functional tests for web-based applications. It is based on java scripting to a large extent. It’s simplicity and robustness makes it an excellent candidate for introducing automated functional testing in our project.&lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;While Selenium-IDE operates as a Firefox add-on and provides an easy-to-use interface for developing and running individual test cases or entire test suites. It has a recording feature, which will keep account of user actions as they are performed and store them as a reusable script to play back. It also has a context menu (right-click) integrated with the Firefox browser, which allows the user to pick from a list of assertions and verifications for the selected location. Selenium-IDE also offers full editing of test cases for more precision and control.&lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;Hence there will be 2 types of artifacts for functional test cases: &lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;/div&gt;&lt;ol style="text-align: left;"&gt;&lt;li&gt;Designed test cases in HTML format. &lt;/li&gt;&lt;li&gt;Corresponding Selenium test case. &lt;/li&gt;&lt;/ol&gt;&lt;div style="text-align: left;"&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-size: x-large;"&gt;#4 Guidelines and principles&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;QA team should follow below guidelines and principles for designing, executing and documenting functional test cases.&lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-size: large;"&gt;#4.1 Designing test cases &lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;/div&gt;&lt;ol style="text-align: left;"&gt;&lt;li&gt;Test cases are directly mapped Functional Requirement Specification. Hence each FRS should have corresponding test case.&lt;/li&gt;&lt;li&gt;Test cases should be written in enough detail that they could be given to a new team member who would be able to quickly start to carry out the tests and find defects.&lt;/li&gt;&lt;li&gt;Test cases should be first designed in HTML format as shown in following table. That is; there have to be sections; Unique ID, Purpose, URL, Prerequisites (optional), Test data, Steps, Notes/Question (optional). After that each test case will be recorded and executed using Selenium IDE.&lt;/li&gt;&lt;li&gt;The crucial issue in constructing functional test case is selection of range of input data. If range is too narrow, then the tests will be trivial and the objects might pass the tests.&lt;/li&gt;&lt;/ol&gt;&lt;div style="text-align: left;"&gt;&lt;a href="http://www.blogger.com/blogger.g?blogID=298834846183725348"&gt;&lt;/a&gt; &lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-size: small;"&gt;#4.1.1 Test case format&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;table border="1" cellpadding="3" cellspacing="0"&gt; &lt;colgroup&gt;&lt;col width="51*"&gt;&lt;/col&gt; &lt;col width="205*"&gt;&lt;/col&gt; &lt;/colgroup&gt;&lt;tbody&gt;&lt;tr&gt;  &lt;th bgcolor="#e6e6e6" colspan="2" width="100%"&gt;&lt;div class="western"&gt;UniqueTestCaseID: Test Case Title&lt;/div&gt;&lt;/th&gt; &lt;/tr&gt;&lt;tr&gt;  &lt;th bgcolor="#e6e6e6" width="20%"&gt;&lt;div class="western"&gt;Purpose:&lt;/div&gt;&lt;/th&gt;  &lt;td width="80%"&gt;&lt;div class="western"&gt;Short sentence or two about the aspect of the   system is being tested. If this gets too long, break the test case   up or put more information into the feature descriptions.&lt;/div&gt;&lt;/td&gt; &lt;/tr&gt;&lt;tr&gt;  &lt;th bgcolor="#e6e6e6" width="20%"&gt;&lt;div class="western"&gt;URL:&lt;/div&gt;&lt;/th&gt;  &lt;td width="80%"&gt;&lt;div class="western"&gt;URL where test is to be performed.&lt;/div&gt;&lt;/td&gt; &lt;/tr&gt;&lt;tr&gt;  &lt;th bgcolor="#e6e6e6" width="20%"&gt;&lt;div class="western"&gt;Prerequisites:&lt;/div&gt;&lt;/th&gt;  &lt;td width="80%"&gt;&lt;div class="western"&gt;Assumptions that must be met before the test   case can be run. e.g., &lt;i&gt;logged in&lt;/i&gt;, &lt;i&gt;guest login allowed&lt;/i&gt;,   &lt;i&gt;user testuser exists&lt;/i&gt;.&lt;/div&gt;&lt;/td&gt; &lt;/tr&gt;&lt;tr&gt;  &lt;th bgcolor="#e6e6e6" width="20%"&gt;&lt;div class="western"&gt;Test Data:&lt;/div&gt;&lt;/th&gt;  &lt;td width="80%"&gt;&lt;div class="western"&gt;List of variables and their possible values   used in the test case. You can list specific values or describe   value ranges. The test case should be performed once for each   &lt;i&gt;combination&lt;/i&gt; of values. These values are written in set   notation, one per line, like;&lt;/div&gt;&lt;div class="western"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="western"&gt;loginID = {Valid loginID, invalid loginID,   valid email, invalid email, empty}&lt;/div&gt;&lt;div class="western"&gt;password = {valid, invalid, empty}&lt;/div&gt;&lt;/td&gt; &lt;/tr&gt;&lt;tr&gt;  &lt;th bgcolor="#e6e6e6" width="20%"&gt;&lt;div class="western"&gt;Steps:&lt;/div&gt;&lt;/th&gt;  &lt;td width="80%"&gt;&lt;div class="western" style="margin-bottom: 0.2in;"&gt;Steps to carry out   the test. See &lt;i&gt;step formatting rules&lt;/i&gt; below.&lt;/div&gt;&lt;ol&gt;&lt;li&gt;&lt;div class="western"&gt;visit LoginPage&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div class="western"&gt;enter userID&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div class="western"&gt;enter password&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div class="western"&gt;click login&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div class="western"&gt;see the terms of use page&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div class="western"&gt;click agree radio button at page bottom&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div class="western"&gt;click submit button&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div class="western"&gt;see PersonalPage&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div class="western"&gt;verify that welcome message is correct    username&lt;/div&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/td&gt; &lt;/tr&gt;&lt;tr&gt;  &lt;th bgcolor="#e6e6e6" width="20%"&gt;&lt;div class="western"&gt;Notes and Questions:&lt;/div&gt;&lt;/th&gt;  &lt;td width="80%"&gt;&lt;div class="western"&gt;If any&lt;/div&gt;&lt;/td&gt; &lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;div style="text-align: left;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;Each step can be written very tersely using the following keywords:&lt;br /&gt;&lt;br /&gt;&lt;b&gt;login [as ROLE-OR-USER] &lt;/b&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;br /&gt;Log into the system with a given user or a user of the given type. Usually only stated explicitly when the test case depends on the permissions of a particular role or involves a workflow between different users.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;visit LOCATION &lt;/b&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;br /&gt;Visit a page or screen. For web applications, LOCATION may be a hyperlink. The location should be a well-known starting point (e.g., the Login screen), drilling down to specific pages should be part of the test.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;enter FIELD-NAME [as VALUE] [in SCREEN-LOCATION] &lt;/b&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;br /&gt;Fill in a named form field. VALUE can be a literal value or the name of a variable defined in the Test Data section. The FIELD-NAME itself can be a variable name when the UI field for that value is clear from context, e.g., enter password.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;enter FIELDS &lt;/b&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;Fill in all fields in a form when their values are clear from context or when their specific values are not important in this test case.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;click "LINK-LABEL" [in SCREEN-LOCATION] &lt;/b&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;Follow a labeled link or press a button. The screen location can be a predefined panel name or English phrase. Predefined panel names are based on GUI class names, master template names, or titles of boxes on the page.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;click BUTTON-NAME [in SCREEN-LOCATION] &lt;/b&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;Press a named button. This step should always be followed by a see step to check the results.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;see SCREEN-OR-PAGE &lt;/b&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;The tester should see the named GUI screen or web page. The general correctness of the page should be testable based on the feature description.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;verify CONDITION &lt;/b&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;The tester should see that the condition has been satisfied. This type of step usually follows a see step at the end of the test case.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;verify CONTENT [is VALUE] &lt;/b&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;The tester should see the named content on the current page, the correct values should be clear from the test data, or given explicitly. This type of step usually follows a see step at the end of the test case.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;perform TEST-CASE-NAME &lt;/b&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;This is like a subroutine call. The tester should perform all the steps of the named test case and then continue on to the next step of this test case.&lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;Every test case must include a verify step at the end so that the expected output is very clear. A test case can have multiple verify steps in the middle or at the end. Having multiple verify steps can be useful if you want a smaller number of long tests rather than a large number of short tests.&lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-size: large;"&gt;#4.2 Recording and Executing test cases&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;Once test cases are designed, they are be recorded and executed using &lt;b&gt;Selenium&lt;/b&gt;. Selenium IDE is the tool to develop Selenium test cases which is an easy-to-use Firefox plug-in and is generally the most efficient way to develop test cases.&lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;While recording and executing Selenium test cases, following checklist is to be kept in mind.&lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;ul style="text-align: left;"&gt;&lt;li&gt;Links &lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;/div&gt;&lt;ol style="text-align: left;"&gt;&lt;li&gt;Check that the link takes you to the page it said it would. &lt;/li&gt;&lt;li&gt;Ensure to have no orphan pages normally (a page that has no links to it). &lt;/li&gt;&lt;li&gt;Are all referenced web sites or email addresses hyperlinked if not generated by image? &lt;/li&gt;&lt;li&gt;Check all of your links to other websites. &lt;/li&gt;&lt;li&gt;If we have removed some of the pages from our own site, set up a custom 404 page that redirects your visitors to your home page (or a search page) when the user try to access a page that no longer exists. &lt;/li&gt;&lt;li&gt;Check all mailto links and whether it reaches properly. &lt;/li&gt;&lt;/ol&gt;&lt;div style="text-align: left;"&gt;&lt;ul style="text-align: left;"&gt;&lt;li&gt;Forms &lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;/div&gt;&lt;ol style="text-align: left;"&gt;&lt;li&gt;Acceptance of invalid input. &lt;/li&gt;&lt;li&gt;Optional versus mandatory fields. &lt;/li&gt;&lt;li&gt;Input longer than field allows. &lt;/li&gt;&lt;li&gt;Default values on page load/reload. &lt;/li&gt;&lt;li&gt;Is Command Button can be used for hyperLinks and Continue Links? &lt;/li&gt;&lt;li&gt;Is all the data inside combo/list box are arranged in required order? &lt;/li&gt;&lt;li&gt;Are all of the parts of a table or form present? Correctly laid out? Can you confirm that selected texts are in the right place? &lt;/li&gt;&lt;li&gt;Does a scroll-bar appear if required?&amp;nbsp; &lt;/li&gt;&lt;/ol&gt;&lt;div style="text-align: left;"&gt;&lt;ul style="text-align: left;"&gt;&lt;li&gt;Data verification and validation &lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;/div&gt;&lt;ol style="text-align: left;"&gt;&lt;li&gt;Is the Privacy Policy clearly defined and available for user access? &lt;/li&gt;&lt;li&gt;At no point of time the system should behave awkwardly when an invalid data is fed. &lt;/li&gt;&lt;li&gt;Check to see what happens if a user deletes cookies while in site. &lt;/li&gt;&lt;li&gt;Check to see what happens if a user deletes cookies after visiting a site. &lt;/li&gt;&lt;/ol&gt;&lt;div style="text-align: left;"&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;ul style="text-align: left;"&gt;&lt;li&gt;Data integration &lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;/div&gt;&lt;ol style="text-align: left;"&gt;&lt;li&gt;Check the maximum field lengths to ensure that there are no truncated characters? &lt;/li&gt;&lt;li&gt;If numeric fields accept negative values can these be stored correctly on the database and does it make sense for the field to accept negative numbers? &lt;/li&gt;&lt;li&gt;If a particular set of data is saved to the database check that each value gets saved fully to the database. (i.e.) Beware of truncation (of strings) and rounding of numeric values. &lt;/li&gt;&lt;/ol&gt;&lt;div style="text-align: left;"&gt;&lt;ul style="text-align: left;"&gt;&lt;li&gt;Date field checks &lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;ol style="text-align: left;"&gt;&lt;li&gt;Assure that leap years are validated correctly &amp;amp; do not cause errors/miscalculations. &lt;/li&gt;&lt;li&gt;Assure that Feb. 28, 29, 30 are validated correctly &amp;amp; do not cause errors/ miscalculations. &lt;/li&gt;&lt;/ol&gt;&lt;div style="text-align: left;"&gt;&lt;ul style="text-align: left;"&gt;&lt;li&gt;Numeric fields &lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;ol style="text-align: left;"&gt;&lt;li&gt;Assure that lowest and highest values are handled correctly. &lt;/li&gt;&lt;li&gt;Assure that numeric fields with a blank in position 1 are processed or reported as an error. &lt;/li&gt;&lt;li&gt;Assure that fields with a blank in the last position are processed or reported as an error an error. &lt;/li&gt;&lt;li&gt;Assure that both + and - values are correctly processed. &lt;/li&gt;&lt;li&gt;Assure that division by zero does not occur. &lt;/li&gt;&lt;li&gt;Include value zero in all calculations. &lt;/li&gt;&lt;li&gt;Assure that upper and lower values in ranges are handled correctly. &lt;/li&gt;&lt;li&gt;Alphanumeric field checks &lt;/li&gt;&lt;li&gt;Use blank and non-blank data. &lt;/li&gt;&lt;li&gt;Include lowest and highest values. &lt;/li&gt;&lt;li&gt;Include invalid characters &amp;amp; symbols. &lt;/li&gt;&lt;li&gt;Include valid characters. &lt;/li&gt;&lt;li&gt;Include data items with first position blank. &lt;/li&gt;&lt;li&gt;Include data items with last position blank. &lt;/li&gt;&lt;/ol&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-size: large;"&gt;#4.3 Organizing test cases&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;While test cases are successfully designed, recorded and executed they should be stored on file-system to re-run them for regression testing, documentation, demonstration etc. There have been designed certain standards and conventions for that, as shown below;&lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;#4.3.1 HTML test cases &lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;/div&gt;&lt;ol&gt;&lt;li&gt;HTML test case should be named as &lt;b&gt;ModuleAction.html&lt;/b&gt;. For example if module is User and action is Login then test case name would be &lt;b&gt;UserLogin.html&lt;/b&gt;. Some more examples are &lt;b&gt;UserAdd.html&lt;/b&gt;, &lt;b&gt;ImageAttach.html&lt;/b&gt; etc. &lt;/li&gt;&lt;li&gt;These test cases are to be organized into single test suite to view them at same time. For that name &lt;b&gt;TestSuite.html&lt;/b&gt; is to be used. A test suite document is an organized table of contents for our test cases: it simply lists the names of all test cases that we intend to write. The suite can be organized in several ways. For example, we can list all the system components, and then list test cases under each. Or, we could list major product features, and then list test cases for each of those. &lt;/li&gt;&lt;li&gt;Test suite is organized in a grid where the rows are types of &lt;b&gt;business&lt;/b&gt; &lt;b&gt;objects&lt;/b&gt; or module names and the columns are types of &lt;b&gt;operations&lt;/b&gt; or &lt;b&gt;actions&lt;/b&gt;. Each cell in the grid lists test cases that test one type of operation on one type of object. Each individual operations/action should also contain hyperlink to corresponding test case document. Format of &lt;b&gt;TestSuite.html&lt;/b&gt; should be as follows: &lt;/li&gt;&lt;/ol&gt;&lt;div style="text-align: left;"&gt;&lt;table border="1" cellpadding="3" cellspacing="0"&gt; &lt;colgroup&gt;&lt;col width="55*"&gt;&lt;/col&gt; &lt;col width="35*"&gt;&lt;/col&gt; &lt;col width="40*"&gt;&lt;/col&gt; &lt;col width="36*"&gt;&lt;/col&gt; &lt;col width="44*"&gt;&lt;/col&gt; &lt;col width="46*"&gt;&lt;/col&gt; &lt;/colgroup&gt;&lt;tbody&gt;&lt;tr&gt;  &lt;th bgcolor="#e6e6e6" colspan="6" width="100%"&gt;&lt;div class="western"&gt;&lt;span style="font-size: small;"&gt;Test cases by &lt;i&gt;modules and actions&lt;/i&gt; or   &lt;i&gt;business objects and operations&lt;/i&gt;&lt;/span&gt;&lt;/div&gt;&lt;/th&gt; &lt;/tr&gt;&lt;tr&gt;  &lt;th bgcolor="#e6e6e6" height="35" style="font-weight: normal;" width="22%"&gt;&lt;div class="western"&gt;&lt;span style="font-size: small;"&gt;Modules/Actions&lt;/span&gt;&lt;/div&gt;&lt;div class="western"&gt;&lt;span style="font-size: small;"&gt;BOs/Operations&lt;/span&gt;&lt;/div&gt;&lt;/th&gt;  &lt;th style="font-weight: normal;" width="14%"&gt;&lt;div class="western"&gt;&lt;span style="font-size: small;"&gt;add&lt;/span&gt;&lt;/div&gt;&lt;/th&gt;  &lt;th style="font-weight: normal;" width="16%"&gt;&lt;div class="western"&gt;&lt;span style="font-size: small;"&gt;list/browse&lt;/span&gt;&lt;/div&gt;&lt;/th&gt;  &lt;th style="font-weight: normal;" width="14%"&gt;&lt;div class="western"&gt;&lt;span style="font-size: small;"&gt;edit&lt;/span&gt;&lt;/div&gt;&lt;/th&gt;  &lt;th style="font-weight: normal;" width="17%"&gt;&lt;div class="western"&gt;&lt;span style="font-size: small;"&gt;delete&lt;/span&gt;&lt;/div&gt;&lt;/th&gt;  &lt;th style="font-weight: normal;" width="18%"&gt;&lt;div class="western"&gt;&lt;span style="font-size: small;"&gt;search&lt;/span&gt;&lt;/div&gt;&lt;/th&gt; &lt;/tr&gt;&lt;tr&gt;  &lt;th bgcolor="#e6e6e6" height="3" style="font-weight: normal;" width="22%"&gt;&lt;div class="western"&gt;&lt;span style="font-size: small;"&gt;User&lt;/span&gt;&lt;/div&gt;&lt;/th&gt;  &lt;td style="color: #a64d79;" width="14%"&gt;&lt;div class="western"&gt;&lt;span style="font-size: small;"&gt;&lt;u&gt;UserAdd&lt;/u&gt;&lt;/span&gt;&lt;/div&gt;&lt;/td&gt;  &lt;td style="color: #a64d79;" width="16%"&gt;&lt;div class="western"&gt;&lt;span style="font-size: small;"&gt;&lt;u&gt;UserList&lt;/u&gt;&lt;/span&gt;&lt;/div&gt;&lt;/td&gt;  &lt;td style="color: #a64d79;" width="14%"&gt;&lt;div class="western"&gt;&lt;span style="font-size: small;"&gt;&lt;u&gt;UserEdit&lt;/u&gt;&lt;/span&gt;&lt;/div&gt;&lt;/td&gt;  &lt;td style="color: #a64d79;" width="17%"&gt;&lt;div class="western"&gt;&lt;span style="font-size: small;"&gt;&lt;u&gt;UserDelete&lt;/u&gt;&lt;/span&gt;&lt;/div&gt;&lt;/td&gt;  &lt;td style="color: #a64d79;" width="18%"&gt;&lt;div class="western"&gt;&lt;span style="font-size: small;"&gt;&lt;u&gt;UserSearch&lt;/u&gt;&lt;/span&gt;&lt;/div&gt;&lt;/td&gt; &lt;/tr&gt;&lt;tr&gt;  &lt;th bgcolor="#e6e6e6" style="font-weight: normal;" width="22%"&gt;&lt;div class="western"&gt;&lt;span style="font-size: small;"&gt;Ad&lt;/span&gt;&lt;/div&gt;&lt;/th&gt;  &lt;td style="color: #a64d79;" width="14%"&gt;&lt;div class="western"&gt;&lt;span style="font-size: small;"&gt;&lt;u&gt;AdAdd&lt;/u&gt;&lt;/span&gt;&lt;/div&gt;&lt;/td&gt;  &lt;td style="color: #a64d79;" width="16%"&gt;&lt;div class="western"&gt;&lt;span style="font-size: small;"&gt;&lt;u&gt;AdList&lt;/u&gt;&lt;/span&gt;&lt;/div&gt;&lt;/td&gt;  &lt;td style="color: #a64d79;" width="14%"&gt;&lt;div class="western"&gt;&lt;span style="font-size: small;"&gt;&lt;u&gt;AdEdit&lt;/u&gt;&lt;/span&gt;&lt;/div&gt;&lt;/td&gt;  &lt;td style="color: #a64d79;" width="17%"&gt;&lt;div class="western"&gt;&lt;span style="font-size: small;"&gt;&lt;u&gt;AdDelete&lt;/u&gt;&lt;/span&gt;&lt;/div&gt;&lt;/td&gt;  &lt;td style="color: #a64d79;" width="18%"&gt;&lt;div class="western"&gt;&lt;span style="font-size: small;"&gt;&lt;u&gt;AdSearch&lt;/u&gt;&lt;/span&gt;&lt;/div&gt;&lt;/td&gt; &lt;/tr&gt;&lt;tr&gt;  &lt;th bgcolor="#e6e6e6" style="font-weight: normal;" width="22%"&gt;&lt;div class="western"&gt;&lt;span style="font-size: small;"&gt;Club&lt;/span&gt;&lt;/div&gt;&lt;/th&gt;  &lt;td style="color: #a64d79;" width="14%"&gt;&lt;div class="western"&gt;&lt;span style="font-size: small;"&gt;&lt;u&gt;ClubAdd&lt;/u&gt;&lt;/span&gt;&lt;/div&gt;&lt;/td&gt;  &lt;td style="color: #a64d79;" width="16%"&gt;&lt;div class="western"&gt;&lt;span style="font-size: small;"&gt;&lt;u&gt;ClubList&lt;/u&gt;&lt;/span&gt;&lt;/div&gt;&lt;/td&gt;  &lt;td style="color: #a64d79;" width="14%"&gt;&lt;div class="western"&gt;&lt;span style="font-size: small;"&gt;&lt;u&gt;ClubEdit&lt;/u&gt;&lt;/span&gt;&lt;/div&gt;&lt;/td&gt;  &lt;td style="color: #a64d79;" width="17%"&gt;&lt;div class="western"&gt;&lt;span style="font-size: small;"&gt;&lt;u&gt;ClubDelete&lt;/u&gt;&lt;/span&gt;&lt;/div&gt;&lt;/td&gt;  &lt;td style="color: #a64d79;" width="18%"&gt;&lt;div class="western"&gt;&lt;span style="font-size: small;"&gt;&lt;u&gt;ClubSearch&lt;/u&gt;&lt;/span&gt;&lt;/div&gt;&lt;/td&gt; &lt;/tr&gt;&lt;tr&gt;  &lt;th bgcolor="#e6e6e6" style="font-weight: normal;" width="22%"&gt;&lt;div class="western"&gt;&lt;span style="font-size: small;"&gt;Element&lt;/span&gt;&lt;/div&gt;&lt;/th&gt;  &lt;td style="color: #a64d79;" width="14%"&gt;&lt;div class="western"&gt;&lt;span style="font-size: small;"&gt;&lt;u&gt;ElementAdd&lt;/u&gt;&lt;/span&gt;&lt;/div&gt;&lt;/td&gt;  &lt;td style="color: #a64d79;" width="16%"&gt;&lt;div class="western"&gt;&lt;span style="font-size: small;"&gt;&lt;u&gt;ElementList&lt;/u&gt;&lt;/span&gt;&lt;/div&gt;&lt;/td&gt;  &lt;td style="color: #a64d79;" width="14%"&gt;&lt;div class="western"&gt;&lt;span style="font-size: small;"&gt;&lt;u&gt;ElementEdit&lt;/u&gt;&lt;/span&gt;&lt;/div&gt;&lt;/td&gt;  &lt;td style="color: #a64d79;" width="17%"&gt;&lt;div class="western"&gt;&lt;span style="font-size: small;"&gt;&lt;u&gt;ElementDelete&lt;/u&gt;&lt;/span&gt;&lt;/div&gt;&lt;/td&gt;  &lt;td style="color: #a64d79;" width="18%"&gt;&lt;div class="western"&gt;&lt;span style="font-size: small;"&gt;&lt;u&gt;ElementSearch&lt;/u&gt;&lt;/span&gt;&lt;/div&gt;&lt;/td&gt; &lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;br /&gt;Once all these objects are created they should be stored at location; &lt;b&gt;tests/functionaltests/html/&lt;/b&gt; location for concerned project. Other artifacts like documents, instructions etc. also should be put at same location. &lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;Since these objects are for internal purpose; they may not be publicly visible. However separate/sub domain can be created to view them from web if needed. &lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;#4.3.2 Selenium test cases &lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;/div&gt;&lt;ol style="text-align: left;"&gt;&lt;li&gt;Selenium test case should also be named as &lt;b&gt;ModuleAction.html&lt;/b&gt;. For example if module is User and action is Login then test case name would be &lt;b&gt;UserLogin.html&lt;/b&gt;. Some more examples are &lt;b&gt;UserAdd.html&lt;/b&gt;, &lt;b&gt;ImageAttach&lt;/b&gt;.html etc. &lt;/li&gt;&lt;li&gt;These test cases are to be organized into single test suite HTML file to re-run them at same time. For that name &lt;b&gt;TestSuite.html&lt;/b&gt; is to be used. &lt;/li&gt;&lt;li&gt;Once all these objects are created they should be stored at location; &lt;b&gt;tests/functionaltests/selenium/&lt;/b&gt; location for concerned project. Other artifacts like documents, instructions etc. also should be put at same location. &lt;/li&gt;&lt;li&gt;Since these objects are for internal purpose; they may not be publicly visible. However separate/sub domain can be created to re-run them from web on other servers if needed. &lt;/li&gt;&lt;/ol&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-size: large;"&gt;#4.4 Scope of testing &lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;/div&gt;&lt;ol&gt;&lt;li&gt;Minimum scope of overall testing procedure is to test all features in all popular browsers and platforms. &lt;/li&gt;&lt;li&gt;Stress testing should be performed (try to overload the program with inputs to see where it reaches its maximum capacity), especially with real time systems. &lt;/li&gt;&lt;li&gt;Crash testing should be performed to see what it takes to bring the system down. &lt;/li&gt;&lt;li&gt;Other scope can be defined according to FRS when test plan is defined. &lt;/li&gt;&lt;/ol&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-size: large;"&gt;#4.5 What test should be written&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;While doing functional testing, it is important to know that what kind of tests should be done. There has been provided some insight about type of some tests. &lt;/div&gt;&lt;ol&gt;&lt;li&gt;All positive tests: This set of tests ensures that everything works as expected. &lt;/li&gt;&lt;li&gt;All failure tests: Use these tests on a one-by-one basis to ensure that every failure or exception case works. &lt;/li&gt;&lt;li&gt;Positive sequence tests: This set of tests ensures that calls in the correct order work as expected. &lt;/li&gt;&lt;li&gt;Negative sequence tests:This set of tests ensures that when calls are made out of order, they fail. &lt;/li&gt;&lt;li&gt;Load tests: When appropriate, you can perform a small set of tests to determine that the performance of those tests is within an expected range. For example; while uploading image, how large file software is able to handle. &lt;/li&gt;&lt;/ol&gt;&lt;div style="text-align: left;"&gt;First 4 types of tests are must for every test case. Rest can be implemented according to FRS.&lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-size: large;"&gt;#4.6 Functional testing in the context of team &lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;Functional testing team is also part of development team, hence they should be included in every meeting, discussion, planning etc. to make them aware about functionalities are to be developed. &lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;Testing strategy described here is to be performed by dedicated testers only. However standard practice is that developers do functional testing immediately after they develop required functionality. Then testing related to that functionality can be given to dedicated testers to test it from user point of view. &lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;FT team may not always have daily tasks of testing, hence in spare time they can also assist developers in developing new functionality if they wish. &lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-size: x-large;"&gt;#5 Links&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;a href="https://gforge2.remres.com/docman/index.php?group_id=157&amp;amp;selected_doc_group_id=253&amp;amp;language_id=1"&gt;&lt;br /&gt;&lt;/a&gt;&lt;a href="http://www.w3.org/TR/2004/WD-qaframe-test-20040225/"&gt;http://www.w3.org/TR/2004/WD-qaframe-test-20040225/&lt;/a&gt;&lt;a href="http://www.w3.org/TR/2004/WD-qaframe-test-20040225/"&gt;&lt;br /&gt;&lt;/a&gt;&lt;a href="http://seleniumhq.org/"&gt;http://seleniumhq.org/&lt;/a&gt;&lt;a href="http://seleniumhq.org/"&gt;&lt;br /&gt;&lt;/a&gt;&lt;a href="http://seleniumhq.org/projects/ide/"&gt;http://seleniumhq.org/projects/ide/&lt;/a&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/298834846183725348-2183673969158138311?l=arzala.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://arzala.blogspot.com/feeds/2183673969158138311/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=298834846183725348&amp;postID=2183673969158138311' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/298834846183725348/posts/default/2183673969158138311'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/298834846183725348/posts/default/2183673969158138311'/><link rel='alternate' type='text/html' href='http://arzala.blogspot.com/2009/02/functional-testing-guidelines.html' title='Functional testing guidelines'/><author><name>Anirudhsinh Zala</name><uri>http://www.blogger.com/profile/16341197487842993303</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://2.bp.blogspot.com/-jEmJYVgTwk0/Tu4SjN7xOgI/AAAAAAAAABI/17BzjhETHMM/s220/me.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-298834846183725348.post-6843618523863954866</id><published>2008-09-09T16:07:00.000+05:30</published><updated>2012-01-10T20:18:14.760+05:30</updated><category scheme='http://www.blogger.com/atom/ns#' term='seo'/><category scheme='http://www.blogger.com/atom/ns#' term='html'/><title type='text'>SEO guidelines</title><content type='html'>&lt;div dir="ltr" style="text-align: left;" trbidi="on"&gt;&lt;span style="font-size: x-large;"&gt;#1 About this document &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;This document aims to defines generic search engine optimization requirements for various projects. &lt;br /&gt;&lt;br /&gt;At this moment this document contains general guidelines of SEO. In future, at the time of taking training session, this document will be expanded further in order to be used as perfect resource for almost all SEO requirements. &lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: x-large;"&gt; #2 General requirements &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: large;"&gt;#2.1 Server location &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;The server should be located in same country from where it will be mostly accessed. Moreover If the service will have it’s own domain then it should reside on a dedicated server. Wildcard DNS should not be allowed as well as all sub domains, if any, should be activated separately. &lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: large;"&gt;#2.2 Robots.txt &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;The &lt;b&gt;robots.txt&lt;/b&gt; file is to be placed in the &lt;b&gt;root&lt;/b&gt; (value of &lt;b&gt;DocumentRoot&lt;/b&gt; directive in case web server is Apache) directory of the software. It should allow the search engines to crawl all directories where information related to various entities will be shown. &lt;br /&gt;&lt;br /&gt;Personal pages such as listing owner's entities, posting/editing entities that require login should be blocked. Most search engines now a days are able to find out this behavior hence you may omit such entries into robots.txt file. &lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: large;"&gt;#2.3 Encoding &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;If there are will be used special characters in language of website they will need to get encoded in URLs (maybe using PHP function like &lt;b&gt;urlencode()&lt;/b&gt;) and Filenames using UTF-8 encoding. For full documentation of encoding of such characters, please visit &lt;a href="http://www1.tip.nl/%7Et876506/utf8tbl.html"&gt;http://www1.tip.nl/~t876506/utf8tbl.html&lt;/a&gt;). As practically all browsers supports the Unicode UTF-8 standard, it should not be important to encode the characters in the actual content. The suitable HTML entities can be taken from this address: &lt;a href="http://leftlogic.com/lounge/articles/entity-lookup/"&gt;http://leftlogic.com/lounge/articles/entity-lookup/&lt;/a&gt; anyhow. &lt;br /&gt;&lt;br /&gt;There should be a &lt;b&gt;301&lt;/b&gt; redirect from any page with special characters in the URL where someone writes the URL using the special characters and not the encoded ones if that user has a browser that over writes the UTF-8 character set with some other character set. See how Wikipedia functions for an example. This prevents links with the wrong character set to be used on external pages. &lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: large;"&gt;#2.4 Header responses &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;#2.4.1 Page not found (404 error) &lt;br /&gt;&lt;br /&gt;Entities that are removed from database/software should not be shown. When someone accesses the removed listings page the server should respond with a &lt;b&gt;404&lt;/b&gt; header response (and not a 200 response) and show an error message (or optionally a separate page) saying that the entity is already deleted/expired/sold etc. Furthermore the relevant listing page should be shown. &lt;br /&gt;&lt;br /&gt;#2.4.2 Redirects (301 error) &lt;br /&gt;&lt;br /&gt;As a general rule of thumb all redirects should be done using the &lt;b&gt;301&lt;/b&gt; permanently moved response. All sub domains should be redirected this way (example.com -&amp;gt; 301 -&amp;gt; www.example.com) and &lt;b&gt;also all other domains&lt;/b&gt; that contain the same information, as shown below; &lt;br /&gt;&lt;br /&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;www.example.net -&amp;gt; 301 -&amp;gt; www.example.com&lt;/div&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;www.example.in -&amp;gt; 301 -&amp;gt; www.example.com &lt;/div&gt;&lt;br /&gt;Assure also that only the specified URLs work and make a 301 redirect rule for all non-specified URL’s when called missing. &lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: x-large;"&gt;#3 General page requirements &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: large;"&gt;#3.1 Using standards &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;The site should comply with the World Wide Web consortium’s (&lt;a href="http://www.w3.org/"&gt;http://www.w3.org/&lt;/a&gt;) recommendations for creating web pages (XHTML 1.0 Transitional should be enough) and also comply with the Americans with disabilities act (&lt;a href="http://www.ada.gov/"&gt;http://www.ada.gov/&lt;/a&gt;) if required. &lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: large;"&gt;#3.2 Page design &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;The pages should be designed with &lt;b&gt;CSS positioning&lt;/b&gt; and the content part of the page should appear in the source code as early as possible preferably before other body content such as navigational blocks. &lt;br /&gt;&lt;br /&gt;The navigation should be implemented with anchor tags and text and the links should not redirect. &lt;br /&gt;&lt;br /&gt;&lt;b&gt;Breadcrumb&lt;/b&gt; navigation would increase SEO with internal back links and usability in a sense that the visitor would see their location on site. Example of the breadcrumb navigation: Home =&amp;gt; List furniture items =&amp;gt; View table =&amp;gt; ... &lt;br /&gt;&lt;br /&gt;&lt;b&gt;Scripts and other elements (CSS) should be put in external files.&lt;/b&gt; The source code should be kept clean with little or no unused code. The preferred maximum file size for HTML code is &lt;b&gt;100 KB&lt;/b&gt;. &lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: large;"&gt;#3.3 Elements of a page &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;The following elements should always be included (and be editable somehow) on a page which is to be indexed by search engine:&lt;br /&gt;&lt;ul style="text-align: left;"&gt;&lt;li&gt;Page title ([title]-element in the header)&lt;/li&gt;&lt;li&gt;Meta description, robots and keywords (in the header)&lt;/li&gt;&lt;li&gt;Page heading (one [h1] per page)&lt;/li&gt;&lt;/ul&gt;#3.3.1 Page title ([title]-element in the header)&lt;b&gt; &lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;A page title should be as specific and concise as possible with respect to the document&lt;/b&gt;. This will insure its uniqueness and click-through in Search Engine Result Pages. A structure similar to "Page name | Section name | Site title - Tagline" is encouraged for clarity, uniqueness and better usability for the visitor. Focus on delivering a title that spans from specific (closer to the beginning) to general keywords. The length of the title needs no more then 80 characters. &lt;br /&gt;&lt;br /&gt;#3.3.2 Meta description, robots and keywords (in the header) &lt;br /&gt;&lt;br /&gt;HTML meta description around 150 characters should be sufficient. Although it doesn't hurt to be a little more, this data should contain the most concise information about the document. The uniqueness of this information also plays a fair role as far as Search Engine Result Pages are concerned. &lt;br /&gt;&lt;br /&gt;Meta keywords on the other hand are not quite necessary since it is the &lt;b&gt;responsibility of the search engine indexers to determine the nature and the relevancy of the document&lt;/b&gt;. For the purposes of accuracy, they can't rely on what the document claims it to be. There comes a transition on the Web which provides this sort of meta information about the document. Today, the results gained from meta keywords are negligible. See below some examples of well written &lt;b&gt;meta&lt;/b&gt; tags;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;lt;meta name="description" content="Suppliers of quality office furniture and accessories at discount prices."&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;lt;meta name="keywords" content="furniture, office, store, shop, retail, discount"&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;#3.3.3 Page heading (one &amp;lt;h1&amp;gt; per page) &lt;br /&gt;&lt;br /&gt;A proper structured document will consist of headings, paragraphs, lists, tables, and forms, and use an external stylesheet to style them. Many search engines place more emphasis on text within heading tags (and not just on keywords provided in meta elements), so make sure they use keywords. Use one &amp;lt;h1&amp;gt; tag per page with the most important keywords. You can also use other head tags ( &amp;lt;h2&amp;gt;, &amp;lt;h3&amp;gt; etc.) to provide variations and support the main heading. &lt;br /&gt;&lt;br /&gt;Some example of tags are;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;lt;h1&amp;gt;Tables&amp;lt;/h1&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;lt;h2&amp;gt;Round tables&amp;lt;/h2&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;lt;p&amp;gt;... information about round tables ...&amp;lt;/p&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;lt;h2&amp;gt;Square Desks&amp;lt;/h2&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;lt;p&amp;gt;... information about square desks, etc.&amp;lt;/p&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;#3.3.4 Body text &lt;br /&gt;&lt;br /&gt;Make sure the text of your web pages contain keywords and common phrases which people might search for. Be careful with the frequency of your keywords - you want to have them occur at least a few times if possible, but don't repeat yourself so much that the copy becomes unnatural. The idea is to discretely spread keywords around without making it obvious. &lt;br /&gt;&lt;br /&gt;&lt;b&gt;A well written document will naturally use keywords that are appropriate and in proportion&lt;/b&gt;. Search engine algorithms essentially compare similar documents to get a better understanding of the nature of the document. If a document is not well written and gives off-balanced scores then it will raise flags and possibly mark it as not relevant as it indicates a document that is written for the machine and not for the human reader. Keep in mind that indexing is in place to assist human searches. An example of good body text could be like;&lt;br /&gt;&lt;br /&gt;[p]Buy office furniture at affordable prices from any of our retail stores.[/p]&lt;br /&gt;&lt;br /&gt;#3.3.5 Images and Pictures &lt;br /&gt;&lt;br /&gt;When pictures, that are not part of the page template, are used they should always include an ALT description. This description should either be automated or editable (This is partly already a requirement of the Americans with disabilities act). &lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: large;"&gt;#3.4 Automation &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;The title element and the meta description and keywords need to be automatically generated according to different templates. These templates will include page- and directory specific elements as well as generic elements. An example of a template for the title element for a page called Search results page could be: &lt;br /&gt;&lt;br /&gt;&lt;results&gt; [Results] - [category] - Search results – My furniture example.com&lt;category&gt;&lt;/category&gt;&lt;/results&gt;&lt;br /&gt;&lt;ul style="text-align: left;"&gt;&lt;li&gt;&lt;results&gt;&lt;category&gt;&lt;/category&gt;&lt;/results&gt;Different elements that could be included are&lt;/li&gt;&lt;li&gt;Results = Search results pages (New, Old, All) &lt;/li&gt;&lt;li&gt; Category name = Such as Wood tables, Wood chairs, Metal chairs &lt;/li&gt;&lt;li&gt; Area = Can represents location of entity. &lt;/li&gt;&lt;li&gt; Page number in a Search results, if applicable &lt;/li&gt;&lt;li&gt; The category name or area might not be in basic form – different grammatical forms might be needed. &lt;/li&gt;&lt;/ul&gt;&lt;div style="text-align: left;"&gt;In the title, meta information and headings the keywords or key phrases are added as is or in another grammatical form but when automating (URL rewriting) the URL, it may need some encoding if other language has been used: &lt;/div&gt;&lt;ul style="text-align: left;"&gt;&lt;li&gt; Non-ASCII keywords (and phrases) included in URLs need to be encoded in hex values (maybe using PHP function like urlencode()) like: &lt;/li&gt;&lt;li&gt;www.example.com/product/table/એપલ =&amp;gt; www.example.com/product/table/%E0%AA%8F%E0%AA%AA%E0%AA%B2 &lt;/li&gt;&lt;/ul&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-size: x-large;"&gt; #4 Index page &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Index page of your website is the most likely to get the highest number of inbound links since it is entry point of your website. Hence linking other pages of website from this page becomes very important. By theory this page should host almost links of all pages that starts from here. &lt;br /&gt;&lt;br /&gt;However number of links in such page should be around 100, in many projects it may not be possible to display all links. In such cases most important links should be made visible from here. And remaining pages could be linked from there because our purpose is to chain all important pages to be get indexed. &lt;br /&gt;&lt;br /&gt;To make this working it becomes important to identify those important links. For example if you are selling something then this home page can have link of those pages that display list of items per category of products. Similarly if they are bound to certain geographical location and if you website displays list of selling items per province/city/area then links to those pages could be placed on this page. &lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: x-large;"&gt; #5 Search pages &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Search pages whether simple or extended, may not be indexed as they are not containing, be default, any information to be searched for. &lt;br /&gt;&lt;br /&gt;However for usability point of view, their URLs, page design and on-page information should be properly designed and implemented. &lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: x-large;"&gt; #6 Listing pages &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Listing pages are the 2nd most important pages for any website as they display information about entities for which website is created. Listings entities can include various types of stuffs ranging from selling items, ads, jobs etc. &lt;br /&gt;&lt;br /&gt;Such listing may contain pagination and sorting links depending upon results and interest of users. It is recommended to keep pagination links in text mode so that search engine can crawl through all available pages and can index those pages. However sorting links may be implemented using JS (Ajax) etc. so that additional query to server can be minimized. From search engine point of view, it doesn't matter in what order information displays. &lt;br /&gt;&lt;br /&gt;If possible, URL scheme of such pages can be made self-informative. For example for furniture selling website URLs can be designed like below;&amp;nbsp;&lt;/div&gt;&lt;br /&gt;www.myfurniture.com/tables/round&lt;br /&gt;www.myfurniture.com/tables/square&lt;br /&gt;www.myfurniture.com/tables/plastic&lt;br /&gt;www.myfurniture.com/chairs/rocking&lt;br /&gt;www.myfurniture.com/chairs/revolving&lt;br /&gt;&lt;br /&gt;Text appearing on such pages should be as informative as possible and number of entity per list should be kept around 10 to 30 entities. Listing pages may also contain links to other important pages which are to be indexed. &lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: x-large;"&gt; #7 View pages &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;View entity pages shows detailed information about entities listed in listing pages. Title, Meta description, Meta keywords, H1 tag should contain information about entity that is expected to be viewed. &lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: x-large;"&gt; #8 Other pages &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Other pages may include pages like Login pages, Posting/Editing entity pages etc. &lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: large;"&gt;#8.1 Login pages &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Such pages should not get indexed as they don't contain any public searchable information. &lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: large;"&gt;#8.2 Posting/Editing entity pages &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Any page that contains forms to be submitted are not normally indexed as they don't display any searchable information to general public. &lt;br /&gt;&lt;br /&gt;General rule of thumb is that those pages which changes stat of the server (like data is inserted/updated, file is created/delete etc.) or those pages which are personal to users are not indexed as they are tightly integrated with data of the website. &lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: x-large;"&gt; #9 Resources &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.google.com/support/webmasters/bin/answer.py?hl=en&amp;amp;answer=35769"&gt;http://www.google.com/support/webmasters/bin/answer.py?hl=en&amp;amp;answer=35769&lt;/a&gt;&lt;br /&gt;&lt;a href="http://help.yahoo.com/l/us/yahoo/search/basics/basics-18.html"&gt;http://help.yahoo.com/l/us/yahoo/search/basics/basics-18.html&lt;/a&gt;&lt;a href="http://search.msn.com.sg/docs/siteowner.aspx?t=SEARCH_WEBMASTER_REF_GuidelinesforOptimizingSite.htm"&gt;&lt;br /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/298834846183725348-6843618523863954866?l=arzala.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://arzala.blogspot.com/feeds/6843618523863954866/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=298834846183725348&amp;postID=6843618523863954866' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/298834846183725348/posts/default/6843618523863954866'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/298834846183725348/posts/default/6843618523863954866'/><link rel='alternate' type='text/html' href='http://arzala.blogspot.com/2011/12/seo-guidelines_30.html' title='SEO guidelines'/><author><name>Anirudhsinh Zala</name><uri>http://www.blogger.com/profile/16341197487842993303</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://2.bp.blogspot.com/-jEmJYVgTwk0/Tu4SjN7xOgI/AAAAAAAAABI/17BzjhETHMM/s220/me.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-298834846183725348.post-2153803766831775928</id><published>2008-03-13T17:15:00.000+05:30</published><updated>2012-01-02T11:13:21.770+05:30</updated><category scheme='http://www.blogger.com/atom/ns#' term='performance'/><category scheme='http://www.blogger.com/atom/ns#' term='lighttpd'/><category scheme='http://www.blogger.com/atom/ns#' term='cache'/><category scheme='http://www.blogger.com/atom/ns#' term='php'/><category scheme='http://www.blogger.com/atom/ns#' term='web-server'/><category scheme='http://www.blogger.com/atom/ns#' term='apache'/><title type='text'>Lighttpd vs. Apache</title><content type='html'>&lt;div dir="ltr" style="text-align: left;" trbidi="on"&gt;&lt;span style="font-size: x-large;"&gt;#1 Lighttpd overview&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Lighttpd&lt;/b&gt; is an open source web server (similar like Apache) to server web pages. It has been developed by a MySQL developer named Jan Kneschke who developed this web server as a part of the &lt;a href="http://www.kegel.com/c10k.html"&gt;C10K problem&lt;/a&gt;. Hence immediate reason of birth of Lighttpd is to overcome weakness, like reducing high memory footprint, of Apache web server. &lt;br /&gt;&lt;br /&gt;The &lt;b&gt;prefork&lt;/b&gt; model that Apache uses consumes a lot of memory (&lt;b&gt;&amp;gt; 20 MB&lt;/b&gt; normally) per process. Which means if we multiply number of process to run simultaneously then RAM of server gets exhausted quickly. Lighttpd here beats Apache by using very low memory footprint (just &lt;b&gt;6MB&lt;/b&gt;) which means faster output from web server. The response appears even more faster when static contents are to be delivered. In Netcraft's latest &lt;a href="http://survey.netcraft.com/Reports/0703/"&gt;web server survey&lt;/a&gt;, we can see Lighttpd among top 5 web servers currently used on Internet.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: x-large;"&gt;#2 How to set it up&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Normal and most preferred installation instruction can be found from this installation page. For &lt;b&gt;Yum&lt;/b&gt; users, a single command &lt;b&gt;yum install zlib pcre lighttpd lighttpd-fastcgi&lt;/b&gt; will do almost all things.&lt;br /&gt;&lt;br /&gt;If you want to start and stop Lighttpd manually, you're done. To install Lighttpd as a service like Apache, edit and install the init script (only if you have installed Lighttpd from source):&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;# sed -e 's/FOO/lighttpd/g' doc/rc.lighttpd &amp;gt; lighttpd.init&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;# chmod a+rx lighttpd.init&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;# cp lighttpd.init /etc/init.d/lighttpd&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;# cp -p doc/sysconfig.lighttpd /etc/sysconfig/lighttpd&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;# install -Dp ./doc/lighttpd.conf /etc/lighttpd/lighttpd.conf&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;# chkconfig lighttpd on&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;If you have installed Lighttpd using Yum then just follow last step. You may also use various other commands to start and stop Lighttpd web service like &lt;b&gt;/etc/init.d/lighttpd start|stop|restart|condrestart|reload|status&lt;/b&gt; or &lt;b&gt;service lighttpd start|stop|restart|condrestart|reload|status&lt;/b&gt;.&lt;br /&gt;&lt;br /&gt;To just test lighttpd.conf, run command &lt;b&gt;lighttpd -t -f /PATH/TO/CONF/lighttpd.conf&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: x-large;"&gt;#3 Differences between Apache and Lighttpd&lt;/span&gt;&lt;b&gt;&lt;br /&gt;&lt;/b&gt;&lt;br /&gt;&lt;span style="font-size: large;"&gt;#3.1 General&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;The main difference between Apache and Lighttpd is the serving model, Lighttpd is &lt;b&gt;event-driven&lt;/b&gt; and Apache is &lt;b&gt;threaded&lt;/b&gt; or &lt;b&gt;pre-forked&lt;/b&gt;.&lt;br /&gt;&lt;br /&gt;Apache provides different multiprocessing models (MPMs) for different runtime environments. The &lt;b&gt;prefork&lt;/b&gt; model that Apache uses creates number of processes at startup of service and manages them in a pool. However each process requires lot of memory to handle requests which means the more the processes the more memory will require. That is simultaneous apache processes quickly eat available RAM.&lt;br /&gt;&lt;br /&gt;On the other hand Lighttpd uses single process, single thread and non-blocking I/O. For that it&amp;nbsp; uses fastest even handler in the target system like: &lt;b&gt;poll, epoll, kqueue&lt;/b&gt; or&lt;b&gt; /dev/poll&lt;/b&gt;. This difference makes Lighttpd faster than Apache in serving static files.&lt;br /&gt;&lt;br /&gt;However the biggest difference between both is how they support scripting languages (specially like PHP). Apache has upper hand here because it supports easy to use Shared module version, CGI and FastCGI all together while Lighttpd supports only FastCGI at this&amp;nbsp; moment.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: large;"&gt;#3.2 Configuration level&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;There is visible difference between styles of configuration files of Lighttpd (lighttpd.conf) and Apache (httpd.conf). Syntax of lighttpd.conf will look more like syntax of php.ini while httpd.conf has XML type syntax. Here is an example of some basic configuration:&lt;br /&gt;&lt;br /&gt;#3.2.1 Basic Configuration&lt;br /&gt;&lt;br /&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&lt;b&gt;Apache:&lt;/b&gt;&lt;/div&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;DocumentRoot /var/www/html&lt;/div&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;CustomLog /var/www/logs/access&lt;/div&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;ErrorLog /var/www/logs/error&lt;/div&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;User apache&lt;/div&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;Group apache&lt;/div&gt;&lt;br /&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&lt;b&gt;Lighttpd:&lt;/b&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;server.document-root="/var/www/html"&lt;/div&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;accesslog.filename="/var/www/logs/access"&lt;/div&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;server.errorlog="/var/www/logs/error"&lt;/div&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;server.username="apache"&lt;/div&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;server.groupname="apache"&lt;/div&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;server.modules=("mod_cml")&lt;/div&gt;&lt;br /&gt;#3.2.2 Virtual Hosts&lt;br /&gt;&lt;br /&gt;Below is an example of difference between VirtualHosts of Apache and Lighttpd. Example is shown for &lt;b&gt;myproject&lt;/b&gt; project.&lt;br /&gt;&lt;br /&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&lt;b&gt;Apache:&lt;/b&gt;&lt;/div&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;NameVirtualHost *&lt;/div&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&lt;virtualhost *:80=""&gt;&amp;lt;VirtualHost *:80&amp;gt;&lt;br /&gt;&amp;nbsp;ServerName 'www.myproject.com'&lt;br /&gt;&amp;nbsp;DocumentRoot '/web/&lt;/virtualhost&gt;myproject&lt;virtualhost *:80=""&gt;/web'&lt;br /&gt;&amp;nbsp;ErrorLog '/web/logs/&lt;/virtualhost&gt;myproject&lt;virtualhost *:80=""&gt;_error'&lt;br /&gt;&amp;lt;/VirtualHost&amp;gt;&lt;/virtualhost&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;Include conf.d/virtualhosts/*.conf&lt;/div&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&lt;b&gt;Lighttpd:&lt;/b&gt;&lt;/div&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;$HTTP[“host”] == “www.myproject.com” {&lt;/div&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;server.document-root=”/web/myproject/web”&lt;/div&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;server.errorlog="/web/myproject_error"&lt;/div&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;}&lt;/div&gt;&lt;br /&gt;#3.2.3 Authentication and Authorization&lt;br /&gt;&lt;br /&gt;Lighttpd, at this moment, does not support .htaccess files, so all settings must be specified in the lighttpd.conf file, or the configuration files that it includes. However it understands Apache user files for basic and digest authentication, but group file support is not yet implemented but will be implemented soon. Here is an example of authentication and authorization:&lt;br /&gt;&lt;br /&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&lt;b&gt;Apache:&lt;/b&gt;&lt;/div&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;lt;Directory ~&amp;gt;&lt;br /&gt;&amp;nbsp; AuthName "Authentication required to access this area."&lt;br /&gt;&amp;nbsp; AuthType Basic&lt;br /&gt;&amp;nbsp; AuthUserFile /web/myproject/docs/valid.users&lt;br /&gt;&amp;nbsp; Order deny,allow&lt;br /&gt;&amp;nbsp; Require valid-user&lt;br /&gt;&amp;lt;/Directory&amp;gt;&lt;br /&gt;&amp;nbsp;&lt;/div&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&lt;b&gt;Lighttpd:&lt;/b&gt;&lt;/div&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;auth.backend="htpasswd"&lt;/div&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;auth.backend.htpasswd.userfile="/web/myproject/docs/valid.users"&lt;/div&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;auth.require=&lt;/div&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;("~" =&amp;gt;&lt;/div&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp; (&lt;/div&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; "method" =&amp;gt;"basic",&lt;/div&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; "realm"&amp;nbsp; =&amp;gt;"Authentication required to access this area.",&lt;/div&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; "require"=&amp;gt;"valid-user"&lt;/div&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp; )&lt;/div&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;)&lt;/div&gt;&lt;br /&gt;Summarily, configuration file of Lighttpd server behaves like an active script in which you can declare variables, write logic, do computation based upon criteria etc. similar like programming script. This feature makes configuration file alive and agile.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: x-large;"&gt;#4 How to run PHP under Lighttpd&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: large;"&gt;#4.1 Configuring PHP under Lighttpd&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Apache processes PHP internally i.e using it as Shared module &lt;b&gt;mod_php&lt;/b&gt; while Lighttpd runs PHP under &lt;b&gt;FastCGI&lt;/b&gt;. Although Apache also supports FastCGI, using PHP under FastCGI with Apache is neglected and is not used. However with Lighttpd, only option is to run under FastCGI, PHP must be compiled with FastCGI option (thought it is not used with Apache). For more information, please read http://trac.lighttpd.net/trac/wiki/TutorialLighttpdAndPHP. Below is the example of difference between running PHP under Apache and lighttpd.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;Apache:&lt;/span&gt;&lt;/b&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;LoadModule php5_module modules/libphp5.so&lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;AddType application/x-httpd-php .php&lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;b&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;Lighttpd:&lt;/span&gt;&lt;/b&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;server.modules=( ..., "mod_fastcgi", ... )&lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;fastcgi.server=( ".php" =&amp;gt;&lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; (&lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; (&lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; "socket" =&amp;gt; "/tmp/php-fastcgi.socket",&lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; "bin-path" =&amp;gt; "/usr/bin/php-cgi",&lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; "broken-scriptfilename" =&amp;gt; "enable",&lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; "bin-environment" =&amp;gt;&lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; (&lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; "PHP_FCGI_CHILDREN" =&amp;gt; "2",&lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; "PHP_FCGI_MAX_REQUESTS" =&amp;gt; "5000"&lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ),&lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; "min-procs" =&amp;gt; 1,&lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; "max-procs" =&amp;gt; 2,&lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; "idle-timeout" =&amp;gt; 60&lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; )&lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; )&lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; )&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;You may require to set path of &lt;b&gt;php-cgi&lt;/b&gt; according to your setup. Please note that directive server.modules actually exists along with other modules on top of configuration file hence above line indicates that mod_fastcgi should be enabled in lighttpd.cnf.&lt;br /&gt;&lt;br /&gt;Then it will require to set 1 directive in following way in &lt;b&gt;php.ini&lt;/b&gt; configuration file if it exists, if&amp;nbsp; doesn't then nothing to do.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;cgi.fix_pathinfo=1&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Last 4 directives of above mentioned configuration are for running PHP scripts in better ways. &lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: large;"&gt;&lt;span style="font-family: inherit;"&gt;#4.2 Application wise changes&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;As FastCGI is a separate process, we can't handle directives of PHP into configuration file of web server (i.e lighttpd.conf). This is one of the biggest drawback of FastCGI that is why PHP is not used under FastCGI. Moreover under FastCGI mode, your PHP script would get limited support from web server which may force you to change or rewrite your scripts. Hence it is not recommended to use PHP under Lighttpd (at this moment because Lighttpd currently supports only FastCGI mode) because of it's lack of features that PHP will require like enabling configuration options of php.ini in configuration file for all hosts or per host base.&lt;br /&gt;&lt;br /&gt;Moreover many benchmarks shows that PHP runs slower under FastCGI than under shared version on Apache.&lt;br /&gt;&lt;br /&gt;However if it is required to run PHP on Lighttpd, then 2 major changes will require. They are:&lt;br /&gt;&lt;ol style="text-align: left;"&gt;&lt;li&gt;To move all PHP related setting either in &lt;b&gt;php.ini&lt;/b&gt; directly or in configuration or global file of the application.&lt;/li&gt;&lt;li style="font-family: inherit;"&gt;Removing all Apache web server related variables and settings from application.&lt;/li&gt;&lt;/ol&gt;Once these changes are done, it will require to test application heavily to find whether functionalities of application get broken somewhere or not. &lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: x-large;"&gt;&lt;span style="font-family: inherit;"&gt;#5 mod_uploadprogress and Prototype&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;This feature will be available in Lighttpd version &lt;b&gt;1.5.0&lt;/b&gt; which is not released yet, hence can not test or write more about it. More information about this module can be found &lt;a href="http://trac.lighttpd.net/trac/wiki/Docs:ModUploadProgress" target="_blank"&gt;at here&lt;/a&gt;. However when it will get released, it would surely be one of the finest module of Lighttpd server because it can be easily integrated with front-end applications using JSON.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: x-large;"&gt;#6 Lighttpd and output compression&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Lighttpd provides output compression for static data through &lt;b&gt;mod_compress&lt;/b&gt; module. Which means before sending static contents to client, mod_compress compresses it and saves at specified path. This compressed and cached copy will be served directly from cached location when similar request is made from same or different client. Thus saving valuable bandwidth and increasing response time.&lt;br /&gt;&lt;br /&gt;Lighttpd supports 3 types of compressions viz. &lt;b&gt;deflate&lt;/b&gt;, &lt;b&gt;gzip&lt;/b&gt; and &lt;b&gt;bzip2&lt;/b&gt;. The limitation of compressing and caching is that Lighttpd can not compress files with size more than &lt;b&gt;128 MByte&lt;/b&gt; and less than &lt;b&gt;128 Bytes&lt;/b&gt;. &lt;br /&gt;&lt;br /&gt;To enable compression we need to set 3 directives in lighttpd.conf file. They are:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;compress.cache-dir="/var/www/cache/myproject/"&lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;compress.filetype=("text/plain", "text/html")&lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;compress.max-filesize=1 MB&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;However since there is upper limit of file size of 128 Mbytes, the last directive is not necessary to declare. While compressing various types of static data, it should be kept in mind that if no file type or wrong file type is mentioned then no file will get compressed.&lt;br /&gt;&lt;br /&gt;You may require to manually create cache folder and assign necessary write permissions to it. These cached contents do not automatically get cleared hence it is left to developer to clean it at periodic level when required. Following type of command can be used to remove contents that are older than a week.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;$ find /var/www/cache/myproject/ -type f -mtime +7 | xargs -r rm&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;To compress dynamic contents, we need to reply on PHP itself as PHP natively supports good compression of dynamic contents. For that following 2 directives are to be set in php.ini or in equivalent configuration file.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;zlib.output_compression=1&lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;zlib.output_handler=On&lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;br /&gt;Please note that to use &lt;b&gt;zlib.output_compression&lt;/b&gt;, value of output_handler should be &lt;b&gt;zlib.output_handler&lt;/b&gt; instead of standard &lt;b&gt;output_handler&lt;/b&gt;. To do so, &lt;b&gt;output_handler&lt;/b&gt; directive is to be set in following way:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;output_handler=zlib.output_handler&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;or&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;zlib.output_handler=On&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: x-large;"&gt;#7 Lighttpd and caching&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: large;"&gt;#7.1 Caching overview&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Caching is also another method to gain better performance in serving contents and increasing response time of your PHP scripts. There are several types of caching softwares available for PHP. Some important from them are Zend Platform, APC (APC GUI), XCache, eAccelerator, ionCube Encoder and PHP Accelerator. Certain web servers like Lighttpd provides built in modules for caching static contents at web server level. They are &lt;b&gt;mod_expire, mod_mem_cache&lt;/b&gt; and &lt;b&gt;mod_cml&lt;/b&gt;. Hence using combination of caching static and dynamic contents effectively, we can gain lot of speed in serving contents. However all of these mechanisms are not similar.&lt;br /&gt;&lt;br /&gt;Aforementioned independent softwares are for &lt;b&gt;Opcode/Bytecode&lt;/b&gt; caching i.e caching your PHP script into compiled state so that when new request arrives for same script, cache software will server compiled version of code directly from cache rather than reading file again from the disk and then compiling. From these 6, &lt;b&gt;eAccelerator&lt;/b&gt;, &lt;b&gt;XCache&lt;/b&gt; and &lt;b&gt;APC&lt;/b&gt; are widely used caching softwares. This benchmarks also show that how XCache and APC are &lt;a href="http://itst.net/wp-content/uploads/2006/10/PHP%20Bytecode%20Cacher%20Review.html" target="_blank"&gt;better than others&lt;/a&gt;. We will learn more about XCache in a short while.&lt;br /&gt;&lt;br /&gt;As said earlier that &lt;b&gt;only good&lt;/b&gt; combination of static and dynamic contents can give considerable boost in performance, we should try to cache as much contents as possible. To cache static contents, integrated modules of web server are the best candidates. In case of Lighttpd they are mod_expire and mod_mem_cache (however this is not provided as default).&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: large;"&gt;#7.2 mod_expire&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Mod_expire&lt;/b&gt; controls the &lt;b&gt;Expire&lt;/b&gt; header in the &lt;b&gt;Response &lt;/b&gt;Header of HTTP/1.0 messages. It is useful to set it for static files which should be cached like images, style-sheets etc. To use this module, first it needs to get enabled in &lt;b&gt;server.modules&lt;/b&gt; directive array. Then module specific directives are to be set in server's configuration file as shown below.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;lt;access|modification&amp;gt; &amp;lt;number&amp;gt; &amp;lt;years|months|days|hours|minutes|seconds&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Some examples could be like:&lt;br /&gt;&lt;ul style="text-align: left;"&gt;&lt;li&gt;Cache contents of folder images for 2 hours.&lt;/li&gt;&lt;/ul&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;expire.url = ( "/images/" =&amp;gt; "access 2 hours" )&lt;/span&gt;&lt;br /&gt;&lt;ul style="text-align: left;"&gt;&lt;li&gt;Cache contents of all sub-folders of images folder for 2 hours.&lt;/li&gt;&lt;/ul&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;$HTTP["url"] =~ "^/images/" {&lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; expire.url = ( "" =&amp;gt; "access 2 hours" )&lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Values can be hours, months, days etc. depending upon requirement.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: large;"&gt;#7.3 mod_mem_cache&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style="text-align: left;"&gt;Mod_mem_cache is a plugin which stores content of files in memory for faster serving. That is it stores specified file types into memory to serve directly from there without going to read it from disk from specified location thus saving disk read access time. This module is a 3rd party module, hence is not included in the official distribution of Lighttpd.&lt;br /&gt;&lt;br /&gt;This module doesn't seem that much promising to use effectively for caching as memory should be used for processing data rather than storing data. Moreover memory should not be occupied for serving files that can reside and easily managed on disks. For example when we have thousands of images to be served then it is not advisable to store them into memory just to serve it faster. More information about this plugin can be found &lt;a href="http://trac.lighttpd.net/trac/wiki/Docs:ModMemCache" target="_blank"&gt;at here&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: large;"&gt;#7.4 mod_cml (Cache Meta Language)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Mod_cml&lt;/b&gt; is an another caching module similar like &lt;b&gt;mod_expire&lt;/b&gt; which is provided by Lighttpd to cache &lt;b&gt;static contents of dynamic pages&lt;/b&gt;. The difference between mod_expire and mod_cml is that mod_cml can cache fragmented static contents which are part of dynamic contents. For example a dynamic page called &lt;b&gt;index.php&lt;/b&gt; might have static contents like menu.html, banner.html inside it which are not integral part of index.php. In such case using mod_cml, these 2 static contents can be cached and can be delivered directly from there.&lt;br /&gt;&lt;br /&gt;But such type of caching can not be handled directly by Lighttpd web server and mod_cml hence we need to write some code in PHP or in special CML scripts for mod_cml which is written in &lt;b&gt;lua&lt;/b&gt; programming language.&lt;br /&gt;&lt;br /&gt;To use mod_cml, it requires to install lua programming language and libmemcache-1.3.x. Additionally Lighttpd must be compiled with 2 options &lt;b&gt;--with-lua&lt;/b&gt; and &lt;b&gt;–with-memcache&lt;/b&gt;. &lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: large;"&gt;&lt;span style="font-family: inherit;"&gt;#7.5 XCache&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;XCache&lt;/b&gt; is a newly emerging candidate in the market of caching PHP scripts. This is an independent software and not a module of Lighttpd. However it has been written by developers of Lighttpd. &lt;br /&gt;&lt;br /&gt;XCache is an open-source &lt;b&gt;opcode&lt;/b&gt; cacher, which means that it accelerates the performance of PHP on servers. It optimizes performance by removing the compilation time of PHP scripts by caching the compiled state of PHP scripts into the shm (RAM) and uses the compiled version straight from the RAM. This will increase the rate of page generation time by up to 5 times as it also optimizes many other aspects of php scripts and reduce server load. Some of the good features of XCache are:&lt;/div&gt;&lt;ol style="text-align: left;"&gt;&lt;li&gt;Optimized opcode cache.&lt;/li&gt;&lt;li&gt;Using a generator to produce C code, reduces human mistake greatly.&lt;/li&gt;&lt;li&gt;Running stable on PHP_4_3/PHP_4_4&lt;/li&gt;&lt;li&gt;Supported and tested on all latest php cvs branches, such as PHP_4_3 PHP_4_4 PHP_5_0 PHP_5_1 PHP_5_2 HEAD (6.x)&lt;/li&gt;&lt;li&gt;Alpha supported for in-alpha-php6, with Unicode enabled.&lt;/li&gt;&lt;li&gt;Read-only Cacher Protection that prevents the cache from being corrupted by php-core/extension or any code other than XCache itself.&lt;/li&gt;&lt;li&gt;Atomic get/set/inc/dec API operation on var cache for php programmers.&lt;/li&gt;&lt;li&gt;Optimizer&lt;/li&gt;&lt;li&gt;Encoder/Decoder(Loader)&lt;/li&gt;&lt;li&gt;&lt;b&gt;Administrator Script&lt;/b&gt;&lt;/li&gt;&lt;/ol&gt;&lt;blockquote class="tr_bq" style="text-align: left;"&gt;&lt;ol&gt;&lt;li&gt;view statistics&lt;/li&gt;&lt;li&gt;to see if it's AutoDisableOnCorrupted?&lt;/li&gt;&lt;li&gt;view cached php/variable list&lt;/li&gt;&lt;li&gt;clear cache&lt;/li&gt;&lt;/ol&gt;&lt;/blockquote&gt;The last feature allows administrator to view statistic and cached PHP variables and manage caching behavior of XCache.&lt;br /&gt;&lt;br /&gt;#7.5.1 Installing XCache&lt;br /&gt;&lt;br /&gt;The standard way to install XCache is from source. Get your desired version of XCache &lt;a href="http://trac.lighttpd.net/xcache/" target="_blank"&gt;from here&lt;/a&gt;. Then follow below steps to install it.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;# tar -zxf xcache-*.tar.gz&lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;# cd xcache&lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;# phpize&lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;# ./configure --enable-xcache&lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;# make&lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;# su&lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;# make install&lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;# cat xcache.ini &amp;gt;&amp;gt; /etc/php.ini&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;To make sure XCache is properly installed, run below command.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;$ php-fcgi -v&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;It will show string like with &lt;b&gt;XCache vX.X, Copyright (c) XXXX-XXXX, by XXX&lt;/b&gt;. Same can be checked from output of &lt;b&gt;phpinfo()&lt;/b&gt; function also. Once XCache is installed, it will require to edit &lt;b&gt;xcache.ini&lt;/b&gt; which contain various caching related directives to be used. However it is not mandatory to edit or change. A complete explanation of all the directives can be found from http://trac.lighttpd.net/xcache/wiki/PhpIni.&lt;br /&gt;&lt;br /&gt;#7.5.2 Configuring Administrator panel&lt;br /&gt;&lt;br /&gt;XCache Administrator panel is an important web interface that you can monitor and operate your opcode cache, seeing how well(or bad) it goes. Since this page is protected by http-auth, it will require to provide certain values in xcache.ini. For that set below 2 directives.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;xcache.admin.user='USER'&lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;xcache.admin.pass='MD5(PASSWORD)'&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;where USER is name of user you wish to use and MD5(PASSWORD) is MD5 encrypted string of password that you wish to use for given USER. &lt;br /&gt;&lt;br /&gt;To set up web interface, copy &lt;b&gt;xcache/admin/&lt;/b&gt; (the whole directory) to your web document-root or sub-directory of it then request it from your browser, a http-auth prompt will popup where you will require to provide above USER and PASSWORD (as a normal string, not MD5 encrypted string). However sometimes installing XCache from rpm based utilities it may require to alias in web server instead of copying the script. To do so, add below directive in your server configuration file.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;Apache:&lt;/span&gt;&lt;/b&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;Alias /xcache-admin/ /usr/share/xcache/admin/&lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;b&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;Lighttpd:&lt;/span&gt;&lt;/b&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;alias.url += ("/xcache-admin/" =&amp;gt; "/usr/share/xcache/admin/")&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Gaining performance boost by using caching mechanism is tricky. Unless used carefully, it cannot give required boost. As we know that we can't cache everything (specially dynamic contents), we should try to cache whatever is left. This can be achieved by various types of caching as discussed above. Static contents are well cached by clients, if not then can be cached by web servers. PHP scripts can be cached using Opcode caching softwares like APC, XCache etc. While static part of dynamic data can be cached by modules like mod_cml (for lighttpd web server only). &lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: x-large;"&gt;#8 Summary&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Summarily, Lighttpd web server is surely worth to have look at it and to be used for serving static data. For dynamic contents like PHP scripts, it is not optimized (because of support of only FastCGI) hence we have to wait until Shared module version PHP get started to support by it. At this moment it is widely used to server static contents only. So it will take time for it to really start competing with Apache.&lt;br /&gt;&lt;br /&gt;However certain modules like &lt;b&gt;mod_secdownload, mod_compress, mod_geoip, mod_trigger_b4_dl, mod_uploadprogress, mod_useronline&lt;/b&gt; etc. are peculiar modules of Lighttpd which can make it stand firmly with currently popular web servers. &lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: x-large;"&gt;#9 Links&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.onlamp.com/pub/a/onlamp/2007/04/05/the-lighttpd-web-server.html"&gt;http://www.onlamp.com/pub/a/onlamp/2007/04/05/the-lighttpd-web-server.html&lt;/a&gt;&lt;br /&gt;&lt;a href="http://survey.netcraft.com/Reports/0703/"&gt;http://survey.netcraft.com/Reports/0703/&lt;/a&gt;&lt;br /&gt;&lt;a href="http://schlitt.info/applications/blog/index.php?/archives/504-Apache-vs.-Lighttpd-echo-performance.html"&gt;http://schlitt.info/applications/blog/index.php?/archives/504-Apache-vs.-Lighttpd-echo-performance.html&lt;/a&gt;&lt;br /&gt;&lt;a href="http://trac.lighttpd.net/trac/wiki/TutorialInstallation"&gt;http://trac.lighttpd.net/trac/wiki/TutorialInstallation&lt;/a&gt;&lt;br /&gt;&lt;a href="http://trac.lighttpd.net/trac/wiki/TutorialConfiguration"&gt;http://trac.lighttpd.net/trac/wiki/TutorialConfiguration&lt;/a&gt;&lt;br /&gt;&lt;a href="http://trac.lighttpd.net/trac/wiki/Docs:ConfigurationOptions"&gt;http://trac.lighttpd.net/trac/wiki/Docs:ConfigurationOptions&lt;/a&gt;&lt;br /&gt;&lt;a href="http://trac.lighttpd.net/trac/wiki/TutorialLighttpdAndPHP"&gt;http://trac.lighttpd.net/trac/wiki/TutorialLighttpdAndPHP&lt;/a&gt;&lt;br /&gt;&lt;a href="http://trac.lighttpd.net/trac/wiki/Docs:ModUploadProgress"&gt;http://trac.lighttpd.net/trac/wiki/Docs:ModUploadProgress&lt;/a&gt;&lt;br /&gt;&lt;a href="http://trac.lighttpd.net/trac/wiki/Docs:ModCompress"&gt;http://trac.lighttpd.net/trac/wiki/Docs:ModCompress&lt;/a&gt;&lt;br /&gt;&lt;a href="http://blog.lighttpd.net/articles/2006/08/01/mod_uploadprogress-is-back"&gt;http://blog.lighttpd.net/articles/2006/08/01/mod_uploadprogress-is-back&lt;/a&gt;&lt;br /&gt;&lt;a href="http://trac.lighttpd.net/trac/wiki/Docs:ModCML"&gt;http://trac.lighttpd.net/trac/wiki/Docs:ModCML&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www-128.ibm.com/developerworks/library/os-php-fastapps1/index.html"&gt;http://www-128.ibm.com/developerworks/library/os-php-fastapps1/index.html&lt;/a&gt;&lt;br /&gt;&lt;a href="http://trac.lighttpd.net/xcache/wiki/Faq"&gt;http://trac.lighttpd.net/xcache/wiki/Faq&lt;/a&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/298834846183725348-2153803766831775928?l=arzala.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://arzala.blogspot.com/feeds/2153803766831775928/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=298834846183725348&amp;postID=2153803766831775928' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/298834846183725348/posts/default/2153803766831775928'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/298834846183725348/posts/default/2153803766831775928'/><link rel='alternate' type='text/html' href='http://arzala.blogspot.com/2008/03/lighttpd-vs-apache.html' title='Lighttpd vs. Apache'/><author><name>Anirudhsinh Zala</name><uri>http://www.blogger.com/profile/16341197487842993303</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://2.bp.blogspot.com/-jEmJYVgTwk0/Tu4SjN7xOgI/AAAAAAAAABI/17BzjhETHMM/s220/me.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-298834846183725348.post-2796791006094610396</id><published>2008-01-02T17:14:00.000+05:30</published><updated>2011-12-30T17:21:24.690+05:30</updated><category scheme='http://www.blogger.com/atom/ns#' term='performance'/><category scheme='http://www.blogger.com/atom/ns#' term='reverse proxy'/><category scheme='http://www.blogger.com/atom/ns#' term='cache'/><category scheme='http://www.blogger.com/atom/ns#' term='varnish'/><title type='text'>Varnish accelerator</title><content type='html'>&lt;div dir="ltr" style="text-align: left;" trbidi="on"&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-size: x-large;"&gt; #1 Introduction&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Varnish is a high performance HTTP accelerator (more precisely a Reverse proxy server) designed for content-heavy dynamic web sites. In contrast to other HTTP accelerators, many of which began life as client-side proxies or origin servers, Varnish was designed from the ground up as an HTTP accelerator. The Varnish web site claims that Varnish is ten to twenty times faster than the popular Squid cache on the same hardware. &lt;br /&gt;&lt;br /&gt;Varnish is installed within the neighbourhood of one or more webservers. All connections coming from the Internet addressed to one of the webservers are routed through the proxy server, which may either deal with the request itself or pass the request wholly or partially to the main webserver. &lt;br /&gt;&lt;br /&gt;There are various reasons to install reverse proxies. They are: &lt;br /&gt;&lt;ul style="text-align: left;"&gt;&lt;li&gt;Security: the proxy server is an additional layer of defence and therefore protects the webservers further up the chain. &lt;/li&gt;&lt;li&gt;Encryption / SSL acceleration: when secure websites are created, the SSL encryption is sometimes not done by the webserver itself, but by a reverse proxy that is equipped with SSL acceleration hardware. &lt;/li&gt;&lt;li&gt;Load distribution: the reverse proxy can distribute the load to several servers, each server serving its own application area. In the case of reverse proxying in the neighbourhood of webservers, the reverse proxy may have to rewrite the URLs in each webpage (translation from externally known URLs to the internal locations). &lt;/li&gt;&lt;li&gt;Caching static content: A reverse proxy can offload the webservers by caching static content, such as images. Proxy caches of this sort can often satisfy a considerable amount of website requests, greatly reducing the load on the central web server.&lt;/li&gt;&lt;li&gt;Compression: the proxy server can optimize and compress the content to speed up the load time.&lt;/li&gt;&lt;li&gt;Spoon feeding: if a program is producing the webpage on the webservers, the webservers can produce it, serve it to the reverse-proxy, which can spoon-feed it however slowly the clients need and then close the program rather than having to keep it open while the clients insist on being spoon fed.&lt;/li&gt;&lt;/ul&gt;&lt;span style="font-size: x-large;"&gt;#2 Architecture&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Varnish is heavily threaded, with each client connection being handled by a separate worker thread. When the configured limit on the number of active worker threads is reached, incoming connections are placed in an overflow queue; only when this queue reaches its configured limit will incoming connections be rejected. &lt;br /&gt;&lt;br /&gt;The principal configuration mechanism is VCL (Varnish Configuration Language), a DSL used to write hooks which are called at critical points in the handling of each request. Most policy decisions are left to VCL code, making Varnish far more configurable and adaptable than most other HTTP accelerators. When a VCL script is loaded, it is translated to C, compiled to a shared object by the system compiler, and linked directly into the accelerator. &lt;br /&gt;&lt;br /&gt;A number of run-time parameters control things such as the maximum and minimum number of worker threads, various timeouts etc. A command-line management interface allows these parameters to be modified, and new VCL scripts to be compiled, loaded and activated, without restarting the accelerator. &lt;br /&gt;&lt;br /&gt;In order to reduce the number of system calls in the fast path to a minimum, log data is stored in shared memory, and the task of filtering, formatting and writing log data to disk is delegated to a separate application. &lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: x-large;"&gt;#3 Installation&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Here we will go through quick installation process. Please get latest version of Varnish &lt;a href="http://sourceforge.net/project/showfiles.php?group_id=155816" target="_blank"&gt;from here&lt;/a&gt; or check it out from &lt;a href="http://varnish.projects.linpro.no/wiki/Repository" target="_blank"&gt;repository&lt;/a&gt;. &lt;br /&gt;&lt;div lang="en-US" style="margin-bottom: 0in;"&gt;&lt;a href="http://www.blogger.com/blogger.g?blogID=298834846183725348" name="Prerequisites"&gt;&lt;/a&gt;&lt;br /&gt;&lt;span style="font-size: large;"&gt;#3.1 Prerequisites &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;The following tools are required to build Varnish:&lt;/div&gt;&lt;ol&gt;&lt;li&gt;A recent version of GCC.&lt;/li&gt;&lt;li&gt;A POSIX compatible make. &lt;/li&gt;&lt;li&gt;Recent versions of GNU autotools like automake, autoconf, libtool.&lt;/li&gt;&lt;/ol&gt;&lt;div lang="en-US" style="margin-bottom: 0in;"&gt;Latest versions of OSes are most likely to contain above mentioned items. &lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div lang="en-US" style="margin-bottom: 0in; text-align: left;"&gt;&lt;br /&gt;&lt;span style="font-size: large;"&gt;#3.2 Configuring and Building&lt;/span&gt;&lt;/div&gt;&lt;div lang="en-US" style="margin-bottom: 0in;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div lang="en-US" style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; font-style: normal; margin-bottom: 0in; text-decoration: none;"&gt;$ ./autogen.sh&lt;/div&gt;&lt;br /&gt;You may see some error messages. Check if &lt;b&gt;configure&lt;/b&gt; and &lt;b&gt;Makefile.in&lt;/b&gt; were generated. If they weren't, you probably need newer versions of the GNU autotools. If they were; run &lt;b&gt;autogen.sh&lt;/b&gt; again: any error messages it still shows the second time around are most likely caused by bugs in autoconf macros installed by other software you have on your machine, and can safely be ignored.&lt;br /&gt;&lt;br /&gt;Next, run configure. In most cases, the defaults are correct and you do not need to specify any command-line options, except perhaps --prefix. If you plan on hacking the Varnish sources, however, you will most likely want to turn on stricter error checks and dependency tracking: &lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;$ ./configure&lt;/span&gt;&lt;br /&gt;&lt;div lang="en-US" style="font-style: normal; margin-bottom: 0in; text-decoration: none;"&gt;&lt;br /&gt;&lt;/div&gt;OR &lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;$ ./configure --enable-debugging-symbols --enable-developer-warnings –enable-dependency-tracking&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;If configure completes without any errors, simply run below two commands to compile and install Varnish. &lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt; $ make &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt; $ make install &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;For more information please visit &lt;a href="http://varnish.projects.linpro.no/wiki/Installation" target="_blank"&gt;this link&lt;/a&gt;&lt;a href="http://varnish.projects.linpro.no/wiki/Installation"&gt;.&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: large;"&gt;#3.3 Enabling Varnish caching &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Varnish API comes with Management console (telnet HOST/IP PORT), Caching process as a child process of management process (varnishd), and some utilities for logging (varnishlog and varnishncsa), statistics of caching (varnishstat), histogram (varnishhist) and log entry ranking (varnishtop). &lt;br /&gt;&lt;br /&gt;Following commands can be used to enable varnish caching on your servers. &lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;$ varnishd -a www.example.com:80 -b www.example.com:8080 &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt; $ varnishd -a www.example.com:80 -f /usr/local/etc/varnish/myconf.vcl &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;$ varnishd -a www.example.com:80 -b www.example.com&lt;/span&gt;&lt;a href="http://www.example.com/" style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&lt;/a&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;:8080 -T www.example.com:6082 &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt; $ varnishd -a www.example.com:80 -f /usr/local/etc/varnish/myconf.vcl -T www.example.com:6082 &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;1st command denotes that website &lt;b&gt;www.example.com&lt;/b&gt; is originally running on port 8080 on Apache web server but it's running through Varnish under port 80 which is default port for http. This is must for production server but for development and/or test server, ports could be exactly in reverse because during development and testing you may want to run your websites without caching. &lt;br /&gt;&lt;br /&gt;Sometimes we might want to use different caching policies (like caching documents having cookies) which is written in special configuration syntax called VCL; in that case 2nd command is useful to tell Varnish to use modified configuration language file than the default one. When &lt;b&gt;-f&lt;/b&gt; switch is used, &lt;b&gt;-b&lt;/b&gt; switch cannot be used together because values of &lt;b&gt;-b&lt;/b&gt; switch is now mentioned in configuration file. &lt;br /&gt;&lt;br /&gt;Once caching is started it can be controlled by management console from which caching can be started, stopped and various configuration values can be set and unset. For that 2 steps are needed. &lt;br /&gt;&lt;ol style="text-align: left;"&gt;&lt;li&gt; enabling Varnish as shown in command 3 or 4 and &lt;/li&gt;&lt;li&gt;using Telnet utility to open management console on given port for given host (like &lt;b&gt;telnet www.example.com 6082&lt;/b&gt;). &lt;/li&gt;&lt;/ol&gt;&lt;div style="text-align: left;"&gt;Please note that to start and stop caching do not just kill process, instead use management console to control caching for particular host. &lt;br /&gt;&lt;br /&gt;Varnish stores log into memory hence to dump it in regular file on disk, use &lt;b&gt;varnishlog&lt;/b&gt; or &lt;b&gt;varnishncsa&lt;/b&gt; utilities. For more information and how to use these and other utilities, please check their man pages. &lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: x-large;"&gt;#4 VCL&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: large;"&gt;#4.1 Description&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;VCL is an acronym for Varnish Configuration Language. In a VCL file, you configure how Varnish should behave. It is like Apache web server's httpd.conf and PHP's php.ini configuration files. &lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: large;"&gt;#4.2 Syntax&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;The VCL syntax is very simple, and deliberately similar to C and Perl. Blocks are delimited by curly braces, statements end with semicolons, and comments may be written as in C, C++ or Perl according to your own preferences. &lt;br /&gt;&lt;br /&gt;In addition to the C-like assignment (=), comparison (==) and boolean (!, &amp;amp;&amp;amp; and ||) operators, VCL sup-ports regular expression and ACL matching using the ~ operator. &lt;br /&gt;&lt;br /&gt;Unlike C and Perl, the backslash (\) character has no special meaning in strings in VCL, so it can be freely used in regular expressions without doubling. &lt;br /&gt;&lt;br /&gt;Assignments are introduced with the set keyword. There are no user-defined variables; values can only be assigned to variables attached to backend, request or document objects. Most of these are typed, and the values assigned to them must have a compatible unit suffix. &lt;br /&gt;&lt;br /&gt;VCL has if tests, but no loops. &lt;br /&gt;&lt;br /&gt;The contents of another VCL file may be inserted at any point in the code by using the include keyword followed by the name of the other file as a quoted string. &lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: large;"&gt;#4.3 How to&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: small;"&gt;#4.3.1 refresh (purge) document when it gets changed on server? &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Refreshing is often called purging a document. There are 2 different ways in Varnish to refresh (purge) any document/s: &lt;/div&gt;&lt;ul style="text-align: left;"&gt;&lt;li&gt;From management console you can type below commands to control purging of desired documents. Regular expressions are allowed in syntax so many documents can be purged by giving few commands.&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;div&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;url.purge ^/$&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;url.purge .*html$ &lt;/span&gt;&lt;/div&gt;&lt;ul style="text-align: left;"&gt;&lt;li&gt;In VCL we can write logic to purge any document when request is method is PURGE. Which means any document that needs to get purged, will require to call same document by PURGE method to remove itself from cache. This is the most convenient and practical way to keep fresh copies of documents in cache. It is also automatic way so server administrator need not to manually purge large amount of documents.&lt;/li&gt;&lt;/ul&gt;&lt;div style="text-align: left;"&gt;Define all possible hosts only from which purging request will be accepted. This is good precaution so that not everyone can purge what is in cache.&lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;acl purge &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;{ &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp; "myhost"; "123.456.789.1"; &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;} &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;When request is received. &lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;sub vcl_recv &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;{ &lt;/span&gt;&lt;br /&gt;&amp;nbsp; &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;if (req.request == "PURGE") &lt;/span&gt;&lt;br /&gt;&amp;nbsp; &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;{ &lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;if (!client.ip ~ purge) &lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;{ &lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;error 405 "Not allowed."; &lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;} &lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;lookup; &lt;/span&gt;&lt;br /&gt;&amp;nbsp; &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;} &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;} &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;When cache is hit (i.e document is to be served from cache). &lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;sub vcl_hit &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;{ &lt;/span&gt;&lt;br /&gt;&amp;nbsp; &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;if(req.request == "PURGE") &lt;/span&gt;&lt;br /&gt;&amp;nbsp; &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;{ &lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;set obj.ttl = 0s; &lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;error 200 "Purged.";&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;}&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;} &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;When cache is missed (i.e document is to be served directly from backend server). &lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;sub vcl_miss &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;{ &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp; if(req.request == "PURGE") &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp; { &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; error 404 "Not in cache."; &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp; } &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;} &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;#4.3.2 cache documents even when cookies are present? &lt;br /&gt;&lt;br /&gt;When request is received. &lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;sub vcl_recv &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;{ &lt;/span&gt;&lt;br /&gt;&amp;nbsp; &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;if (req.request == "GET" &amp;amp;&amp;amp; req.http.cookie) &lt;/span&gt;&lt;br /&gt;&amp;nbsp; &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;{ &lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;lookup; &lt;/span&gt;&lt;br /&gt;&amp;nbsp; &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;} &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;} &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Fetch document from backend server. &lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;sub vcl_fetch &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;{ &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp; if (resp.http.Set-Cookie) &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp; { &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; insert; &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp; } &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;} &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;#4.3.3 support multiple sites running on separate backends in the same Varnish instance? &lt;br /&gt;&lt;br /&gt;Define all backend WWW servers which are to be used for caching. &lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;backend www &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;{ &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp; set backend.host = "www.example.com"; &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp; set backend.port = "8080"; &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;} &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Define all backend Image servers which are to be used for caching. &lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;backend images &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;{ &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp; set backend.host = "images.example.com"; &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp; set backend.port = "8080"; &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;} &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;When request is received.&lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;sub vcl_recv &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;{&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp; if (req.http.host ~ "^(www.)?example.com.com$"&lt;/span&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;) &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp; { &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; set req.backend = www; &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp; } &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp; elsif (req.http.host ~ "^images.example.com") &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp; { &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; set req.backend = images; &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp; } &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp; else &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp; { &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; error 404 "Unknown virtual host"; &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp; } &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;} &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;#4.3.4 force a minimum TTL for all documents?&lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;br /&gt;Fetch document from backend server.&lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;sub vcl_fetch &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;{&lt;/span&gt;&lt;/div&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; text-align: left;"&gt;&amp;nbsp; if (obj.ttl &amp;lt; 120s)&lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp; {&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; set obj.ttl = 120s;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp; }&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: x-large;"&gt;#5 Performance&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;br /&gt;While Varnish is designed to reduce contention between threads to a minimum, its performance will only be as good as that of the system's &lt;b&gt;pthreads&lt;/b&gt; implementation. Additionally, a poor &lt;b&gt;malloc&lt;/b&gt; implementation may add unnecessary contention and thereby limit performance. On FreeBSD (using libthr) and Linux (using native threads), it is believed that performance is limited only by hardware. &lt;br /&gt;&lt;br /&gt;When the requested document is in cache, response time is typically measured in microseconds. This is significantly better than most HTTP servers, so even sites consisting mostly of static content will mostly benefit from Varnish. &lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: x-large;"&gt;#6 Limitations&lt;/span&gt;&lt;/div&gt;&lt;ol style="text-align: left;"&gt;&lt;li&gt;Current versions of Varnish do not understand the HTTP Vary: header, which can lead to problems with sites which support content negotiation. &lt;/li&gt;&lt;li&gt;the HTTP Host: header is always included in the object hash, so sites which can be accessed under multiple different names will have multiple copies of the same content cached. &lt;/li&gt;&lt;li&gt;Default policy of Varnish doesn't allow caching documents having cookies/sessions, which means websites heavily dependent upon cookies and session can not use Varnish out of the box for dynamic documents. To solve this problem VCL is to be tweaked as shown in section 4.3.2. &lt;/li&gt;&lt;li&gt;Varnish’s internal caching mechanism doesn’t obey even the minimum requisite client-side HTTP caching pragmas. It fails to obey other established caching headers, and support for them cannot even be implemented by end users through configuration, because there’s no mechanism to control cache behavior based on Web server HTTP headers — only on client headers. Which means preventing caching of files without an ETag response header is very hard to implement. &lt;/li&gt;&lt;li&gt;Varnish refuses to start if your &lt;b&gt;/tmp&lt;/b&gt; is mounted &lt;b&gt;noexec&lt;/b&gt;. Because Varnish attempts to compile a “shared lib” and load it from /tmp. Such problems are very hard to detect because the startup script doesn’t give any indication, and the log files don’t either. &lt;/li&gt;&lt;li&gt;There is lack of proper documentation for Varnish and VCL. There is some documentation in man pages but it is accessible only when you have Varnish installed on your PC. &lt;/li&gt;&lt;/ol&gt;Most of these limitations have been or are being addressed in the development version.&lt;br /&gt;&lt;div style="text-align: left;"&gt;&lt;br /&gt;&lt;span style="font-size: x-large;"&gt;#7 Conclusion&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;br /&gt;Web accelerators (here caching software) are not &lt;b&gt;install and forget&lt;/b&gt; type of software. They require constant monitoring and inspection on them for their behaviour and effectiveness. Software like Varnish have their limitations as shown in section 6 which must be kept in mind before using them. Then there are other things to be taken care of in your project to use caching most effectively. &lt;/div&gt;&lt;ol style="text-align: left;"&gt;&lt;li&gt;Caching of documents is implemented on &lt;b&gt;GET&lt;/b&gt; and &lt;b&gt;HEAD&lt;/b&gt; methods only. Hence your project must have maximum documents using above 2 methods. &lt;/li&gt;&lt;li&gt;URL structure should be caching friendly. &lt;/li&gt;&lt;li&gt;For dynamic document session IDs should not get appended into URL because they are dynamic and different every time they are generated hence same document having such different session IDs makes caching of documents less effective because same document will have different versions in cache as session IDs are different.&lt;/li&gt;&lt;/ol&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-size: x-large;"&gt;#8 Links&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;br /&gt;&lt;a href="http://varnish.linpro.no/"&gt;http://varnish.linpro.no/&lt;/a&gt; &lt;br /&gt;&lt;a href="http://phk.freebsd.dk/pubs/varnish.pdf"&gt;http://phk.freebsd.dk/pubs/varnish.pdf&lt;/a&gt; &lt;br /&gt;&lt;a href="http://rudd-o.com/archives/2007/07/02/why-the-varnish-cache-sucks-with-bonus-varnish-dev-whining-about-me/"&gt;http://rudd-o.com/archives/2007/07/02/why-the-varnish-cache-sucks-with-bonus-varnish-dev-whining-about-me/&lt;/a&gt; &lt;br /&gt;&lt;a href="http://projects.linpro.no/pipermail/varnish-misc/2007-July/000577.html"&gt;http://projects.linpro.no/pipermail/varnish-misc/2007-July/000577.html&lt;/a&gt; &lt;br /&gt;&lt;a href="http://www.version2.dk/artikel/3084"&gt;http://www.version2.dk/artikel/3084&lt;/a&gt; &lt;br /&gt;&lt;a href="http://varnish.projects.linpro.no/wiki/StatsExplained"&gt;http://varnish.projects.linpro.no/wiki/StatsExplained&lt;/a&gt; &lt;br /&gt;&lt;a href="http://varnish.projects.linpro.no/wiki/FAQ"&gt;http://varnish.projects.linpro.no/wiki/FAQ&lt;/a&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/298834846183725348-2796791006094610396?l=arzala.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://arzala.blogspot.com/feeds/2796791006094610396/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=298834846183725348&amp;postID=2796791006094610396' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/298834846183725348/posts/default/2796791006094610396'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/298834846183725348/posts/default/2796791006094610396'/><link rel='alternate' type='text/html' href='http://arzala.blogspot.com/2008/01/varnish-accelerator.html' title='Varnish accelerator'/><author><name>Anirudhsinh Zala</name><uri>http://www.blogger.com/profile/16341197487842993303</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://2.bp.blogspot.com/-jEmJYVgTwk0/Tu4SjN7xOgI/AAAAAAAAABI/17BzjhETHMM/s220/me.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-298834846183725348.post-750851330924734608</id><published>2007-08-09T17:13:00.000+05:30</published><updated>2011-12-31T21:19:15.399+05:30</updated><category scheme='http://www.blogger.com/atom/ns#' term='php'/><category scheme='http://www.blogger.com/atom/ns#' term='web-service'/><title type='text'>Designing web service</title><content type='html'>&lt;div dir="ltr" style="text-align: left;" trbidi="on"&gt;&lt;span style="font-size: x-large;"&gt;#1 New way of Programming experience&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Designing API requires different way of thinking in programming because API is mainly related to handling raw data and header management. Hence apart from traditional web development, it requires to have good understanding and experience of HTTP Headers, HTTP request methods, REST architectural style, OOP and Responsiveness. &lt;br /&gt;&lt;br /&gt;Another difference between API and normal web application is that once API is being started to use it grows vertically hence it's URL scheme, response headers and types can not be changed that easily so proper care should be taken before designing it. Best practice is to start with providing simple interface of only GETting data. And from that experience more functionality for adding, updating and deleting resources can be added. &lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: x-large;"&gt;#2 Handling input data &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;While designing APIs, developers should not rely on browsers because except POST and GET methods; data coming by other methods will directly come to server skipping the browser. Hence population of incoming data (which is done by PHP by storing them in $_GET and $_POST super globals) would not be possible particularly for PUT and DELETE methods. Which means all data should be handled by standards input which can be accessed from &lt;b&gt;php://input&lt;/b&gt;. After that they can be parsed to extract information in chunks to finally execute requests. Please study &lt;b&gt;example API&lt;/b&gt; for more details about how to handle and implement raw data. &lt;a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html" target="_blank"&gt;This link&lt;/a&gt; explains all possible HTTP methods and how they work. &lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: x-large;"&gt;#3 Structure of codebase&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Normally API would require 1 configuration file to store server specific data, 1 global file to store other global settings, 1 front controller and then bunch of classes according to required modules. Since API doesn't have GUI, multiple controllers are not required. And anyway modern practices recommend having only 1 single controller to receive and dispatch data. &lt;br /&gt;&lt;br /&gt;URL of API could be like &lt;b&gt;http://api.mysite.fi&lt;/b&gt; or &lt;b&gt;http://www.mysite.com/api/&lt;/b&gt;. As far as directory structure is concerned there can be created folders to store API related includable files, classes and controller/s. Since API is part of main application, file and folder structure should conform to existing standards of main application. &lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: x-large;"&gt;#4 Authentication and session management&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Access control and session management are important aspects of API design. When it is required to change state of resource on server then it becomes important to identify client who has made such request. This can be done by asking requester to provide details of account on behalf of which request is made. &lt;br /&gt;&lt;br /&gt;For example, to build generic authentication mechanism a URL like &lt;b&gt;http://www.mysite.fi/api/api_login/&lt;/b&gt; can be provided where clients can submit his/her ID and Password to log on. The API authentication module will verify ID and Password and if found ok then can issue an api_token which can then be used to execute subsequent requests. Depending upon sensitiveness of data various authentication mechanisms can be implemented which includes session based authentication and basic/digest authentications. &lt;br /&gt;&lt;br /&gt;For more information about authentication following resources can be studied: &lt;br /&gt;&lt;br /&gt;&lt;a href="http://code.google.com/apis/gdata/basics.html"&gt;http://code.google.com/apis/gdata/basics.html&lt;/a&gt; &lt;br /&gt;&lt;a href="http://code.google.com/apis/gdata/auth.html"&gt;http://code.google.com/apis/gdata/auth.html&lt;/a&gt; &lt;br /&gt;&lt;a href="http://code.google.com/apis/accounts/AuthForInstalledApps.html"&gt;http://code.google.com/apis/accounts/AuthForInstalledApps.html&lt;/a&gt; &lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: x-large;"&gt;#5 Access control&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;When API get considerable traffic from various clients it becomes important to restrict clients to not to make so many requests at particular time. Depending upon available resources and amount traffic to various resources, various timing related mechanism can be applied so that clients can not submit particular request more than once or twice or thrice for each minute or hour or so and so. This is important to keep hackers/crackers away who can damage API service at various levels. &lt;br /&gt;&lt;br /&gt;For advanced usage, access control can also be applied to allow usage of other users' data. Hence if API client want to use other users' resources, he/she first get confirmation from respective user/s to use his/her data for various purposes. &lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: x-large;"&gt;#6 Caching of common resources &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Once API starts receiving high amount of traffic to particular resource/s, it may become necessary to cache certain resources into memory or file to serve them faster and to save bandwidth. There can be some resources like&lt;b&gt; top rated image of users&lt;/b&gt;, which may not be changing frequently, could be cached.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: x-large;"&gt;#7 Designing URLs&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;As we have adopted REST architectural style for implementing API, we must adhere to it's standards. For that it would require to properly understand REST principles. In REST architectural style, URL of any resource is tightly coupled to &lt;b&gt;request method&lt;/b&gt; of that resource. Which means URL can be same but depending upon request method, response from API could change. For example resource &lt;b&gt;http://www.mysite.fi/api/users/&lt;/b&gt; requested by POST method would mean to add new user to existing users; with GET method will provide list of users. Similarly resource &lt;b&gt;http://www.mysite.fi/api/user/1/&lt;/b&gt;&lt;a href="http://www.mysite.fi/api/user/1/"&gt;&lt;/a&gt; requested by PUT method would update information of particular user; with GET method will provide details of user and; with DELETE method will remove that user from database. &lt;br /&gt;&lt;br /&gt;Please note that if resource &lt;b&gt;http://www.mysite.fi/api/user/1/&lt;/b&gt;&lt;a href="http://www.mysite.fi/api/user/1/"&gt;&lt;/a&gt; is requested by POST method then there should be appropriate error response telling API client that POST method is not allowed for such resource. Similarly no resources can be deleted by GET, POST or PUT methods. For that only DELETE method must be used. Such problem exists with Del.ico.us API where everything is done via &lt;b&gt;GET&lt;/b&gt; including creating, changing and removing resources which is unRESTful way of implementation. &lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: x-large;"&gt;#8 Programming approach&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;A typical API can contain following objects/modules. Each object/module could be a single class to handle request/s at various stages. &lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: large;"&gt;#8.1 Request handler&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;This is the 1st module which will receive request. It will then determine request method, will log client's information and will store raw data received in request. Then it will give control to authentication or session manager. &lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: large;"&gt;#8.2 Authenticator/Session manager&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;This module, if required, will check whether authentication is required for particular request or not. If yes then will inform client via error handler module to send credentials. This module will generate authentication tokens to client for subsequent requests. &lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: large;"&gt;#8.3 Parser&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Once client is authenticated next step would be to parse raw data to extract information from it to for execution. This extracted data will then be handed over to data validator. &lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: large;"&gt;#8.4 Data Validator&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;This module will validate (will check accept type, range and type of data etc.) extracted data for particular requests. If everything is ok then Executer module will be called to execute request for which request is made. &lt;br /&gt;&lt;br /&gt;Here Parser and Data validator modules can be combined together also depending upon convenience of developers. &lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: large;"&gt;#8.5 Executer &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;This module will be collection of various classes which will actually execute request and generate output in Arrays. Such modules could be same as primary objects of requests like &lt;b&gt;image, user, tag&lt;/b&gt; etc. &lt;br /&gt;&lt;br /&gt;These classes should preferably generate data in associate arrays so that it can be used in any format. Once output is generated it will be handed over to renderer module. &lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: large;"&gt;#8.6 Renderer (XML/XHTML/JSON etc.)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;This module will redder generated data and will send back to client. Default format of data could be XML but depending upon query string different format can be provided. There can be separate templates for each format so that in final output dynamic part will be replaced with data and static part will remain as it is. &lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: large;"&gt;#8.7 Error handler&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;This module can be used with any module at any level to inform client about occurrence of any error while executing any request. Format of errors could be like below:&lt;br /&gt;&lt;res status="0"&gt; &lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;lt;?xml version="1.0" encoding="utf-8" ?&amp;gt;&lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;lt;res status="0"&amp;gt;&lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp; &amp;lt;error code="123"&amp;gt;Invalid data. Please read documentation for more details.&amp;lt;/error&amp;gt;&lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;lt;/res&amp;gt;&lt;/span&gt;&lt;/res&gt;&lt;br /&gt;&lt;br /&gt;Note that whenever error occurs, "status" attribute will be set to "0" rather than 1. Apart from custom error messages and codes, standard HTTP headers can also be used to minimize parsing of output at client side to determine whether request was executed successfully or not. &lt;br /&gt;&lt;br /&gt;All these modules classes could be designed by using latest concepts of PHP5. One such concept is to have Getter and Setter methods to set and get data whenever required. It is not easy to test and debug API by conventional browsers because developers can't send raw headers and data by browsers. Hence either API client will require to be designed first or to use other options. One such option is to use LiveHTTPHeaders extension in FF browser. It is an excellent way to send and receive raw data over HTTP to API. By this way developers can easily see what response is received when particular request is made. For more details about this extension, visit link &lt;a href="http://livehttpheaders.mozdev.org/"&gt;http://livehttpheaders.mozdev.org/&lt;/a&gt; &lt;br /&gt;&lt;br /&gt;Excellent resource about how to design RESTful API can be found here &lt;a href="http://www.peej.co.uk/articles/restfully-delicious.html"&gt;http://www.peej.co.uk/articles/restfully-delicious.html&lt;/a&gt;. &lt;br /&gt;&lt;br /&gt;#9 Sample of output of data&lt;br /&gt;&lt;br /&gt;Below is given samples of XML responses. Root level node would be &lt;res&gt;&lt;/res&gt; having attribute 1 or 0 to indicate API client whether request was executed successfully or not. Rest of nodes can be designed as per requirements. It would be noted that most common way of response is XML. Later when API gets more demand, more response format can be provided like Serialized PHP, JSON etc.&lt;br /&gt;&lt;br /&gt;=&amp;gt; Basic XML structure of response: &lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;lt;?xml version="1.0" encoding="utf-8" ?&amp;gt; &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;lt;res status="1"&amp;gt;&amp;lt;/res&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;=&amp;gt; XML structure of response with data: &lt;br /&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&lt;res status="1"&gt;&lt;/res&gt;&lt;/div&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&lt;res status="1"&gt;&amp;lt;?xml version="1.0" encoding="utf-8" ?&amp;gt;&lt;br /&gt;&amp;lt;res status="1"&amp;gt;&lt;br /&gt;&amp;nbsp; &amp;lt;image&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;resource&amp;gt;/image/recent&amp;lt;/resource&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;url&amp;gt;http://www.mysite.fi/images/123456.jpg&amp;lt;/url&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;width&amp;gt;120&amp;lt;/width&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;height&amp;gt;90&amp;lt;/height&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;metadata&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;camera&amp;gt;Canon EOS 60&amp;lt;/camera&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;date-taken&amp;gt;10-09-2007&amp;lt;/date-taken&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/metadata&amp;gt;&lt;br /&gt;&amp;nbsp; &amp;lt;/image&amp;gt;&lt;br /&gt;&amp;lt;/res&amp;gt;&lt;/res&gt;&lt;/div&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&lt;br /&gt;&lt;/div&gt;REST architectural style emphasizes on following 2 rules while responding requests, they are: &lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: large;"&gt;#9.1 Resources should be interconnected&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;which means each response should contain information about previous and next resource. For example while displaying list of users if limit of response is &lt;b&gt;30&lt;/b&gt; records per page then each response should contain link of next and previous list of users if applicable. This tells that by inspecting any response, API client could find what was previous response and what will be the next one. This can be accomplished either by setting attribute/s like &lt;b&gt;next-url&lt;/b&gt; and &lt;b&gt;previous-url&lt;/b&gt; or by providing attributes like &lt;b&gt;tot-page&lt;/b&gt;, &lt;b&gt;cur-page&lt;/b&gt;, &lt;b&gt;next-page&lt;/b&gt; etc. in response XM so that those can be used as query string of request to access next or previous resources. &lt;br /&gt;&lt;br /&gt;Similarly whenever new resource is created, response sent back to client should contain URL of that newly created resource. This is how inter-connectivity works. &lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: large;"&gt;#9.2 Revelation of information should be step by step&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;which means all information should not be responded with just one call. For example request like &lt;b&gt;http://www.mysite.fi/api/images/&lt;/b&gt; should not contain details of each image, instead it can contain link to obtain information of each image (http://www.mysite.fi/api/image/12345_6789.jpg) and after calling that resource, actual information of image would be responded. &lt;br /&gt;&lt;br /&gt;All response should be using UTF-8 characters and encoded in same way before sending to client. &lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: x-large;"&gt;#10 Documentation &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Documentation is must while designing any API. Without documentation none would use your API. Hence it should be prepared in parallel with developing of code. It also should be easy to understand and use. &lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: x-large;"&gt;#11 Example of API&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;It is important to study existing API while building API first time. Below link contains source code of such API. It is REST implementation of managing users and companies. However it is very old and developed in PHP4 but still worth to have look at it specially it's code to understand how to handle, execute and respond various requests. &lt;br /&gt;&lt;br /&gt;&lt;a href="http://nchc.dl.sourceforge.net/sourceforge/phprestsql/phprestsql.tar.gz"&gt;http://nchc.dl.sourceforge.net/sourceforge/phprestsql/phprestsql.tar.gz&lt;/a&gt; &lt;br /&gt;&lt;a href="http://phprestsql.sourceforge.net/tutorial.html"&gt;http://phprestsql.sourceforge.net/tutorial.html&lt;/a&gt; &lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/298834846183725348-750851330924734608?l=arzala.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://arzala.blogspot.com/feeds/750851330924734608/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=298834846183725348&amp;postID=750851330924734608' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/298834846183725348/posts/default/750851330924734608'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/298834846183725348/posts/default/750851330924734608'/><link rel='alternate' type='text/html' href='http://arzala.blogspot.com/2007/06/designing-web-service.html' title='Designing web service'/><author><name>Anirudhsinh Zala</name><uri>http://www.blogger.com/profile/16341197487842993303</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://2.bp.blogspot.com/-jEmJYVgTwk0/Tu4SjN7xOgI/AAAAAAAAABI/17BzjhETHMM/s220/me.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-298834846183725348.post-2417980130907318786</id><published>2007-06-11T17:15:00.000+05:30</published><updated>2011-12-30T15:27:19.080+05:30</updated><category scheme='http://www.blogger.com/atom/ns#' term='version control'/><title type='text'>CVS best practices</title><content type='html'>&lt;div dir="ltr" style="text-align: left;" trbidi="on"&gt;Best practices often requires thorough knowledge of technology that is used in software development. To fully use CVS, we now need to know about tag, trunk, branch, merging etc. to minimize or eliminate certain problems arising of out insufficient use of CVS. In this document it has been shown how we can use CVS in most effective way to minimize such problems. Here are some policies that have been designed to follow whenever it is possible.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: x-large;"&gt;#1 Sandbox&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;The developer &lt;b&gt;sandbox&lt;/b&gt; is where each developer keeps his or her working copy of the code base. In CVS this is referred to as the working directory. This is where they build, test and debug the modules that they are working on. A sandbox can also be the area where the staging build or the production build is done. Changes made in the work area are checked into the CVS repository. In addition, changes made in the repository by others have to be updated in the sandbox on a regular basis.&lt;br /&gt;&lt;br /&gt;The best practices related to developers sandbox are:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: large;"&gt;#1.1 Keep System clocks in Sync&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;CVS tracks change to source files by using the &lt;b&gt;timestamps&lt;/b&gt; on the file. If each client system date and time is not in sync, there is a definite possibility of CVS getting confused. Thus system clocks must be kept in sync by use of a central time server or similar mechanism.&lt;br /&gt;&lt;br /&gt;CVS is designed from ground up to handle multiple timezones. As long as the host operating system has been setup and configured correctly, CVS will be able to track changes correctly.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: large;"&gt;#1.2 Stay in sync with the repository&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;To gain the benefits of working within a sandbox as mentioned above, the developer must keep his or her sandbox in sync with the main repository. A regular cvs update with the appropriate tag or branch name will ensure that the sandboxes are kept up to date.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: large;"&gt;#1.3 Do not share the sandbox&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Sandboxes have to be unique for each developer or purpose. They should not be used for multiple things at the same time. A sandbox can be a working area for a developer or the build area for the final release. If such sandboxes are shared, then the owner of the sandbox will not be aware of the changes made to the files resulting in confusion.&lt;br /&gt;&lt;br /&gt;In CVS, the sandbox is created automatically when a working copy is checked out for a CVS project using the &lt;b&gt;cvs checkout [options] MODULES&lt;/b&gt; command. In very large projects, it does not make sense for the developers to check−out the entire source into the local sandbox. In such cases, they can take only certain modules in which they are working.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: large;"&gt;#1.4 Do not work outside the sandbox&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;The sandbox can be thought of as a controlled area within which CVS can track for changes made to the various source files. Files belonging to other developers will be automatically updated by CVS in the developer's sandbox. Thus the developer who lives within the sandbox will stand to gain a lot of benefits of concurrent development.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: large;"&gt;#1.5 Cleanup after completion&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Make sure that the sandbox is cleaned up after completion of work on the files. Clean up can be done in CVS by using the &lt;b&gt;cvs release [-d] [DIRECTORIES]&lt;/b&gt; command. This ensures that no old version of the files exists in the development sandbox.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: large;"&gt;#1.6 Check−in often&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;To help other developers keep their code in sync with your code, you must check−in (commit) your code often into the CVS repository. The best practice would be to check−in soon as a piece of code is completed, reviewed and tested, check−in the changes with command &lt;b&gt;cvs commit [options] [-m LOG_MESSAGE | -F FILE] [-r revision] [FILES]&lt;/b&gt; to ensure that your changes are committed to the CVS repository.&lt;br /&gt;&lt;br /&gt;CVS promotes concurrent development. Concurrent development is possible only if all the other developers are aware of the ongoing changes on a regular basis. This awareness can be termed as "situation awareness". One of the "bad" practices that commonly occur is the sharing of files between developers by email. This works against most of the best practices mentioned above. To share updates between two developers, CVS must be used as the communication medium. This will ensure that CVS is &lt;b&gt;aware&lt;/b&gt; of the changes and can track them. Thus, audit trail can be established if necessary.&lt;br /&gt;&lt;br /&gt;When you commit a change to the repository, make sure your change reflects a single purpose: the fixing of a specific bug, the addition of a new feature, or some particular task. Your commit will create a new revision number which can forever be used as a &lt;b&gt;name&lt;/b&gt; for the change. You can mention this revision number in bug databases, or use it as an argument to CVS merge should you want to undo the change or port it to another branch.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: large;"&gt;#1.7 Add/Commit data in proper way&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;CVS is not good in handling directories. Hence once any directory is added, can't be removed from repository in normal way. Hence be careful when dealing with directories.&lt;br /&gt;&lt;br /&gt;Moreover CVS tend to exclude empty directories while checking out any module. Which means any directory that is supposed to be empty at check-out time wont be included in checked-out copy of module. This problem often occurs when any directory is used to store temporary files which are not required to keep in CVS. Hence if directory is not present in checked-out module, your local sandbox might not work as expected. To solve this problem an empty file called &lt;b&gt;.keepme&lt;/b&gt; can be added to empty directory.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: large;"&gt;#1.8 Use the issue-tracker wisely&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Try to create as many two-way links between CVS changesets and your issue-tracking (gForge, Bugzilla, Mantis etc.) database as possible:&lt;br /&gt;&lt;br /&gt;If possible, refer to a specific issue ID in every commit log message. When appending information to an issue (to describe progress, or to close the issue) name the revision number(s) responsible for the change.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: x-large;"&gt;#2 Branching and Merging&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Branching in CVS splits a project's development into separate, parallel histories. Changes made on one branch do not affect the other branches. Branching can be used extensively to maintain multiple versions of a product for providing support and new features.&lt;br /&gt;&lt;br /&gt;Merging converges the branches back to the main trunk. In a merge, CVS calculates the changes made on the branch between the point where it diverged from the trunk and the branch's tip (its most recent state), then applies those differences to the project at the tip of the trunk.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: large;"&gt;#2.1 Know when to create branches&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;This is a hotly debated question, and it really depends on the culture of your software project. Rather than prescribe a universal policy, we'll describe three common ones here.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: small;"&gt;#2.1.1 The Never-Branch system&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;(Often used by nascent projects that don't yet have runnable code.) Users commit their day-to-day work on /trunk. Occasionally /trunk "breaks" (doesn't compile, or fails functional tests) when a user begins to commit a series of complicated changes.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Pros:&lt;/b&gt; Very easy policy to follow. New developers have low barrier to entry. Nobody needs to learn how to branch or merge.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Cons:&lt;/b&gt; Chaotic development, code could be unstable at any time.&lt;br /&gt;&lt;br /&gt;&lt;i&gt;Note:&lt;/i&gt; this sort of development is a bit less risky in Subversion than in CVS. Because Subversion commits are atomic, it's not possible for a checkout or update to receive a "partial" commit while somebody else is in the process of committing.&lt;br /&gt;&lt;br /&gt;#2.1.2 The Always-Branch system&lt;br /&gt;&lt;br /&gt;(Often used by projects that favor heavy management and supervision.) Each user creates/works on a private branch for every coding task. When coding is complete, someone (original coder, peer, or manager) reviews all private branch changes and merges them to /trunk.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Pros:&lt;/b&gt; /trunk is guaranteed to be extremely stable at all times. &lt;br /&gt;&lt;br /&gt;&lt;b&gt;Cons:&lt;/b&gt; Coders are artificially isolated from each other, possibly creating more merge conflicts than necessary. Requires users to do lots of extra merging.&lt;br /&gt;&lt;br /&gt;#2.1.3 The Branch-When-Needed system&lt;br /&gt;&lt;br /&gt;Users commit their day-to-day work on /trunk.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Rule #1:&lt;/b&gt; /trunk must compile and pass regression tests at all times. Committers who violate this rule are publicly humiliated.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Rule #2:&lt;/b&gt; a single commit (changeset) must not be so large so as to discourage peer-review.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Rule #3:&lt;/b&gt; if rules #1 and #2 come into conflict (i.e. it's impossible to make a series of small commits without disrupting the trunk), then the user should create a branch and commit a series of smaller changesets there. This allows peer-review without disrupting the stability of /trunk.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Pros:&lt;/b&gt; /trunk is guaranteed to be stable at all times. The hassle of branching/merging is somewhat rare.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Cons:&lt;/b&gt; Adds a bit of burden to users' daily work: they must compile and test before every commit.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: large;"&gt;#2.3 Assign ownership to Trunk and Branches&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;The main trunk of the source tree and the various branches should have a owner assigned who will be responsible for.&lt;br /&gt;&lt;br /&gt;#2.3.1 Keeping the list of configurable items for the branch or trunk&lt;br /&gt;&lt;br /&gt;The owner will be the maintainer of the contents list for the branch or trunk. This list should contain the item name and a brief description about the item. This list is essential since new artifacts are always added to or removed from the repository on an ongoing basis. This list will be able to track the new additions/deletions to the repository for the respective branch.&lt;br /&gt;&lt;br /&gt;#2.3.2 Establishing a working policy for the branch or trunk&lt;br /&gt;&lt;br /&gt;The owner will establish policies for check−in and check−out. The policy will define when the code can be checked in (after coding or after review etc.,). Who is responsible to merge changes on the same file and resolve conflicts (the author or the person who recently changed the file).&lt;br /&gt;&lt;br /&gt;#2.3.3 Identifying and document policy deviations&lt;br /&gt;&lt;br /&gt;Policies once established tend to have exceptions. The owner will be responsible for identifying the workaround and tracking/documenting the same for future use.&lt;br /&gt;&lt;br /&gt;#2.3.4 Merging with the trunk&lt;br /&gt;&lt;br /&gt;The branch owner will be responsible for ensuring that the changes in the branch can be successfully merged with the main trunk at a reasonable point in time.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: large;"&gt;#2.3 Tag each release&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;As part of the release process, the entire code base must be tagged (by &lt;b&gt;cvs tag [options] SYMBOLIC_TAG [FILES]&lt;/b&gt; command) with an identifier that can help in uniquely identifying the release. A tag gives a label to the collection of revisions represented by one developer's working copy (usually, that working copy is completely up to date so the tag name is attached to the "latest and greatest" revisions in the repository).&lt;br /&gt;&lt;br /&gt;The identifier for the tag should provide enough information to identify the release at any point in time in the future. One suggested tag identifier is of the form.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;release_{major version #}_{minor version #}&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;Checkout the entire codebase using the tag, and then proceed to go through a build / deploy / test process before making the actual release. This will absolutely ensure that what "leaves the door " is a verified and tested codebase.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: large;"&gt;#2.4 Create a branch after each release&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;After each software release, once the CVS repository is tagged, a branch has to be immediately created. This branch will serve as the bug fix baseline for that release. This branch is created only if the release is not a bug fix or patch release in the first place. Patches that have to be made for this release at any point in time in the future will be developed on this branch. The main trunk will be used for ongoing product development.&lt;br /&gt;&lt;br /&gt;With this arrangement, the changes in the code for the ongoing development will be on the main trunk and the branch will provide a separate partition for hot fixes and bug fix releases.The identifier for the branch name can be of the form.&lt;br /&gt;&lt;br /&gt;A branch can be created using &lt;b&gt;cvs tag -b BRANCH_NAME&lt;/b&gt; command.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: large;"&gt;#2.5 Make bug fixes to branches only&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;This practice extends from the previous practice of creating a separate branch after a major release. The branch will serve as the code base for all bug fixes and patch release that have to be made. Thus, there is a separate repository "sandbox" where the hot fixes and patches can be developed apart from the mainstream development.&lt;br /&gt;&lt;br /&gt;This practice also ensures that bug fixes done to previous releases do not mysteriously affect the mainstream version. In addition, new features added to the mainstream version do not creep into the patch release accidentally.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: large;"&gt;#2.6 Make patch releases from branches only&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Since all the bug fixes for a given release are done on its corresponding branch, the patch releases are made from the branch. This ensures that there is no confusion on the feature set that is released as part of the patch release.. After the patch release is made, the branch has to be tagged using the release tagging practice (see Tag each release).&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: large;"&gt;#2.7 Merge branch with the trunk after release&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;After each release from a branch, the changes made to the branch should be merged (by &lt;b&gt;cvs update -j BRANCH&lt;/b&gt; command) with the trunk. This ensures that all the bug fixes made to the patch release are properly incorporated into future releases of the application.&lt;br /&gt;&lt;br /&gt;This merge could potentially be time consuming depending on the amount of changes made to the trunk and the branch being merged. In fact, it will probably result in a lot of conflicts in CVS resulting in manual merges. After the merge, the trunk code base must be tested to verify that the application is in proper working order. This must be kept in mind while preparing the project schedule.&lt;br /&gt;&lt;br /&gt;In the case of changes occurring on branches for a long period, these changes can be merged to the main branch on a regular basis even before the release is made. The frequency of merge is done based on certain logical points in the branch's evolution. To ensure that duplicate merging does not occur, the following practice can be adopted.&lt;br /&gt;&lt;br /&gt;In addition to the branch tag, a tag called &lt;b&gt;{branch_name}_MERGED&lt;/b&gt; should be created. This is initially at the same level as the last release tag for the branch. This tag is then "moved" after each intermediate merge by using the −F option. This eliminates duplicate merging issues during intermediate merges.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: x-large;"&gt;#3 Summary&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;it is not said that all of the above mentioned policies must be followed as they are there. There are always exceptions depending upon type of project, amount of work that is to be done. Hence policies need to be followed under most suitable way.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/298834846183725348-2417980130907318786?l=arzala.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://arzala.blogspot.com/feeds/2417980130907318786/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=298834846183725348&amp;postID=2417980130907318786' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/298834846183725348/posts/default/2417980130907318786'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/298834846183725348/posts/default/2417980130907318786'/><link rel='alternate' type='text/html' href='http://arzala.blogspot.com/2007/06/cvs-best-practices.html' title='CVS best practices'/><author><name>Anirudhsinh Zala</name><uri>http://www.blogger.com/profile/16341197487842993303</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://2.bp.blogspot.com/-jEmJYVgTwk0/Tu4SjN7xOgI/AAAAAAAAABI/17BzjhETHMM/s220/me.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-298834846183725348.post-2237727281681412738</id><published>2007-02-27T12:40:00.000+05:30</published><updated>2011-12-31T13:07:19.615+05:30</updated><category scheme='http://www.blogger.com/atom/ns#' term='culture'/><category scheme='http://www.blogger.com/atom/ns#' term='l10n'/><title type='text'>Localization</title><content type='html'>&lt;div dir="ltr" style="text-align: left;" trbidi="on"&gt;&lt;span style="font-size: x-large;"&gt;#1 L10N overview&lt;/span&gt; &lt;br /&gt;&lt;br /&gt;&lt;b&gt;Internationalization&lt;/b&gt; and &lt;b&gt;Localization&lt;/b&gt; are means of adapting products such as publications, hardware and software for non-native environments, especially other nations and cultures. &lt;br /&gt;&lt;br /&gt;When you implement i18n, l10n automatically knocks your door to get implemented. Reason is that if you allow users from different countries and cultures to use your software, they will expect that apart from language transformation, real data should also get transformed into localized ways. This expectation is reasonable because it might be possible that different countries are using different standards for displaying dates, currencies, units etc. For example US people won't understand &lt;b&gt;Kilometers&lt;/b&gt; because they use &lt;b&gt;Mile&lt;/b&gt; as unit, however for Indian people Kilometer is quite familiar unit. The more the cultures, the more the varieties one can see in communication, displaying information etc. &lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: large;"&gt;#1.1 Locale and formats &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Before implementing l10n we first need to have proper understanding of terms &lt;b&gt;locale&lt;/b&gt; and &lt;b&gt;format&lt;/b&gt;. Locale represents a whole culture that can contain information about how to display dates, how to show currencies, which measurements units are to be used for conversions etc. For example for Indian locale, it is like below: &lt;br /&gt;&lt;ul style="text-align: left;"&gt;&lt;li&gt;Date display:DD-MM-YYYY&amp;nbsp;&lt;/li&gt;&lt;li&gt;Currency: 1,11,111 &lt;/li&gt;&lt;li&gt;Unit to measure distance: Km &lt;/li&gt;&lt;/ul&gt;While for US, it can be like below: &lt;br /&gt;&lt;ul style="text-align: left;"&gt;&lt;li&gt;Date display: MM-DD-YYYY &lt;/li&gt;&lt;li&gt;Currency: 111,111 &lt;/li&gt;&lt;li&gt;Unit to measure distance: Mile &lt;/li&gt;&lt;/ul&gt;Hence locale should be seen in broader way as it represents set of various localized items. But sometimes apart from locale, users prefer more customization in locals, hence there comes the term format which means allowing 1 more level of customization. For example a US user might like to format date from &lt;b&gt;02-01-2007&lt;/b&gt; to &lt;b&gt;February 1st 2007&lt;/b&gt;. In short locale includes language, default format, glyph and other instruction set for particular locale while format is nothing but the different representation of same values. Hence overall a locale can have more than 1 formats. &lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: x-large;"&gt;#2 How to implement it? &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;While implementing l10n in softwares, software administrator or team members first need to determine that how many locales and formats should be used. Chosen locale and formats can be stored in file system or in database. Once it is decided, it can be implemented at 2 levels. &lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: large;"&gt;#2.1 Backend&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Each software normally has administrative area from where whole software is managed. This area should be used to select number of formats for respective locales for particular software. &lt;br /&gt;&lt;br /&gt;From selected formats, there should be chosen 1 default format for each l10n entity which will be used at client area. This default format is applicable to whole client area of software until it is overridden at user-level. &lt;br /&gt;&lt;br /&gt;For certain entities like number format and currency format only 1 format should be set and user-level option may not be allowed. It should also be kept in mind that formats of one locale should not be used in other locale. &lt;br /&gt;&lt;br /&gt;For softwares likes FS and Flog where client is registered from administrative area, user-level locales and formats could be selected directly. &lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: large;"&gt;#2.2 Frontend&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;At client area, if user is not given option to set his/her own locales &amp;amp; formats or if it is provided but user is not logged in then locale and formats set as default at administrative area should be used. &lt;br /&gt;&lt;br /&gt;#2.2.1 Setting locale &lt;br /&gt;&lt;br /&gt;While implementing l10n in PHP based softwares, developers need to set locales first. This locale can be decided upon selection of language. For example if &lt;b&gt;English&lt;/b&gt; language is selected by user then locate should be set as &lt;b&gt;en_US&lt;/b&gt;, for Finnish language locale should be set as &lt;b&gt;fi_FI&lt;/b&gt;. To set locale in PHP, you can use function &lt;b&gt;setlocale()&lt;/b&gt;. You can set locale for various categories like to display monetary items, or dates or messages etc. Please refer PHP manual for more details about how to use this function. &lt;br /&gt;&lt;br /&gt;There are various PHP functions which behaves depending upon locales. Some of them are strcoll(), strftime(), date() etc. &lt;br /&gt;&lt;br /&gt;#2.2.2 Displaying data in various formats based upon locales &lt;br /&gt;&lt;br /&gt;Once locale is set for particular language, locale related functions behaves in different ways. For example below code will display day in different language for different locales. You can see that code remains same but information displays in different way. &lt;br /&gt;&lt;br /&gt;// Displays “Wednesday” for English language. &lt;br /&gt;setlocale(LC_TIME,'C'); &lt;br /&gt;echo strftime('%A'); &lt;br /&gt;&lt;br /&gt;// Displays “keskiviikko” for Finnish language. &lt;br /&gt;setlocale(LC_TIME,'fi_FI'); &lt;br /&gt;echo strftime('%A'); &lt;br /&gt;&lt;br /&gt;// Displays “mercredi” for French language. &lt;br /&gt;setlocale(LC_TIME,'fr_FR'); &lt;br /&gt;echo strftime('%A'); &lt;br /&gt;&lt;br /&gt;// Displays “Mittwoch” for German language. &lt;br /&gt;setlocale(LC_TIME,'de_DE'); &lt;br /&gt;echo strftime('%A'); &lt;br /&gt;&lt;br /&gt;// Displays “बधवार” for Hindi language. &lt;br /&gt;setlocale(LC_TIME,'hi_IN'); &lt;br /&gt;echo strftime('%A');&lt;br /&gt;&lt;br /&gt;Similarly locales can be set for entities like currency, number format etc. To set locale for all entities, constant &lt;b&gt;LC_ALL&lt;/b&gt; should be used. &lt;br /&gt;&lt;br /&gt;At code level there might be problems during implementing different formats because for different locales default formats can be different. Hence above code doesn't actually serve our purpose. See example below. &lt;br /&gt;&lt;br /&gt;// Displays 'Friday December 22 1978' in English. &lt;br /&gt;setlocale(LC_ALL, 'en_US'); &lt;br /&gt;echo strftime('%A %B %d %Y', mktime(0, 0, 0, 12, 22, 1978))."\n"; &lt;br /&gt;&lt;br /&gt;// Displays 'perjantai 22 joulukuu 1978' in Finnish. &lt;br /&gt;setlocale(LC_ALL, 'fi_FI'); &lt;br /&gt;echo strftime('%A %d %B %Y', mktime(0, 0, 0, 12, 22, 1978))."\n"; &lt;br /&gt;&lt;br /&gt;// Displays 'vendredi 22 d�embre 1978' in French. &lt;br /&gt;setlocale(LC_ALL, 'fr_FR'); &lt;br /&gt;echo strftime('%A %d %B %Y', mktime(0, 0, 0, 12, 22, 1978))."\n"; &lt;br /&gt;&lt;br /&gt;// Displays 'Freitag 22 Dezember 1978' in German. &lt;br /&gt;setlocale(LC_ALL, 'de_DE'); &lt;br /&gt;echo strftime('%A %d %B %Y', mktime(0, 0, 0, 12, 22, 1978))."\n"; &lt;br /&gt;&lt;br /&gt;// Displays '22 दिसमबर शकरवार 1978' in Hindi. &lt;br /&gt;setlocale(LC_ALL, 'hi_IN'); &lt;br /&gt;echo strftime('%d %B %A %Y', mktime(0, 0, 0, 12, 22, 1978))."\n"; &lt;br /&gt;&lt;br /&gt;In this example there are different formats for different locales, hence to make implementation easy at code level, we should store conversion specifier into database/file and using it directly into function. For example for Finnish languages locale, conversion specifier &lt;b&gt;%A %d %B %Y&lt;/b&gt; would stored as string and should be used directly into function like above. Similarly this type of conversion specifiers can be used for all formats of all entities. &lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: x-large;"&gt;#3 Limitations of l10n &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Native support of l10n in script or database is limited to display information into different format and glyphs only. It doesn't actually convert values according to localization. For example if price of any item is stored in &lt;b&gt;$&lt;/b&gt; currency, then that price, when displays to users who has selected Finnish language (or locale), wont get displayed automatically into his/her own chosen currency (i.e. &lt;b&gt;€&lt;/b&gt;). This is because conversion rates between 2 units gets constantly changed. &lt;br /&gt;&lt;br /&gt;For such issues, l10n should be implemented in customized way in your software where unit conversion functions can be built and used according to chosen format. However information should be stored in database in only one format and should be formatted only while displaying it to users. &lt;br /&gt;&lt;br /&gt;However there is one one exception in displaying date and time, which can be displayed with different values if time zone related functions are used. Normally software logs date and time into it's own locale, but it could be possible that the user who is using that software located in different country where date/time is different than server time. Hence in such cases software should provide option to select timezone so that date/time can be displayed with localized values. Such option is essential for softwares that provides email services. &lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: x-large;"&gt;#4 Links &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://en.wikipedia.org/wiki/I18n"&gt;http://en.wikipedia.org/wiki/l10n&lt;/a&gt; &lt;br /&gt;http://www.useit.com/alertbox/9608.html &lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/298834846183725348-2237727281681412738?l=arzala.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://arzala.blogspot.com/feeds/2237727281681412738/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=298834846183725348&amp;postID=2237727281681412738' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/298834846183725348/posts/default/2237727281681412738'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/298834846183725348/posts/default/2237727281681412738'/><link rel='alternate' type='text/html' href='http://arzala.blogspot.com/2007/02/localization.html' title='Localization'/><author><name>Anirudhsinh Zala</name><uri>http://www.blogger.com/profile/16341197487842993303</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://2.bp.blogspot.com/-jEmJYVgTwk0/Tu4SjN7xOgI/AAAAAAAAABI/17BzjhETHMM/s220/me.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-298834846183725348.post-2131548581575804152</id><published>2007-02-23T17:16:00.000+05:30</published><updated>2011-12-31T12:38:16.641+05:30</updated><category scheme='http://www.blogger.com/atom/ns#' term='culture'/><category scheme='http://www.blogger.com/atom/ns#' term='i18n'/><title type='text'>Internationalization</title><content type='html'>&lt;div dir="ltr" style="text-align: left;" trbidi="on"&gt;&lt;span style="font-size: x-large;"&gt;#1 I18N overview &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Internationalization and localization are means of adapting products such as publications, hardware and software for non-native environments, especially other nations and cultures. &lt;br /&gt;&lt;br /&gt;I18n includes many non-english and non-european languages like Hindi, Gujarati etc. that require multi bytes to store characters. To support such languages, software should use utf-8 encoding scheme to input, process, store, search and output data in same language. &lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: x-large;"&gt;#2 How to implement it? &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Just few years ago i18n was headache for developers to implement because of limited support from database, scripting language, browsers, OS and other middle layers. But now a days with transparent support of utf-8 at each layer it has been easy to implement i18n. &lt;br /&gt;&lt;br /&gt;In this document I have mentioned steps about how to implement i18n for LAMP based softwares with MySQL 4.1 and higher and PHP 5.0 and higher. For lower versions than these certain steps may not work. &lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: large;"&gt;#2.1 Server side &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;This sections includes changes are to be made at server side.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: small;"&gt;#2.1.1 OS level &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;At OS level, the only requirement is that OS should support &lt;b&gt;utf-8&lt;/b&gt; encoding which modern OSes like FC1...6, CentOS etc. support very well. &lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: small;"&gt;#2.1.2 Database level &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;At database level, you should use &lt;b&gt;utf-8_*&lt;/b&gt; encoding as default for database communication and collation. For that you need to add following entries into &lt;b&gt;my.cnf&lt;/b&gt; (MySQL software's configuration file) file at section &lt;b&gt;[mysqld]&lt;/b&gt;. &lt;br /&gt;&lt;br /&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;# To support Asiatic languages use utf-8. &lt;/div&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&lt;/div&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;init-connect='SET NAMES utf8' &lt;/div&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&lt;/div&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;default-character-set=utf8 &lt;/div&gt;&lt;br /&gt;Sometimes customized configuration my.cnf has more sections like [client] etc. In that case add below entry in &lt;b&gt;[client]&lt;/b&gt; section also. &lt;br /&gt;&lt;br /&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;# To support Asiatic languages use utf-8. &lt;/div&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&lt;/div&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;default-character-set=utf8 &lt;/div&gt;&lt;br /&gt;After making above entries, restart MySQL service. Whenever you create new database, use connection collation as &lt;b&gt;utf8_*&lt;/b&gt; and use &lt;b&gt;utf-8&lt;/b&gt; as character set of the file. However if you have set above 2 values then these changes are not required, but still it is advised to check them as sometimes you are dumping databases from different versions of MySQL. &lt;br /&gt;&lt;br /&gt;To test what is set; run below SQL queries. &lt;br /&gt;&lt;br /&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;SHOW VARIABLES LIKE 'character_set%';&lt;/div&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;SHOW VARIABLES LIKE 'collation%';&lt;/div&gt;&lt;br /&gt;It will output all values containing utf-8 word in it. Sometimes it is not possible to add above type of entries in my.cnf specially on shared hosting server. In such case, execute below SQL query before execution of any query (in your PHP script).&lt;br /&gt;&lt;br /&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;SET NAMES 'utf8';&lt;/div&gt;&lt;br /&gt;It does same thing for which we added entries in my.cnf except that this is runtime and applicable in local scope only. However database and tables must be created in utf-8 format and using same as collation.&lt;br /&gt;&lt;br /&gt;#2.1.3 PHP script level&lt;br /&gt;&lt;br /&gt;This is the main area where important changes are to be made. PHP natively doesn't support handling of &lt;b&gt;i18n&lt;/b&gt; hence we have to use certain extensions to fulfill our requirements. These extensions are iconv and &lt;b&gt;mbstring&lt;/b&gt;. But from these 2, mbstring is popular and works very well. As mbstring extension is not part of standard PHP installation, we need to enable it manually.&lt;br /&gt;&lt;ul style="text-align: left;"&gt;&lt;li&gt;If you have configured your web server using utilities like YUM then it is very easy. Just run below command as root user and restart httpd service. &lt;/li&gt;&lt;/ul&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;[root@mypc ~]# yum install php-mbstring &lt;/div&gt;&lt;br /&gt;&lt;ul style="text-align: left;"&gt;&lt;li&gt;For manual installation, you need to set following option to enable all the supported languages. &lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;–enable-mbstring=all &lt;/div&gt;&lt;br /&gt;Once this extension is enabled in PHP, we need to set certain directives to make it working. These directives can be set in &lt;b&gt;php.ini&lt;/b&gt; for global usage, &lt;b&gt;httpd.conf&lt;/b&gt; for host wise usage and in PHP script itself for page or project wise usage. But I recommend to use it in PHP script itself so that it's usage remains limited to specific application or project. See below section for implementation. &lt;br /&gt;&lt;br /&gt;Apart from these changes, all your PHP and other required scripts should be saved in utf-8 character set encoding because we store static i18n data in flat files (like fl_fi.inc.php). Hence editors needs to be configured in that way. Most popular editors provide setting of character set encoding; hence select utf-8 as standard encoding type. &lt;br /&gt;&lt;br /&gt;#2.1.4 Application level &lt;br /&gt;&lt;br /&gt;At application level, you need set certain directives using function &lt;b&gt;ini_get()&lt;/b&gt; to enable &lt;b&gt;mbstring&lt;/b&gt; extension. These directives are: &lt;br /&gt;&lt;br /&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;// Settings for i18n support. &lt;/div&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&lt;/div&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;ini_set('mbstring.internal_encoding','utf-8'); &lt;/div&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&lt;/div&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;ini_set('mbstring.func_overload',7); &lt;/div&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&lt;/div&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;ini_set('mbstring.encoding_translation',1); &lt;/div&gt;&lt;br /&gt;If your application is using output buffering (i.e. output_buffering=On) then output handler should be set as &lt;b&gt;mb_output_handler&lt;/b&gt; like below: &lt;br /&gt;&lt;br /&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;ini_set('output_handler','mb_output_handler'); &lt;/div&gt;&lt;br /&gt;Once these directives are set, all string related, regular expression related and mail system related functions will work transparently for all kind of languages. For more information about above directives, refer PHP manual. &lt;br /&gt;&lt;br /&gt;While sending emails, &lt;b&gt;utf-8&lt;/b&gt; should be set as character set encoding in headers. Similarly while outputting HTML/XHTML to browser you need to explicitly set character set encoding into meta tags like below:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;lt;meta http-equiv="Content-Type" content="text/html; charset=utf-8" /&amp;gt;&lt;/span&gt; &lt;br /&gt;&lt;br /&gt;Moreover sometimes if your application outputs contents to browser directly from running script even then you need to pass certain header like below: &lt;br /&gt;&lt;br /&gt;In short wherever and whenever character set encoding is required, pass utf-8 as encoding scheme. &lt;br /&gt;&lt;br /&gt;If you are using Ajax mechanism in your website then you also require to encode your Ajax query string before submitting to server for execution. This is specially required while running application in MSIE browsers. Firefox and other Gecko based browsers handles Ajax queries that contains i18n data correctly. For more info read thread http://news.php.net/php.i18n/1059. &lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: large;"&gt;#2.2 Client side &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;At client side minimal support is required.&lt;br /&gt;&lt;br /&gt;#2.2.1 OS level &lt;br /&gt;&lt;br /&gt;Client's OS should be able to understand utf-8 encoding, which is quite possible in latest versions of OSes. Apart from that, OS should have support to type characters in native language which is called as &lt;i&gt;Keyboard layout and Regional settings&lt;/i&gt;. &lt;br /&gt;&lt;br /&gt;#2.2.2 Browser level &lt;br /&gt;&lt;br /&gt;The only requirement at browser level is that browser should be able to interpret &lt;b&gt;utf-8&lt;/b&gt; character set encoding which is supported by almost all modern browsers. Contents sent from server (refer section 2.1.4) tell browser that which encoding scheme is to be used. &lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: x-large;"&gt;#3 How to implement in existing projects?&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;To implement i18n in existing projects requires above implementation plus conversion of existing data.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: large;"&gt;#3.1 Converting database &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;#3.1.1 Using commands &lt;br /&gt;&lt;br /&gt;To convert existing database encoded into utf-8, take dump of data by running below command. &lt;br /&gt;&lt;br /&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;mysqldump -hHOST -uUSER -p --opt --default-character-set=CHARSET --skip-set-charset DB_NAME|sed -e 's/SOURCE_CHARSET/DEST_CHARSET/g' &amp;gt; DB_NAME.sql &lt;/div&gt;&lt;br /&gt;It will create SQL file containing all data of selected database which you can use to re-create new database. Now convert existing file into utf-8 format by running below command. &lt;br /&gt;&lt;br /&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;iconv -f SOURCE_CHARSET -t UTF-8 DB_NAME.sql &amp;gt; UTF_DB_NAME.sql &lt;/div&gt;&lt;br /&gt;To dump above data into newly created database, run below command: &lt;br /&gt;&lt;br /&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;mysql -hHOST -uUSER -p --default-character-set=DEST_CHARSET DB_NAME &amp;lt; &lt;/div&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&lt;/div&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;UTF_DB_NAME.sql &lt;/div&gt;&lt;br /&gt;#3.1.2 Converting database directly &lt;br /&gt;&lt;br /&gt;Sometimes it is not possible do this using command line interface (due to shared hosting environment), then it will require to execute certain SQL queries to change character set of existing database without copying or moving it anywhere. To do so; run below SQL queries wherever it is applicable. Please note the order of execution of queries. &lt;br /&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;# First change all i18n fields of all tables into BLOB.&lt;/div&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;ALTER TABLE TABLE MODIFY FIELD BLOB; &lt;/div&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;# Now change character set of database as UTF-8. &lt;/div&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&lt;/div&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;ALTER DATABASE DATABASE charset=utf8; &lt;/div&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;# Then change character set of each table.&lt;/div&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;ALTER TABLE TABLE charset=utf8; &lt;/div&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;# Now change all i18n fields of all tables into UTF-8 character set.&lt;/div&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;ALTER TABLE TABLE MODIFY FIELD ORIG_FIELD_TYPE CHARACTER SET utf8; &lt;/div&gt;&lt;br /&gt;Ideally above queries should be run by making shell or PHP script so that it can be used later or for other projects. &lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: large;"&gt;#3.2 Converting file system &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;You will also require to change encoding of existing PHP scripts and other files if they contain data that requires utf-8 encoding. Normally you would require to change format of files containing non-english text only. But it is recommended to use same encoding for all type of files throughout your software. To change encoding of file iconv utility can be used. One example is provided below. &lt;br /&gt;&lt;br /&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;iconv -f SOURCE_CHARSET -t UTF-8 FILENAME &amp;gt; FILENAME &lt;/div&gt;&lt;br /&gt;You can also use mb_string_* functions of PHP to change character set encoding of your files. However this is PHP based function so you need to design a script to convert all existing files. &lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: large;"&gt;#3.3 Translating your project &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;When you design multilingual projects, it becomes mandatory to dynamically handle static text of your application. Your application can have several options for that depending upon tools used to build it. Symfony based projects can have XLIFF as standard mechanism to translate static data. But overall if we want such mechanism in every PHP application then there are 2 ways to do so. &lt;br /&gt;&lt;ul style="text-align: left;"&gt;&lt;li&gt;Declaring PHP variables where static text gets displayed, and then putting those variables in language files, according to each language used in application, and then including it in scripts where those translations are required. This is standard way but there are some disadvantages of it. Since file is PHP based, third party translators will find difficulties in adding/updating translations as they might be from non-technical area. Hence there exists professional mechanism to overcome this problem.&lt;/li&gt;&lt;li&gt;For large applications, where translators are from various cultures and backgrounds, preferred approach is it to use PHP extension called &lt;b&gt;Gettext&lt;/b&gt; (in PHP it is bundled as &lt;b&gt;php-gettext&lt;/b&gt;). &lt;/li&gt;&lt;/ul&gt;To check whether it is installed or not, run command &lt;b&gt;php -m&lt;/b&gt; from command line. If output contains text like gettext then it is installed. Otherwise using various options it can be installed. The most popular way is using Yum utility. Just type below command as root user and that's it. &lt;br /&gt;&lt;br /&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;[root@mypc ~]# yum install php-gettext &lt;/div&gt;&lt;br /&gt;&lt;b&gt;php-gettext&lt;/b&gt; works in this way. 1 language file is prepared using specials editors like KBabel, poEdit where all translations are kept in pairs of 2 special variable &lt;b&gt;msgid&lt;/b&gt; and &lt;b&gt;msgstr&lt;/b&gt;. &lt;b&gt;msgid&lt;/b&gt; variable denotes variable name to be used in PHP script while &lt;b&gt;msgstr&lt;/b&gt; denotes language translation associated with that &lt;b&gt;msgid&lt;/b&gt; variable. Using pair of &lt;b&gt;msgid&lt;/b&gt; and &lt;b&gt;msgstr&lt;/b&gt;, we can build as much translations as required for any language. There will be separate files for each language. This version of file has &lt;b&gt;.po&lt;/b&gt; extension but it is only for editing translations. Actual file which is used by PHP to apply these translations is not this. For that .po file needs to get compiled into &lt;b&gt;.mo&lt;/b&gt; binary file. For that following command can be used. &lt;br /&gt;&lt;br /&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;[user@mypc ~]# msgfmt -cv -o FILE.mo FILE.po &lt;/div&gt;&lt;br /&gt;Normally both files are kept at same location for easy maintenance. Since we have generated files for language translations, I will describe how to use them in your application. In your global includable script following code needs to get added to bind your created language files and your application. &lt;br /&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;// Set environment variable. &lt;/div&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&lt;/div&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;putenv('LC_ALL=&lt;b&gt;en_US&lt;/b&gt;'); &lt;/div&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;// Set selected locale (language). &lt;/div&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&lt;/div&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;setlocale(LC_ALL, &lt;b&gt;en_US&lt;/b&gt;); &lt;/div&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;// Specify location of translation tables. &lt;/div&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&lt;/div&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;bindtextdomain('frontend', '/web/projects/myproject/translations/'); &lt;/div&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&lt;/div&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;bindtextdomain('backend', '/web/projects/myproject/translations/'); &lt;/div&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;// Choose domain for application. &lt;/div&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&lt;/div&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;textdomain('frontend'); &lt;/div&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;// Bind specific character set to be used with selected domain. &lt;/div&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&lt;/div&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;bind_textdomain_codeset('frontend','UTF-8'); &lt;/div&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&lt;/div&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;bind_textdomain_codeset('backend','UTF-8'); &lt;/div&gt;&lt;br /&gt;In above code snippet, items marked in &lt;b&gt;bold&lt;/b&gt; are to be replaced by your application specific needs. Here &lt;b&gt;en_US&lt;/b&gt; is a locale which can be changed as required. &lt;br /&gt;&lt;br /&gt;Since gettext accesses translation files in special way, they needs to get stored according to rules defined by gettext. With reference to above code-snippet, if root folder of language translation files is like &lt;b&gt;/web/projects/myproject/translations/&lt;/b&gt; and application areas are admin and client then language related files should be stored in following way. &lt;br /&gt;&lt;br /&gt;/web/projects/myproject/translations/en_US/LC_MESSAGES/backend.mo, [admin.po] &lt;br /&gt;/web/projects/myproject/translations/en_US/LC_MESSAGES/frontend.mo, [client.po] &lt;br /&gt;&lt;br /&gt;/web/projects/myproject/translations/en_GB/LC_MESSAGES/backend.mo, [admin.po] &lt;br /&gt;/web/projects/myproject/translations/en_GB/LC_MESSAGES/frontend.mo, [client.po] &lt;br /&gt;&lt;br /&gt;/web/projects/myproject/translations/fi_FI/LC_MESSAGES/backend.mo, [admin.po] &lt;br /&gt;/web/projects/myproject/translations/fi_FI/LC_MESSAGES/frontend.mo, [client.po] &lt;br /&gt;&lt;br /&gt;Hence by switching values in function &lt;b&gt;textdomain()&lt;/b&gt;, desired translation files can be included in each application. Now how to use these translation in PHP script?. For that each &lt;b&gt;msgid&lt;/b&gt; variable should be written like &lt;b&gt;_('myVar')&lt;/b&gt; in PHP script to include corresponding translation from selected file. &lt;br /&gt;&lt;br /&gt;That's it, whenever translation files are modified, they need to get recompiled using command &lt;b&gt;msgfmt&lt;/b&gt; as described earlier to avail latest translations. Since compiled binary &lt;b&gt;.mo&lt;/b&gt; files are cached by PHP, modifications might not get reflected immediately. In such case web service should be gracefully restarted. &lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: x-large;"&gt;#4 Summary &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Advantages of implementing i18n using utf-8 character set encoding is that users can now input data in their localized language and those contents would saved and displayed back in browser in same language. Not only these, but database can make searching records in native language also. For example if you are required to retrieve records of all users whose last name is “ઝાલા”, then writing SQL like below will work successfully. &lt;br /&gt;&lt;br /&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;SELECT * FROM user WHERE last_name='ઝાલા'; &lt;/div&gt;&lt;br /&gt;At PHP script level you can compare, sort, split Unicode strings in same way like you are doing for normal strings. Next version of PHP (i.e &lt;b&gt;PHP 6&lt;/b&gt;) is going to support Unicode by default hence there will not require extensions or setting to enable Unicode string. &lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: x-large;"&gt;#5 Links &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.nyphp.org/content/presentations/smallworld/April2006-nyphp-Presentation.ppt"&gt;http://www.nyphp.org/content/presentations/smallworld/April2006-nyphp-Presentation.ppt&lt;/a&gt; &lt;br /&gt;&lt;a href="http://en.wikipedia.org/wiki/I18n"&gt;http://en.wikipedia.org/wiki/I18n&lt;/a&gt; &lt;br /&gt;&lt;a href="http://www.useit.com/alertbox/9608.html"&gt;http://www.useit.com/alertbox/9608.html&lt;/a&gt; &lt;br /&gt;&lt;a href="http://dev.mysql.com/doc/refman/5.0/en/charset-connection.html"&gt;http://dev.mysql.com/doc/refman/5.0/en/charset-connection.html&lt;/a&gt; &lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/298834846183725348-2131548581575804152?l=arzala.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://arzala.blogspot.com/feeds/2131548581575804152/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=298834846183725348&amp;postID=2131548581575804152' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/298834846183725348/posts/default/2131548581575804152'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/298834846183725348/posts/default/2131548581575804152'/><link rel='alternate' type='text/html' href='http://arzala.blogspot.com/2007/02/internationalization.html' title='Internationalization'/><author><name>Anirudhsinh Zala</name><uri>http://www.blogger.com/profile/16341197487842993303</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://2.bp.blogspot.com/-jEmJYVgTwk0/Tu4SjN7xOgI/AAAAAAAAABI/17BzjhETHMM/s220/me.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-298834846183725348.post-8002155162918041099</id><published>2006-11-29T17:14:00.000+05:30</published><updated>2012-01-10T20:34:59.227+05:30</updated><category scheme='http://www.blogger.com/atom/ns#' term='rest'/><category scheme='http://www.blogger.com/atom/ns#' term='php'/><title type='text'>REST</title><content type='html'>&lt;div dir="ltr" style="text-align: left;" trbidi="on"&gt;&lt;span style="font-size: x-large;"&gt;#1 REST overview&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Representational State Transfer or REST is a style of software architecture for distributed hypermedia systems such as the World Wide Web. The term was originated by Roy Fielding, one of the principal authors of the HTTP protocol specification.&lt;br /&gt;&lt;br /&gt;Roy Fielding describes REST as:&lt;br /&gt;&lt;br /&gt;&lt;i&gt;Representational State Transfer is intended to evoke an image of how a well-designed Web application behaves: a network of web pages (a virtual state-machine), where the user progresses through an application by selecting links (state transitions), resulting in the next page (representing the next state of the application) being transferred to the user and rendered for their use.&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;The term is also often used in a loose sense to describe any simple interface that transmits domain-specific data over HTTP without an additional messaging layer such as SOAP or session tracking via HTTP cookies. Systems that follow Fielding's REST principles are often referred to as &lt;b&gt;RESTful&lt;/b&gt;.&lt;br /&gt;&lt;br /&gt;The Web is the key example of existing RESTful design. Much of it conforms or can be made to conform to REST principles. The Web consists of various protocols like HTTP, FTP, HTTPS, SMTP etc, content types including the HTML, XML and other Internet technologies such as the Domain Name Service (DNS).&lt;br /&gt;&lt;br /&gt;HTML can include Javascript and Applets that has implicit support for hyper-links. HTTP has a uniform interface for accessing resources which consists of URIs, Request methods (GET, POST, PUT, DELETE), Status codes (401, 404, 500), Headers, and Content distinguished by MIME type (application/plain-text, image/gif, image/png etc.).&lt;br /&gt;&lt;br /&gt;HTTP separates the notions of a web server and a web browser. This allows the implementation of each to vary from the other based on the client/server principle. When used RESTfully, HTTP is stateless. Each message contains all the information necessary to understand the request when combined with state at the resource. As a result, neither the client nor the server needs to remember any communication-state between messages. Any state retained by the server must be modeled as a resource.&lt;br /&gt;&lt;br /&gt;Before further reading this document, I advise to read this article &lt;a href="http://www.xfront.com/REST.html"&gt;http://www.xfront.com/REST.html&lt;/a&gt; in order to understand REST in proper way.&lt;br /&gt;&lt;br /&gt;Let's understand REST in the by taking example of "Camera purchasing store"&amp;nbsp; project. In RESTful application, only single base URL is given to client and after that each representation of resources gives more URLs to be visited and so on. To get information of cameras available on camera purchasing website, a base URL can be given like &lt;b&gt;http://mycamera.com/camera&lt;/b&gt;. This can be called as a main resource of available cameras. Calling this resource will result into primary information of available cameras on the website. To obtain more information about each camera link to more resources are provided. They are: &lt;b&gt;http://mycamera.com/camera/view/camera_id/1&lt;/b&gt; and &lt;b&gt;http://mycamera.com.com/camera/view/camera_id/2&lt;/b&gt;. Both these resources provides details of respective cameras. These details may also contain links to more resources like 1st resource contains link to another resource &lt;a href="http://en.wikipedia.org/wiki/Nikon_D70"&gt;http://en.wikipedia.org/wiki/Nikon_D70&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Each of the above request URI is &lt;b&gt;stateless&lt;/b&gt; and self-explanatory which means server at any point doesn't require to ask client to provide more information about the request. Moreover each resultant representation provides required information of requested resource as well hyper-link to additional resource attached to main resource.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: large;"&gt;#2 REST characteristics and principles&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: large;"&gt;#2.1 REST characteristics&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Characteristics of the RESTful system would be:&lt;br /&gt;&lt;ul style="text-align: left;"&gt;&lt;li&gt;Client-Server: a pull-based interaction style: consuming components pull representations.&lt;/li&gt;&lt;li&gt;Stateless: each request from client to server must contain all the information necessary to understand the request, and cannot take advantage of any stored context on the server.&lt;/li&gt;&lt;li&gt;Cache: to improve network efficiency responses must be capable of being labelled as cacheable or non-cacheable.&lt;/li&gt;&lt;li&gt;Uniform interface: all resources are accessed with a generic interface (e.g., GET, POST, PUT, DELETE).&lt;/li&gt;&lt;li&gt;Named resources - the system is comprised of resources which are named using a URL.&lt;/li&gt;&lt;li&gt;Interconnected resource representations - the representations of the resources are interconnected using URLs, thereby enabling a client to progress from one state to another.&lt;/li&gt;&lt;li&gt;Layered components - intermediaries, such as proxy servers, cache servers, gateways, etc, can be inserted between clients and resources to support performance, security, etc.&lt;/li&gt;&lt;/ul&gt;&lt;span style="font-size: x-large;"&gt;#2.2 REST principles&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Key principles of RESTful system are:&lt;br /&gt;&lt;ul style="text-align: left;"&gt;&lt;li&gt;The key to creating Web Services in a REST network (i.e., the Web) is to identify all of the conceptual entities that you wish to expose as services.&lt;/li&gt;&lt;li&gt;Create a URL to each resource. The resources should be nouns, not verbs. For example, do not use this:&lt;/li&gt;&lt;/ul&gt;&lt;b&gt;http://mycamera.com/camera/viewCamera.php?camera_id=1&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;Note the verb, viewCamera. Instead, use a noun:&lt;br /&gt;&lt;br /&gt;&lt;b&gt;http://mycamera.com/camera/view/camera_id/1&lt;/b&gt;&lt;br /&gt;&lt;ul style="text-align: left;"&gt;&lt;li&gt;Categorize your resources according to whether clients can just receive a representation of the resource, or whether clients can modify (add to) the resource. For the former, make those resources accessible using an HTTP GET. For the later, make those resources accessible using HTTP POST, PUT, and/or DELETE.&lt;/li&gt;&lt;li&gt;All resources accessible via HTTP GET should be side-effect free. That is, the resource should just return a representation of the resource. Invoking the resource should not result in modifying the resource.&lt;/li&gt;&lt;li&gt;No man/woman is an island. Likewise, no representation should be an island. In other words, put hyper-links within resource representations to enable clients to drill down for more information, and/or to obtain related information.&lt;/li&gt;&lt;li&gt;Design to reveal data gradually. Don't reveal everything in a single response document. Provide hyper-links to obtain more details.&lt;/li&gt;&lt;li&gt;Specify the format of response data using a schema (DTD, W3C Schema, RelaxNG, or Schematron). For those services that require a POST or PUT to it, also provide a schema to specify the format of the response.&lt;/li&gt;&lt;li&gt;Describe how your services are to be invoked using either a WSDL document, or simply an HTML document.&lt;/li&gt;&lt;/ul&gt;&lt;span style="font-size: x-large;"&gt;#2.3 How to achieve them?&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;To achieve above principles while developing RESTful application, developers will require to start thinking web applications in context of &lt;b&gt;resource and it's representation&lt;/b&gt;.&lt;br /&gt;&lt;br /&gt;It is not difficult to achieve some of the REST principles, but it is difficult to achieve all of them. For example we hardly use PUT and DELETE methods of HTTP. Below are guidelines about how to achieve them.&lt;br /&gt;&lt;ul style="text-align: left;"&gt;&lt;li&gt;Developers should be able to identify all of the conceptual entities that is to be provided as service.&lt;/li&gt;&lt;li&gt;These entities or resources must have a URI that can represent them.&lt;/li&gt;&lt;li&gt;The format of URIs should be easy to understand by users. For example prefer noun over verbs i.e use &lt;b&gt;http://mycamera.com/camera/view/camera_id/1&lt;/b&gt; instead of &lt;b&gt;http://mycamera.com/camera/viewCamera.php?camera_id=1&lt;/b&gt;.&lt;/li&gt;&lt;li&gt;Categorize all available resources that are to be exposed so that users can easily find them and visit them one by one.&lt;/li&gt;&lt;li&gt;Coding should be done in such a way that all resources to be accessed by GET method should remain side-effect free i.e do not modify, delete, alter resources using parameters in GET method like &lt;b&gt;http://mycamera.com/viewUser.php?id_user=1&amp;amp;delete=1&lt;/b&gt;.&lt;/li&gt;&lt;li&gt;In RESTful application, there is not any end-point i.e. Representation of 1 resource leads to access of another resource as shown in camera purchasing example (where list of camera get displayed first, then hyper-link to details of each camera can be accessed from there). However resources need not to be delivered from only 1 domain i.e they can be delivered from different domains also. Even in case of error/s occurring on server while accessing certain resources, server should return status code with proper information that what to do next or what steps to be followed by users so that error/s would not occur again. &lt;/li&gt;&lt;li&gt;While developing application, data should not get revealed altogether. Which means first generic list of resources should get displayed. That list should contain link to details of each individual resources and so on. The purpose is that daily users might not be interested in seeing details of every resource each time. &lt;/li&gt;&lt;li&gt;For example in camera purchasing website, URL &lt;b&gt;http://mycamera.com/camera&lt;/b&gt; just displays list of cameras. From there, link to details of each individual camera (&lt;b&gt;http://mycamera.com/camera/view/camera_id/1&lt;/b&gt;) or purchase of camera (&lt;b&gt;http://mycamera.com/camera/purchase/camera_id/1&lt;/b&gt;) can be requested.&lt;/li&gt;&lt;li&gt;Sometimes different format of data is requested by client; in such case client application should pass desired format related instructions in request directly and server should be able to understand and deliver it according to specifications. For example if details of camera is needed in XML format then query string could be like &lt;b&gt;http://mycamera.com/camera/view/camera_id/1/xml&lt;/b&gt;. &lt;/li&gt;&lt;/ul&gt;&lt;span style="font-size: x-large;"&gt;#3 REST and non-REST&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Simplest definition between REST and non-REST system is that &lt;b&gt;a system that is not following REST principles is called a non-REST system&lt;/b&gt;. That is there is not any specific guidelines or rules to differentiate REST vs. non-REST.&lt;br /&gt;&lt;br /&gt;Most of web application are &lt;b&gt;non-REST&lt;/b&gt; because it is not possible to create 100% RESTful application due to it's constraints. Often web application needs to use HTTP cookies and Session to keep track of client. Using such components violate REST principle/s (not being stateless). To make application 100% RESTful such information can not be passed in URI due to security reasons.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: x-large;"&gt;#4 REST and SOAP&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;REST can not be directly compared with SOAP as REST is an architectural style while SOAP is a message layer. However RESTful service can be compared with SOAP.&lt;br /&gt;&lt;br /&gt;The key difference between REST and SOAP is message style. SOAP is strictly bound to XML while REST doesn't have such constraints hence can use HTML, XML or any other MIME types. Other differences between REST and SOAP are:&lt;br /&gt;&lt;br /&gt;REST can use proxy servers in serving contents as resource can easily be identified from URL. Proxies are useful in defining policies of serving resources. Which means if certain resources are not be served, it can be directly denied from there without sending request to actual web server.&lt;br /&gt;&lt;br /&gt;On the other hand when resource is requested through SOAP, proxy cannot determine whether resource is to be allowed or not because information of resource is hidden in message envelope. Furthermore the URL is not to the target resource, but rather to a SOAP server which means proxy server will require to look inside each SOAP message to determine what is being asked. To do so proxy server would require to understand semantics of message. Which is difficult task as each SOAP message can have different semantics. However there are other solutions like using RDF/DAML format to allow proxy server to dynamically discover the resource or method to be discovered.&lt;br /&gt;&lt;br /&gt;Similar like proxy servers, there are other web intermediaries like gateways, caches etc. which can not be taught to understand semantics of every SOAP message.&lt;br /&gt;On the contrary REST request is self-explanatory hence these web intermediaries can work effectively in serving resources.&lt;br /&gt;&lt;br /&gt;Each client application can be considered as a state machine which means each resource representation that it receives causes it to transition to the next state.&lt;br /&gt;In REST based application each representation contains hyper-links; following them puts client into next state. That is there is not endpoint for any state in REST based application.&lt;br /&gt;&lt;br /&gt;While in SOAP based implementation each SOAP message is just data i.e no hyper-links which means which resources is to be accessed next must be made out of the band. Following 2 figures gives more details about this difference.&lt;br /&gt;&lt;br /&gt;&lt;div style="text-align: center;"&gt;&lt;u&gt;&lt;i&gt;State Transitions in a REST-based Network&lt;/i&gt;&lt;/u&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/-Yh940c3EjzQ/Tv8BlN6j5VI/AAAAAAAAACw/GpPgwzC0m8U/s1600/rest1.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="378" src="http://1.bp.blogspot.com/-Yh940c3EjzQ/Tv8BlN6j5VI/AAAAAAAAACw/GpPgwzC0m8U/s640/rest1.jpg" width="640" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div style="text-align: center;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: center;"&gt;&lt;i&gt;&lt;u&gt;State Transitions in a SOAP-based Network&lt;/u&gt;&lt;/i&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/-trXWHAU3iIE/Tv8BqqevRVI/AAAAAAAAAC8/BaXRvgJZvsA/s1600/rest2.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="382" src="http://2.bp.blogspot.com/-trXWHAU3iIE/Tv8BqqevRVI/AAAAAAAAAC8/BaXRvgJZvsA/s640/rest2.jpg" width="640" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div style="text-align: center;"&gt;&lt;br /&gt;&lt;/div&gt;In REST based implementation, caching can play important role in saving bandwidth and increasing response time because each resources has it's own location hence cache servers can easily cache them (if defined in headers) and when new request arrives resource can be served directly from cache.&lt;br /&gt;&lt;br /&gt;When resources is requested in SOAP system, message is always sent using POST method even if purpose is to get data. Moreover with SOAP server URI is always same and not the target resource hence a cache server would not know from the URI what resource is being requested. That is with SOAP message, the cache server cannot determine if data is being requested, nor what resource is being requested. Thus no caching possible with SOAP.&lt;br /&gt;&lt;br /&gt;In the context of semantic web, according to vision of Tim Berners-Lee, every resource can be given a URI and in fact any resource of significance should be given a URI. The REST architectural style is consistent with this vision due to having unique location for each resource.&lt;br /&gt;&lt;br /&gt;While with SOAP, since all requests are submitted at only one SOAP server, it breaks above vision of semantic web.&lt;br /&gt;&lt;br /&gt;A key feature of REST (and the Web) is that every resource have a generic interface. Namely, access to every resource is accomplished using HTTP &lt;b&gt;GET&lt;/b&gt;, &lt;b&gt;POST&lt;/b&gt;, &lt;b&gt;PUT&lt;/b&gt;, and &lt;b&gt;DELETE&lt;/b&gt;.&lt;br /&gt;&lt;br /&gt;With SOAP there is no defined set of methods. Each SOAP application is free to define its own set of methods.&lt;br /&gt;&lt;br /&gt;The key to interoperability is standardization. The reason why independent resources on the Web are able to interoperate today is because the Web has standardized on:&lt;br /&gt;&lt;ol style="text-align: left;"&gt;&lt;li&gt;Addressing and naming resources -&amp;gt; URI &lt;/li&gt;&lt;li&gt;Generic resource interface -&amp;gt; HTTP GET, POST, PUT, DELETE&lt;/li&gt;&lt;li&gt;Resource representations -&amp;gt; HTML, XML, GIF, JPEG, etc&lt;/li&gt;&lt;li&gt;Media types -&amp;gt; MIME types (text/html, text/plain, etc)&lt;/li&gt;&lt;/ol&gt;While SOAP much more depends upon customization. Because each SOAP message provides its own unique method of naming, a resource and each SOAP application defines its own interface.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: x-large;"&gt;#5 REST and Symfony&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Since REST is an architectural style and not a standard or a feature, it doesn't depend upon any programming language or framework. However a well designed framework can help a lot in developing RESTful applications.&lt;br /&gt;&lt;br /&gt;Symfony framework assists in generating Smart URLs and usage of “/” in URI to represent parent-child relationship through it's routing mechanism (together with Apache web server's &lt;b&gt;mod_rewrite&lt;/b&gt; module). Which are important characteristics of a RESTful application.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: x-large;"&gt;#6 Examples of REST implementation&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Our above example of "Camera purchasing store" is a RESTful web application. Hence we can see some examples of REST principles using HTTP &lt;b&gt;GET&lt;/b&gt; and &lt;b&gt;POST&lt;/b&gt; methods.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: large;"&gt;#6.1 Using GET method&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;For example if users want to retrieve information of available cameras (i.e resources in REST way) from the website, then URL &lt;b&gt;http://mycamera.com/camera&lt;/b&gt; provides them list of them and links to see further details of each camera. You can see that it has been implemented using &lt;b&gt;GET&lt;/b&gt; method.&lt;br /&gt;&lt;br /&gt;This representation contains URL of each camera resource like &lt;b&gt;http://mycamera.com/camera/view/camera_id/1&lt;/b&gt; and &lt;b&gt;http://mycamera.com/camera/view/camera_id/2&lt;/b&gt;. Which means data is linked to more data. By visiting above resources user might get links to more camera related resources.&lt;br /&gt;&lt;br /&gt;Main resource also provides links to get information about purchase of each camera like &lt;b&gt;http://mycamera.com/camera/purchase/camera_id/1&lt;/b&gt; and &lt;b&gt;http://mycamera.com/camera/&lt;/b&gt;&lt;b&gt;purchase&lt;/b&gt;&lt;b&gt;/camera_id/2&lt;/b&gt; that is another resources are there. When any of these resources, server returns purchase made for each camera as well as link to other resources like viewing details of each person (&lt;b&gt;http://mycamera.com/user/view/user_id/19&lt;/b&gt;) who has purchased particular camera.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: large;"&gt;#6.2 Using POST method&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;HTTP &lt;b&gt;POST&lt;/b&gt; is an another popular HTTP method to manage resources for any application. As GET is used to retrieve resources from server, POST is used to add/alter/remove resources. Normally POST is used with web forms where user input is required. Hence request submitted through POST method should be handled properly at server side.&lt;br /&gt;&lt;br /&gt;RESTful action of POST method for our website is "to purchase cameras”. Consider a base URL &lt;b&gt;http://mycamera.com/camera&lt;/b&gt; that provides list of cameras. From this list; link to purchase particular camera can be requested. This link &lt;b&gt;http://mycamera.com/camera/purchase/camera_id/1&lt;/b&gt; is a resource to purchase 1st camera. It will display a form to select desired from and to dates to purchase selected camera. Upon selection and submission of data, camera will get purchased (after making payments etc.). Upon successful submission another resource &lt;b&gt;http://mycamera.com/user&lt;/b&gt; is returned which displays confirmation of order made by this user. From this resource order history can be view and deleted if required. Cancellation of order/s (i.e resource) will require another HTTP POST operation.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: large;"&gt;#6.3 PUT and DELETE methods&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;DELETE&lt;/b&gt; and &lt;b&gt;PUT&lt;/b&gt; methods; unlike GET and POST; are not supported by browsers. Hence we have to use POST method to update (PUT) and remove (DELETE) resources in desired way. To do so we may provide PUT and DELETE related information via hidden fields of forms.&lt;br /&gt;&lt;br /&gt;Resource &lt;b&gt;http://mycamera.com/user&lt;/b&gt; is an example of deleting order which is equivalent to DELETE method while resource &lt;b&gt;http://mycamera.com/user/edit &lt;/b&gt;is an example of updating user information which is equivalent to PUT method.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: x-large;"&gt;#7 How to create REST based web services&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Web services have been designed to share data across many platforms and hardware configurations. For example a web services created on PHP platform can be used by .NET based platform as well as messaging format between client and server is common i.e XML or other HTTP based ones.&lt;br /&gt;&lt;br /&gt;Currently there are 3 web services which are popular on the web. They are XML-RPC, SOAP and REST. First 2 services are strictly using XML messaging format while 3rd can use standard HTML, XML, GIF or JPEG etc. In this document important guidelines have been provided to create REST based web-services.&lt;br /&gt;&lt;br /&gt;Implementing REST web service correctly requires a resource-oriented view of the world instead of the object-oriented views many developers are familiar with.&lt;br /&gt;&lt;br /&gt;In REST based web service &lt;b&gt;resource&lt;/b&gt; is the key concept. Hence whole REST web service is designed around managing resources. Since resource requires some mechanism to get identified by web, they are represented by &lt;b&gt;URI&lt;/b&gt;.&lt;br /&gt;&lt;br /&gt;The creator of a URI decides the encoding of the URI, and users should not derive metadata from the URI itself. URI opacity only applies to the path of a URI. The query string and fragment have special meaning that can be understood by users. There must be a shared vocabulary between a service and its consumers.&lt;br /&gt;&lt;br /&gt;A service provider should ignore any query parameters it does not understand during processing. If it needs to consume other services, it should pass all ignored parameters along. This practice allows new functionality to be added without breaking existing services. Here &lt;b&gt;XML schema&lt;/b&gt; can be used to validate query parameters.&lt;br /&gt;&lt;br /&gt;The resource should be delivered by either of these 4 ways.&lt;br /&gt;&lt;ol style="text-align: left;"&gt;&lt;li&gt;Server-driven negotiation.&lt;/li&gt;&lt;li&gt;Client-driven negotiation.&lt;/li&gt;&lt;li&gt;Proxy-driven negotiation.&lt;/li&gt;&lt;li&gt;URI-specified representation. &lt;/li&gt;&lt;/ol&gt;A service represents a specialized business function. Hence it should be safe and should not incur any obligations from its invoking client, even if this service may cause a change of state on the server side.&lt;br /&gt;&lt;br /&gt;A safe service should be invoked by the GET method of HTTP. Parameters needed to invoke the service can be embedded in the query string of a URI. The main purpose of a safe service is to obtain a representation of a resource.&lt;br /&gt;&lt;br /&gt;If there is more than one representation available for a resource, the service should negotiate with the client as discussed above. When returning a representation, a service provider should set the HTTP headers that relate to caching policies for better performance.&lt;br /&gt;&lt;br /&gt;Obligated services should be implemented using POST. A request to an obligated service should be described by some kind of XML instance, which should be constrained by a schema. The schema should be written in W3C XML Schema or Relax NG. An obligated service should be made idempotent so that if a client is unsure about the state of its request, it can send it again.&lt;br /&gt;&lt;br /&gt;Web service should be asynchronous i.e it needs to :&lt;br /&gt;&lt;ul style="text-align: left;"&gt;&lt;li&gt;Return a receipt immediately upon receiving a request.&lt;/li&gt;&lt;li&gt;Validate the request.&lt;/li&gt;&lt;li&gt;If the request if valid, the service must act on the request as soon as possible. It must report an error if the service cannot process the request after a period of time defined in the service contract. &lt;/li&gt;&lt;/ul&gt;The receipt element should include a received attribute, the value of which is the time the server received the request in WXS dateTime type format.&lt;br /&gt;&lt;br /&gt;A transaction represents an atomic unit of work done by a server. The goal of a transaction is to complete the work successfully or return to the original state if an error occurs. For example, a transaction in a purchase order service should either place the order successfully or not place the order at all, in which case the client incurs no obligation.&lt;br /&gt;&lt;br /&gt;The status resource should not vary much from it's transaction URI. For example:&lt;br /&gt;&lt;br /&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;Transaction URI: http://mycamera.com/xyz1234&lt;/div&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;Transaction Status URI: http://mycamera.com/xyz1234?option=status&lt;/div&gt;&lt;br /&gt;Life cycle of transaction should be as shown in below image.&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/-KLgXvrNVnE4/Tv8C_amVymI/AAAAAAAAADI/wSHhOKG1WGM/s1600/rest3.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://2.bp.blogspot.com/-KLgXvrNVnE4/Tv8C_amVymI/AAAAAAAAADI/wSHhOKG1WGM/s1600/rest3.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;While receiving and sending XML, one should follow the principle of &lt;b&gt;strict out and loose in&lt;/b&gt;. When sending XML, one must ensure it is validated against the relevant schema. When receiving an XML document, one should only validate the XML against the smallest set of schema that is really needed. Any software agent must not change XML it does not understand.&lt;br /&gt;&lt;br /&gt;Typical architectural style of a REST web service could have a pipe-and-filter style. This classical and robust architectural style was used by the famous physicist, Richard Feynman, to build the first atomic bomb in his computing team. It is made of front-end filters, a connector and back-end filters as shown in below image &lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/-37_vtqyrz-Y/Tv8DJOpBVVI/AAAAAAAAADU/r5twzvn5CQs/s1600/rest4.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://2.bp.blogspot.com/-37_vtqyrz-Y/Tv8DJOpBVVI/AAAAAAAAADU/r5twzvn5CQs/s1600/rest4.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;In this style a request is processed by a chain of filters and each filter is responsible for a well-defined unit of work. Those filters are further classified as two distinct groups: front-end and back-end. Front-end filters are responsible to handle common Web service tasks and they must be light weight. Before or at the end of front-end filters, a response is returned to the invoking client.&lt;/div&gt;&lt;br /&gt;All front-end filters must be lightweight and must not cause serious resource drain on the host. A common filter is a bouncer filter, which checks the eligibility of the request using some simple techniques:&lt;br /&gt;&lt;ol style="text-align: left;"&gt;&lt;li&gt;IP filtering. Only requests from eligible IPs are allowed.&lt;/li&gt;&lt;li&gt;URL mapping. Only certain URL patterns are allowed.&lt;/li&gt;&lt;li&gt;Time-based filtering. A client can only send a certain number of requests per second.&lt;/li&gt;&lt;li&gt;Cookie-based filtering. A client must have a cookie to be able to access this service.&lt;/li&gt;&lt;li&gt;Duplication-detection filter. This filter checks the content of a request and determines whether it has received it before. A simple technique is based on the hash value of the received message. However, a more sophisticated technique involves normalizing the contents using an application-specific algorithm. &lt;/li&gt;&lt;/ol&gt;A connector, whose purpose is to decouple the time dependency between front-end filters and back-end filters, connects front-end filters and back-end filters. If back-end processing is lightweight, the connector serves mainly as a delegator, which delegates requests to its corresponding back-end processors. If back-end processing is heavy, the connector is normally implemented as a queue.&lt;br /&gt;&lt;br /&gt;Back-end filters are usually more application specific or heavy. They should not respond directly to requests but create or update resources.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: large;"&gt;#8.1 Determining data interchange format&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Most REST web services use XML as data interchange format. However it is not necessary to use only XML as different web services might have different requirements. There can be used plain text as well as HTML.&lt;br /&gt;&lt;br /&gt;Why XML is used the most is because it is well structured and information can easily be extracted from returned data by using ready made XML parsers. For Plain text and HTML it is difficult to extract certain piece of information unless used at whole.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: small;"&gt;#8.1.1 Data interchange format and JSON&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Apart from XML, JSON is an another popular data interchange format for REST web services. It is Javascript object notation which is used at client side to interpret response in Javascript. Response provided by server can directly be used in JS if web service outputs data in JSON format. JSON:&lt;br /&gt;&lt;ol style="text-align: left;"&gt;&lt;li&gt;conforms REST principles.&lt;/li&gt;&lt;li&gt;handles simple and complex data types,&lt;/li&gt;&lt;li&gt;can be used with Ajax and&lt;/li&gt;&lt;li&gt;can be used at server side. &lt;/li&gt;&lt;/ol&gt;Since no other middle layer processing is required, to process JSON data before using it, it is widely used in client applications. Below is given an example of REST web service using JSON as output format.&lt;br /&gt;&lt;ul style="text-align: left;"&gt;&lt;li&gt;Server side implementation &lt;/li&gt;&lt;/ul&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;// Class to convert Rupees into Euro, USD and Pound.&lt;/div&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;class Converter&lt;/div&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;{&lt;/div&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp; public function convert($curr='E', $value=0)&lt;/div&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp; {&lt;/div&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; if($curr == 'E')&lt;/div&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return ($value / 55);&lt;/div&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; if($curr == 'D')&lt;/div&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return ($value / 44);&lt;/div&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; if($curr == 'P')&lt;/div&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return ($value / 75);&lt;/div&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp; &amp;nbsp; ... &lt;/div&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp; }&lt;/div&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;}&lt;/div&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;// Create instance.&lt;/div&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;$converter=new Converter;&lt;/div&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;// Convert value. When call is made like&lt;/div&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;// "converter.php?curr=E&amp;amp;value=3000"&lt;/div&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;$value=$converter-&amp;gt;convert($_GET['curr'], $_GET['value']);&lt;/div&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;// Store result into array.&lt;/div&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;$result=array('value'=&amp;gt; $value);&lt;/div&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;// Output JSON encoded string to be used by JS.&lt;/div&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;echo 'var result='.json_encode($result);&lt;/div&gt;&lt;ul style="text-align: left;"&gt;&lt;li&gt;Client side implementation &lt;/li&gt;&lt;/ul&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;[html]&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;[head]&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp; [script type="text/javascript" src="converter.php?curr=E&amp;amp;value=3000"]&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;[/script]&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;[/head]&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;[body]&lt;/span&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp; [script type="text/javascript"]&lt;/span&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; var json=eval(result);&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp; &amp;nbsp; alert(json.value) // Alerts "54.54".&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp; [/script]&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;[/body]&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;[/html]&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: large;"&gt;#8.2 Building API&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;REST API should respect REST principles. Hence while building API, following technical points should be kept in mind. &lt;br /&gt;&lt;ul style="text-align: left;"&gt;&lt;li&gt;URL of REST web service API should be easy to read and understand and should be self-descriptive. For example for our example project project, URL could be like &lt;b&gt;http://rest.mycamera.com&lt;/b&gt; or &lt;b&gt;http://webservice.mycamera.com&lt;/b&gt;.&lt;/li&gt;&lt;li&gt;API can be designed using existing structure of the project so that project's common libraries can also be used. &lt;/li&gt;&lt;li&gt;REST doesn't constrain how request should be handled at back-end. Hence developers have full control and convenience over design and implementation of API. Therefore only single controller can be used to understand incoming requests. This controller then can call other scripts or code to generate proper response in order to satisfy request. &lt;/li&gt;&lt;li&gt;Conventions used in scripts and resources should be self-descriptive and easy to navigate in between. For example resource that provides information of particular user could be as simple as like &lt;b&gt;http://rest.mycamera.com/user/XXXX&lt;/b&gt; (where XXXX is ID of user). Similarly information of 1st album of this user can be represented by resource like &lt;b&gt;http://rest.mycamera.com/user/XXXX/album/YYYY&lt;/b&gt; (where YYYY is ID of 1st album). However for same resource, there can be updation or deletion operations also. This can be determined by type of HTTP request. For example, for URL &lt;b&gt;http://rest.mycamera.com/user/XXXX&lt;/b&gt;, if GET method is used then it means information of user has been requested. But if PUT (sometimes POST) method is used then information is to be updated and if DELETE method is used then resource is to be deleted (i.e user is to be deleted). &lt;/li&gt;&lt;/ul&gt;&lt;blockquote class="tr_bq"&gt;As we know that handling above type of resources is not easy at server side due to web server constraints, hence frameworks like Symfony (together with URL rewriting mechanism called mod_rewrite for Apache web server) can be used to easily extract operation and values from resources. &lt;/blockquote&gt;&lt;ul style="text-align: left;"&gt;&lt;li&gt;API should be well documented. &lt;/li&gt;&lt;li&gt;If data transferring between client and server are sensitive then secure HTTP i.e &lt;b&gt;https&lt;/b&gt; should be used. &lt;/li&gt;&lt;/ul&gt;&lt;span style="font-size: large;"&gt;#8.3 Authenticating users&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;It is often required to ask users to provide authentication before allowing them to access web service or certain part of web service. There are various ways for to accomplish this task. Since REST architectural style is stateless, we can't ask users to provide valid credentials every time they submit requests. We can have 3 types of solutions. &lt;br /&gt;&lt;ol style="text-align: left;"&gt;&lt;li&gt;Standard solution of this problem is to use HTTP authentication. Once user is authenticated, he/she will just need to provide valid token for validation instead of providing credential every time. This token can then be used to response subsequent requests.&lt;/li&gt;&lt;li&gt;Another approach is to use Session mechanism that PHP provides. Once API validates users' credentials, it should create session for associate user. PHP then issues a session ID (referred as PHPSESSID) that can be used to associate particular user with existing session on server. This session ID is stored in form of cookie at user side (if user has enabled cookies) and will be read directly from there by PHP's session mechanism. If cookies are disabled (or not accepted) then this session ID can be appended to query string each time new request is made to web service. PHP stores sessions in form of files at specified folders (usually /tmp). This session ID stores user's information such as browser's user agent, IP address of user's machine etc. which means even if someone else tries to use this session ID to act as authenticated user, he/she can't do so. Moreover, by default, upon inactivity, these session IDs are destroyed after 20 minutes which means in future also none can use it.&lt;/li&gt;&lt;li&gt;3rd solutions is to use customized interface to authenticate users. For that database storage system can be used where user's information can be stored. When user submits request 1st time, he/she will require to provide ID and Password to log on web service. At server side API will do authentication and will issue a unique hash or token back to user to be used for subsequent requests. This hash will be appended to request URL every time new request will be made. At server side this hash or token will be stored in database along with other information of user for future validations. By this way we can increase/decrease inactivity time out, can store more information about user and can retain certain information of client for logging purpose etc.&lt;/li&gt;&lt;/ol&gt;&lt;span style="font-size: x-large;"&gt;#9 Summary&lt;/span&gt; &lt;br /&gt;&lt;br /&gt;There are many components of web that exist since long time but were not utilized in best way. REST and Ajax are examples of them. Few years ago web was simple hence people were using REST principles unknowingly. At that time it was not required to have look at them in ordered way. But when web became complex flooding with so many complex techniques, it is again required to make things simple. &lt;br /&gt;&lt;br /&gt;REST has been recalled to make things simple. Currently REST is gaining rapid growth because of it's simplicity of implementation and usage over XML-RPC and SOAP. Hence it is the key of next generation web services. Overall, the thing to keep in mind is that REST is about exposing resources through URIs, not services through messaging interfaces.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: x-large;"&gt;#10 Links&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.xfront.com/REST.ppt"&gt;http://www.xfront.com/REST.ppt&lt;/a&gt;&lt;br /&gt;&lt;a href="http://en.wikipedia.org/wiki/Representational_State_Transfer"&gt;http://en.wikipedia.org/wiki/Representational_State_Transfer&lt;/a&gt;&lt;br /&gt;&lt;a href="http://rest.blueoxen.net/cgi-bin/wiki.pl?FrontPage"&gt;http://rest.blueoxen.net/cgi-bin/wiki.pl?FrontPage&lt;/a&gt;&lt;br /&gt;&lt;a href="http://rest.blueoxen.net/cgi-bin/wiki.pl?RestFaq"&gt;http://rest.blueoxen.net/cgi-bin/wiki.pl?RestFaq&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.xfront.com/REST-Web-Services.html"&gt;http://www.xfront.com/REST-Web-Services.html&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.w3.org/DesignIssues/Axioms.html"&gt;http://www.w3.org/DesignIssues/Axioms.html&lt;/a&gt;&lt;br /&gt;&lt;a href="http://developer.yahoo.com/maps/rest/V1/geocode.html"&gt;http://developer.yahoo.com/maps/rest/V1/geocode.html&lt;/a&gt; &lt;br /&gt;&lt;a href="http://www.onlamp.com/pub/a/php/2003/07/03/php_amazon_soap.html"&gt;http://www.onlamp.com/pub/a/php/2003/07/03/php_amazon_soap.html&lt;/a&gt; &lt;a href="http://www.onlamp.com/pub/a/php/2003/10/30/amazon_rest.html"&gt;http://www.onlamp.com/pub/a/php/2003/10/30/amazon_rest.html&lt;/a&gt; &lt;a href="http://webservices.xml.com/pub/a/ws/2004/03/24/phpws.html"&gt;http://webservices.xml.com/pub/a/ws/2004/03/24/phpws.html&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.xml.com/pub/a/2004/08/11/rest.html"&gt;http://www.xml.com/pub/a/2004/08/11/rest.html&lt;/a&gt; &lt;br /&gt;&lt;a href="http://ajaxpatterns.org/archive/RESTful_Service.php"&gt;http://ajaxpatterns.org/archive/RESTful_Service.php&lt;/a&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/298834846183725348-8002155162918041099?l=arzala.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://arzala.blogspot.com/feeds/8002155162918041099/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=298834846183725348&amp;postID=8002155162918041099' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/298834846183725348/posts/default/8002155162918041099'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/298834846183725348/posts/default/8002155162918041099'/><link rel='alternate' type='text/html' href='http://arzala.blogspot.com/2006/11/rest.html' title='REST'/><author><name>Anirudhsinh Zala</name><uri>http://www.blogger.com/profile/16341197487842993303</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://2.bp.blogspot.com/-jEmJYVgTwk0/Tu4SjN7xOgI/AAAAAAAAABI/17BzjhETHMM/s220/me.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/-Yh940c3EjzQ/Tv8BlN6j5VI/AAAAAAAAACw/GpPgwzC0m8U/s72-c/rest1.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-298834846183725348.post-8395228363948980074</id><published>2006-09-06T22:11:00.000+05:30</published><updated>2011-12-30T12:06:14.639+05:30</updated><category scheme='http://www.blogger.com/atom/ns#' term='symfony'/><category scheme='http://www.blogger.com/atom/ns#' term='performance'/><category scheme='http://www.blogger.com/atom/ns#' term='cache'/><category scheme='http://www.blogger.com/atom/ns#' term='php'/><category scheme='http://www.blogger.com/atom/ns#' term='apache'/><title type='text'>Various types of caching</title><content type='html'>&lt;div dir="ltr" style="text-align: left;" trbidi="on"&gt;&lt;ol style="font-family: inherit; text-align: left;"&gt;&lt;/ol&gt;&lt;span style="font-size: x-large;"&gt;#1 Caching overview&lt;/span&gt;&lt;br /&gt;&lt;ol style="font-family: inherit; text-align: left;"&gt;&lt;/ol&gt;&lt;div style="font-family: inherit;"&gt;Caching is one of the important techniques to gain better performance in serving contents and increasing response time of your web sites. There are several types of caching mechanism that can be used to cache HTML, Media, Raw scripts, Compiled scripts etc. Let's understand what can be cached at what level from below diagram.&lt;/div&gt;&lt;div style="font-family: inherit;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div lang="en-US" style="font-family: inherit; font-style: normal; font-weight: normal; margin-bottom: 0in;"&gt;&lt;div style="text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/-LRDKUxqbmYo/Tu6z_9_xtRI/AAAAAAAAAB0/wTtJiniIoxk/s1600/cache.png" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="400" src="http://1.bp.blogspot.com/-LRDKUxqbmYo/Tu6z_9_xtRI/AAAAAAAAAB0/wTtJiniIoxk/s400/cache.png" width="395" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;div&gt;A request traverses through 3 components viz. Client, Internet and Server environment. At each component there can be implemented various caching mechanism according to requirement.&lt;/div&gt;&lt;/div&gt;&lt;ol style="font-family: inherit; text-align: left;"&gt;&lt;li&gt;At client level browsers are good candidates of caching static media like CSS, Images, JS, Videos etc. Most browsers take such data from cache instead of requesting to serve as fresh copy. They handle caching of such media automatically hence no special instructions or headers are required to tell browser to how to cache such media. However browsers tend to cache almost everything that it renders hence special HTTP headers are passed to inform them to not to cache such items (usually PHP handles this automatically). Browser cache can be also managed by web server by sending certain HTTP headers if browsers are not behaving in normal ways. For that, web server module like mod_expire (for Apache) is used send cache control related HTTP headers. More details about mod_expire can be found later section.&lt;/li&gt;&lt;li&gt;Internet is intermediate between client and server which includes Gateways, ISPs, Proxies and several other components. At this level, ISP and Proxy cache can be implemented to cache pages, but since it is not in control of client or server it is not good option of caching.&lt;/li&gt;&lt;li&gt;Server environment is made of components like Apache web server, PHP scripting language, Middlewares like frameworks and database like MySQL. For each component, there exists separate caching mechanisms to boost performance of web site. Let's discuss about each in detail.&lt;/li&gt;&lt;/ol&gt;&lt;span style="font-size: x-large;"&gt;#2 Levels of caching in server environment&lt;/span&gt;&lt;br /&gt;&lt;ol style="font-family: inherit; text-align: left;"&gt;&lt;/ol&gt;&lt;span style="font-size: large;"&gt;#2.1 Web server (Apache)&lt;/span&gt;&lt;br /&gt;&lt;ol style="font-family: inherit; text-align: left;"&gt;&lt;/ol&gt;&lt;div style="font-family: inherit;"&gt;Certain web servers like Apache, Lighttpd etc. provide built in modules for caching contents at web server level. They are &lt;b&gt;mod_cache, mod_disk_cache, mod_expire, mod_file_cache, mod_mem_cache&lt;/b&gt;.&lt;/div&gt;&lt;div style="font-family: inherit;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="font-family: inherit;"&gt;&lt;span style="font-size: small;"&gt;&lt;i&gt;#2.1.1 mod_cache&lt;/i&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="font-family: inherit;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="font-family: inherit;"&gt;This module of Apache web server required to implement caching of HTTP contents. However it is always used along with other caching modules like &lt;i&gt;mod_disk_cache&lt;/i&gt; or &lt;i&gt;mod_mem_cache&lt;/i&gt; depending upon requirements. Detailed information about this module can be found from &lt;a href="http://httpd.apache.org/docs/2.2/en/mod/mod_cache.html" target="_blank"&gt;here&lt;/a&gt;.&lt;/div&gt;&lt;div style="font-family: inherit;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="font-family: inherit;"&gt;&lt;i&gt;#2.2.2 mod_disk_cache&lt;/i&gt;&lt;/div&gt;&lt;div style="font-family: inherit;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="font-family: inherit;"&gt;This module is used to cache files using disk based storage manager i.e cached files are stored on disk on URI based keys and when same URI is requested, cache content is served directly from cache. This mechanism is similar like how browser caches entire page on local disk. The only difference here is that content is stored on server instead of client. Detailed information about this module can be found from &lt;a href="http://httpd.apache.org/docs/2.2/en/mod/mod_disk_cache.html" target="_blank"&gt;here&lt;/a&gt;.&lt;/div&gt;&lt;div style="font-family: inherit;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="font-family: inherit;"&gt;&lt;i&gt;#2.2.3 mod_file_cache&lt;/i&gt;&lt;/div&gt;&lt;div style="font-family: inherit;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="font-family: inherit;"&gt;This module provides two techniques for caching frequently requested static files. Through configuration directives, mod_file_cache can be directed to either open then &lt;b&gt;mmap()&lt;/b&gt; a file, or to &lt;b&gt;pre-open&lt;/b&gt; a file and save the file's open file handle. Both techniques reduce server load when processing requests for these files by doing part of the work (specifically, the file I/O) for serving the file when the server is started rather than during each request.&lt;/div&gt;&lt;div style="font-family: inherit;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="font-family: inherit;"&gt;Not all platforms support both techniques, hence it is to be found out that which technique will work for specific environment.&lt;/div&gt;&lt;div style="font-family: inherit;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="font-family: inherit;"&gt;This &lt;b&gt;mmap()&lt;/b&gt; ing is done once at server start or restart, only. So whenever one of the mapped files changes on the filesystem, web server is to be restarted. However if the files are modified in place without restarting the server, only cached contents will be served. Hence files should get updated by unlinking the old copy and putting a new copy in place. Most tools such as &lt;b&gt;&lt;i&gt;rdist&lt;/i&gt;&lt;/b&gt; and &lt;b&gt;&lt;i&gt;mv&lt;/i&gt;&lt;/b&gt; do this. The reason why this modules do't take care of changes to the files is that this check would need an extra stat() every time which is a waste and against the intent of I/O reduction.&lt;/div&gt;&lt;div style="font-family: inherit;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="font-family: inherit;"&gt;For certain systems, configuration and global files are ideal candidates for this module because they do not get changed frequently. This mechanism should not be used to cache media files as they can be effectively cached at client side. Detailed information about this module can be found from &lt;a href="http://httpd.apache.org/docs/2.2/en/mod/mod_file_cache.html" target="_blank"&gt;here&lt;/a&gt;.&lt;/div&gt;&lt;div style="font-family: inherit;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="font-family: inherit;"&gt;&lt;i&gt;#2.2.4 mod_mem_cache&lt;/i&gt;&lt;/div&gt;&lt;div style="font-family: inherit;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="font-family: inherit;"&gt;As opposite to mod_disk_cache, mod_mem_cache implements memory based caching of contents which provides faster access to cached contents than disk. This module can be implemented in 2 ways;&lt;br /&gt;&lt;ol style="text-align: left;"&gt;&lt;li&gt;by caching open file descriptors or&lt;/li&gt;&lt;li&gt;caching objects in heap storage. This module is most useful when it is used to cache locally generated content or to cache backend server content for &lt;i&gt;mod_proxy&lt;/i&gt; configured as reverse proxy. Content is stored in and retrieved from the cache using URI based keys.&lt;/li&gt;&lt;/ol&gt;&lt;/div&gt;&lt;div style="font-family: inherit;"&gt;This module can be used to store session files in memory to share session across different services of particular system. Detailed information about this module can be found from &lt;a href="http://httpd.apache.org/docs/2.2/en/mod/mod_mem_cache.html" target="_blank"&gt;here&lt;/a&gt;.&lt;/div&gt;&lt;div style="font-family: inherit;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="font-family: inherit;"&gt;&lt;i&gt;#2.2.5 mod_expire&lt;/i&gt;&lt;/div&gt;&lt;div style="font-family: inherit;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="font-family: inherit;"&gt;This module controls the setting of the &lt;b&gt;Expires&lt;/b&gt; HTTP header and the &lt;b&gt;max-age&lt;/b&gt; directive of the &lt;b&gt;Cache-Control HTTP header&lt;/b&gt; in server responses. The expiration date can set to be relative to either the time the source file was last modified, or to the time of the client access.&lt;/div&gt;&lt;div style="font-family: inherit;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="font-family: inherit;"&gt;These HTTP headers are an instruction to the client about the document's validity and persistence. If cached, the document may be fetched from the cache rather than from the source until this time has passed. After that, the cache copy is considered "expired" and invalid, and a new copy must be obtained from the source.&lt;/div&gt;&lt;div style="font-family: inherit;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="font-family: inherit;"&gt;This module is not useful when caching is turned off from browser because nothing is cached at server side. Since most browsers automatically handle caching of static media, this module may not be as useful as it seems. Detailed information about this module can be found from &lt;a href="http://httpd.apache.org/docs/2.2/en/mod/mod_expires.html" target="_blank"&gt;here&lt;/a&gt;.&lt;/div&gt;&lt;div style="font-family: inherit;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="font-family: inherit;"&gt;&lt;i&gt;#2.2.6 Reverse proxy (Varnish)&lt;/i&gt;&lt;/div&gt;&lt;div style="font-family: inherit;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="font-family: inherit;"&gt;&lt;a href="http://arzala.blogspot.com/2008/01/varnish-accelerator.html" target="_blank"&gt;See here&lt;/a&gt;.&lt;/div&gt;&lt;div style="font-family: inherit;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;span style="font-size: large;"&gt;#2.2 Scripting language (PHP)&lt;/span&gt;&lt;br /&gt;&lt;div style="font-family: inherit;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="font-family: inherit;"&gt;&lt;i&gt;#2.2.1 Opcode/Bytecode cache&lt;/i&gt;&lt;/div&gt;&lt;div style="font-family: inherit;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="font-family: inherit;"&gt;Opcode/Bytecode caching is caching your PHP script into compiled state so that when new request arrives for same script, cache software will server compiled version of code directly from cache rather than reading file from the disk and then compiling. Some examples of opcode caching softwares are &lt;a href="http://www.zend.com/de/products/zend_optimizer/"&gt;Zend Platform&lt;/a&gt;, &lt;a href="http://pecl.php.net/package/APC"&gt;APC&lt;/a&gt; (&lt;a href="http://www0.fh-trier.de/%7Ebeckerr/apcphpgui.phtml"&gt;APC GUI&lt;/a&gt;), &lt;a href="http://trac.lighttpd.net/xcache/wiki"&gt;XCache&lt;/a&gt;, &lt;a href="http://www.eaccelerator.net/"&gt;eAccelerator&lt;/a&gt;, &lt;a href="http://www.ioncube.com/"&gt;ionCube Encoder&lt;/a&gt; and &lt;a href="http://www.php-accelerator.co.uk/"&gt;PHP Accelerator&lt;/a&gt;. From these 6, eAccelerator, XCache and APC are widely used caching softwares. &lt;a href="http://itst.net/wp-content/uploads/2006/10/PHP%20Bytecode%20Cacher%20Review.html"&gt;This benchmarks&lt;/a&gt; also show that how XCache and APC are better than others.&lt;/div&gt;&lt;div style="font-family: inherit;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="font-family: inherit;"&gt;&lt;span style="font-size: large;"&gt;#2.3 Middleware (Symfony)&lt;/span&gt;&lt;/div&gt;&lt;div style="font-family: inherit;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="font-family: inherit;"&gt;Symfony framework provides 3 types of caching of data. They are HTML cache of output, cache of configuration scripts and cache of translated templates. Last 2 mechanisms are automatic and handled by Symfony directly.&lt;/div&gt;&lt;div style="font-family: inherit;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="font-family: inherit;"&gt;&lt;i&gt;#2.3.1 HTML cache&lt;/i&gt;&lt;/div&gt;&lt;div style="font-family: inherit;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="font-family: inherit;"&gt;HTML cache is nothing but output of script that is sent to browser for display. A web page is made of many sections. These sections are mostly designed in separate templates and files. Hence depending upon type of output, different type of HTML caching can be enabled in Symfony environment. Caching can be enabled by changing off =&amp;gt; on in settings.yml file as shown below.&lt;/div&gt;&lt;div style="font-family: inherit;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="font-family: inherit;"&gt;prod:&lt;/div&gt;&lt;div style="font-family: inherit;"&gt;dev:&lt;/div&gt;&lt;div style="font-family: inherit;"&gt;&amp;nbsp; .settings:&lt;/div&gt;&lt;div style="font-family: inherit;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; cache : on&lt;/div&gt;&lt;div style="font-family: inherit;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="font-family: inherit;"&gt;There are 5 types of HTML cache that can be implemented in Symfony. They are Action, Partial, Component, Page and Fragment of template. Each type is useful depending upon type of data. Enabling each type of cache requires specific settings in configuration files at various levels. For more details, please refer to Symfony API manual.&lt;/div&gt;&lt;div style="font-family: inherit;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="font-family: inherit;"&gt;In modern web applications, most of data is dynamic hence great care should be taken while enabling caching in particular action or page.&lt;/div&gt;&lt;div style="font-family: inherit;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="font-family: inherit;"&gt;However following care should be taken before implementing HTML cache in Symfony.&lt;/div&gt;&lt;ol style="font-family: inherit;"&gt;&lt;li&gt;Setting less time of caching data may not effectively boost performance, similarly setting long time than required may result in annoyance of users since they could be viewing old data. &lt;/li&gt;&lt;li&gt;Structure of page should be divided into sections like which section can be cached and which can not be so that cached part can easily be identified and handled. &lt;/li&gt;&lt;li&gt;Enabling or Disabling cache should not be entirely depending upon just any programmer, instead it should be well discussed before making any change in it. &lt;/li&gt;&lt;li&gt;Static templates should not be cached as anyway they do not require extra processing time.&lt;/li&gt;&lt;li&gt;Cache should get cleared regularly either by automatic or manual way. &lt;/li&gt;&lt;/ol&gt;&lt;div style="font-family: inherit;"&gt;&lt;span style="font-size: small;"&gt;&lt;i&gt;#2.3.3 Template Translations cache&lt;/i&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="font-family: inherit;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="font-family: inherit;"&gt;Multilingual projects requires separate language files for each language. These language translation files are also cached by Symfony. Location of these cached files is /..../PROJECT/cache/i18n/. This cache is automatically handled by Symfony hence at code level nothing is to be done.&lt;/div&gt;&lt;div style="font-family: inherit; margin-bottom: 0in;"&gt;&lt;br /&gt;&lt;span style="font-size: large;"&gt;#2.4 Database (MySQL)&lt;/span&gt;&lt;br /&gt;&lt;i&gt;&lt;span style="font-size: small;"&gt;&lt;b&gt;&lt;/b&gt;&lt;/span&gt;&lt;/i&gt;&lt;/div&gt;&lt;div style="font-family: inherit; margin-bottom: 0in;"&gt;&lt;br /&gt;At database level (specially MySQL), &lt;b&gt;query cache&lt;/b&gt; can be implemented which stores the text of a &lt;b&gt;SELECT&lt;/b&gt; statement together with the corresponding result that was sent to the client. If an identical statement is received later, the server retrieves the results from the query cache rather than parsing and executing the statement again.&lt;br /&gt;&lt;ul&gt;&lt;li&gt;The query cache is extremely useful in an environment where you have tables that do not change very often and for which the server receives many identical queries. This is a typical situation for many web servers that generate many dynamic pages based on database content.&lt;/li&gt;&lt;li&gt;There are some points to be considered before implementing query cache.&lt;/li&gt;&lt;li&gt;The query cache does not return stale data. When tables are modified, any relevant entries in the query cache are flushed.&lt;/li&gt;&lt;li&gt;The query cache does not work in an environment where you have multiple &lt;i&gt;mysqld&lt;/i&gt; servers updating the same MyISAM tables.&lt;/li&gt;&lt;li&gt;The query cache is not used for server-side prepared statements. If you're using server-side prepared statements consider that these statement won't be satisfied by the cache.&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;div style="font-family: inherit;"&gt;&lt;span style="font-size: x-large;"&gt;#3 Summary&lt;/span&gt;&lt;/div&gt;&lt;br /&gt;Gaining performance boost by using caching mechanism is tricky. Unless used ca&lt;br /&gt;refully, it cannot give required boost. As we know that we can't cache everything (specially dynamic contents), we should try to cache whatever is left. This can be achieved by various types of caching as discussed above. Static contents are well cached by clients, if not then can be cached by web servers. PHP scripts can be cached using Opcode caching softwares like APC, XCache etc. While static part of dynamic data can be cached by middleware like Symfony framework.&lt;br /&gt;&lt;div style="font-family: inherit;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="font-family: inherit;"&gt;However only drawback of caching is that exact calculation of pages served, displayed, data transferred etc. becomes almost impossible which may effect rankings of website and thus effects popularity, revenue generations etc.&lt;/div&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/298834846183725348-8395228363948980074?l=arzala.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://arzala.blogspot.com/feeds/8395228363948980074/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=298834846183725348&amp;postID=8395228363948980074' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/298834846183725348/posts/default/8395228363948980074'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/298834846183725348/posts/default/8395228363948980074'/><link rel='alternate' type='text/html' href='http://arzala.blogspot.com/2011/12/test.html' title='Various types of caching'/><author><name>Anirudhsinh Zala</name><uri>http://www.blogger.com/profile/16341197487842993303</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://2.bp.blogspot.com/-jEmJYVgTwk0/Tu4SjN7xOgI/AAAAAAAAABI/17BzjhETHMM/s220/me.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/-LRDKUxqbmYo/Tu6z_9_xtRI/AAAAAAAAAB0/wTtJiniIoxk/s72-c/cache.png' height='72' width='72'/><thr:total>0</thr:total></entry></feed>
