45

Lightweight web frameworks

  • Upload
    jph98

  • View
    19.028

  • Download
    1

Embed Size (px)

Citation preview

Page 1: Lightweight web frameworks
Page 2: Lightweight web frameworks

Welcome...

to the inaugural meeting of Chippenham Tech Chat...

Page 3: Lightweight web frameworks

Meetup DetailsWill be hosted once a month at Mango/Scisys - Methuen Park

Presentations on various topics. If you're interested in doing one then propose it on the forum

Meetup grouphttp://www.meetup.com/Chippenham-Tech-Chat/

Google Groups Forumhttps://groups.google.com/forum/?fromgroups#!forum/chippenhamtechchat

Page 4: Lightweight web frameworks

Lightweight Web Frameworks

Jonathan [email protected]

twitter: jph98

Page 5: Lightweight web frameworks

Overview

● A brief history of web applications● Past experience● An overview of lightweight web frameworks● An introduction to one web framework and

it's features● I won't go into

Page 6: Lightweight web frameworks

Web Frameworks - A Brief History

● CGI and Perl - circa 1993● PHP, Coldfusion - circa 1995● ASP - circa 1998● JSP and Servlet Spec - circa 1999● Struts - circa 2001● Rails - circa 2005

How many are there today?

Page 7: Lightweight web frameworks

261 !* at least

Page 8: Lightweight web frameworks

Used Java Servlets and JSP around 1999/2000. First introduction - somewhat painful.

Then discovered Struts in 2001/2002 (pre 1.0 release). Vowed never to go back to JSP hell.

In 2005/2006 we migrated our legacy Struts apps to Struts 2. Better still.

SpringMVC came in around the same time.

Past Experience - Cathedrals

Page 9: Lightweight web frameworks

Broken down into language (approx)

91 33 31 40

14 22 23 7

Page 10: Lightweight web frameworks

Past Experience - Post Java

Then looked at PHP for doing more lightweight work. Used CakePHP 1.x then looked at CodeIgniter.

Used Dojo (pre 1.0 release) and Velocity to build a rich client Javascript application.

Page 11: Lightweight web frameworks

Past Experience - First One Pager

Then ended up building a rich client interface in Google Web Toolkit 1.x

Then around 2007 went along to the Vancouver Ruby/Rails meetup. Talked about Rails/Merb then someone mentioned Sinatra.

Then picked up Flask, looked at Ratpack in Geecon this year

Page 12: Lightweight web frameworks

Flask - Python

Page 13: Lightweight web frameworks

Really?

Page 14: Lightweight web frameworks

Here's what we would have have done back in the day with Apache Struts...

Page 15: Lightweight web frameworks

1. Setup web.xml

2. Created an index.jsp to forward on to my app

3. Setup struts-config.xml and added a form and action mapping detailing my Action class

4. Create an Action & Action Form class

Page 16: Lightweight web frameworks

5. Setup my forward on success

6. Put all this in a predefined folder structure

7. Package it all up into a war file

8. Deploy to Tomcat and Start

Page 17: Lightweight web frameworks

then....

9. Fix the stupid errors

10. Deploy again and see Hello World in my browser. Maybe.

Page 18: Lightweight web frameworks

easy...

Page 19: Lightweight web frameworks

Others?

Page 20: Lightweight web frameworks

There's others !!There's a bunch of other lightweight web frameworks in various languages:

● Flask - Python● Nancy - .NET● Ratpack - Groovy/Java● Berliner - CoffeeScript● Dancer - Perl

Classification of these...

Page 21: Lightweight web frameworks

Web Framework Taxonomy

Sinatra, Flask, Berliner, Dancer, Ratpack, Nancy[Micro Frameworks]

Rails, Django[Lightweight Frameworks]

Play, Struts 2, Spring MVC[MOR]

Google Web Toolkit, JSF[Component Based]

Light

Heavy

Page 22: Lightweight web frameworks

Sinatra - Ruby

#!/usr/bin/env rubyrequire 'rubygems'require 'sinatra'

get '/' do '<b>Hello, world!</b>'end

Page 23: Lightweight web frameworks

Nancy - dot NET

public class SampleModule : Nancy.NancyModule{ public SampleModule() { Get["/"] = _ => "Hello World!"; }}

Page 24: Lightweight web frameworks

Ratpack - Groovy

get("/helloworld") { "Hello, World!"}

Page 25: Lightweight web frameworks

Berliner - Coffeescript

app = require 'berliner'app.get '/', -> 'Hello, world!'app.run 4567

Page 26: Lightweight web frameworks

Properties of such frameworks?

● Minimalistic by default

● Self contained web server

● Modular with extensions available

Page 27: Lightweight web frameworks

Some more on Flask...

Page 28: Lightweight web frameworks

Python Flask Architecture

Based on Werkzeug so mod_wsgi based

Built in web server

Uses Jinja2 for templating

Hosting available on heroku, webfaction

Celery integration for async task/job queuing

Page 29: Lightweight web frameworks

Flask Extension Modules

Example modules (will cover later):● Flask admin - generates an admin interface● Flask login - login mechanism● Flask cache - simple caching● Flask couchdb - couchdb module● Flask lesscss - less CSS template● Flask lettuce - BDD● Flask celery - distributed task queue

Extensions registry here:http://flask.pocoo.org/extensions/

Page 30: Lightweight web frameworks

What can I use Flask for?

1. Projects with tight deadlines

2. Prototyping

3. In-house internal applications

4. Applications where system resources are limited, e.g. VM's hosted on Linode.com

Page 31: Lightweight web frameworks

App

Page 32: Lightweight web frameworks

Flask App - Log Viewer

A lightweight log viewer application, but without the overhead of indexing. Provides:

● Access to specific application logs for users instead of them ssh'ing to the server to "less" them.

● Retrieve the head or tail a log file

● Search in logs (with grep) for an expression

Page 33: Lightweight web frameworks

Flask 0.9 utilising:● YAML (Yet Another Markup Language) for

configuration ● Jinja 2 templates for content separation● The LESS dynamic stylesheet module

Virtualenv - for creating an isolated Python environment to manage dependencies

Python 2.6.1 (CPython)

System Components

Page 34: Lightweight web frameworks

Python Modules

Used additional Python wrappers for Grin - http://pypi.python.org/pypi/grin● Provides search features (wraps GNU grep)● Supports regex, before/after context● File/dir exclusion

Tailer - http://pypi.python.org/pypi/tailer/0.2.1● Display n lines of the head/tail of a file● Allows "follow" of a file

Page 35: Lightweight web frameworks

Main UI

Page 36: Lightweight web frameworks

Templating<!doctype html>{% include 'header.html' %}

{% include 'search.html' %}

{% macro genlink(func, filename) -%} <a href="{{func}}/{{ filename }}/{{ session['grepnumlines'] }}">{{func}}</a>{%- endmacro %}

{% for filename in session['validfiles']|sort %}<div class="logfile">

{{ session['validfiles'].get(filename)[0] }} -{{ genlink('head', filename) }} &nbsp;<span style="color:#cecece">&#124;</span>

&nbsp;{{ genlink('tail', filename) }}- {{ session['validfiles'].get(filename)[1] }} bytes

</div>{% endfor %}

{% include 'footer.html' %}

Page 37: Lightweight web frameworks

New route() for [email protected]("/grep/", methods=['GET', 'POST'])def grep():

"""Search through a file looking for a matching phrase"""

# Validate the form inputsif request is None or request.form is None:

return render_template('list.html',error='no search expression specified')

if request.form['expression'] is None or len(request.form['expression']) == 0:return render_template('list.html',error='no search expression specified')

expression = request.form['expression'].strip()output = ""filepaths = []

output += search_expr(output, filepaths, session.get('validfiles'), expression, request.form['grepbefore'], request.form['grepafter'])

if not output:return render_template('list.html', error='No results found for search expression')

expression = expression.decode('utf-8')highlight = '<span class="highlightmatch">' + expression + '</span>'highlightedoutput = output.decode('utf-8').replace(expression, highlight)

return render_template('results.html', output=highlightedoutput,filepaths=filepaths,expression=expression)

Page 38: Lightweight web frameworks

Search Expression - using grindef search_for_expression(output, filepaths, validfiles, expression, grepbefore, grepafter):

"""Carry out search for expression (using grep context) on validfiles returning matching files as output"""

options = grin.Options()options['before_context'] = int(grepbefore)options['after_context'] = int(grepafter)options['use_color'] = Falseoptions['show_filename'] = Falseoptions['show_match'] = Trueoptions['show_emacs'] = Falseoptions['show_line_numbers'] = True

searchregexp = re.compile(expression)grindef = grin.GrepText(searchregexp, options)

for file in validfiles:filepath = validfiles.get(file)[0]report = grindef.grep_a_file(filepath)if report:

output += '<a name="filename' + str(anchorcount) + '"></a><h2>' + filepath + '</h2>'filepaths.append(filepath)reporttext = report.split("\n")for text in reporttext:

if text:output += "line " + text + "<br>"

return output

Page 39: Lightweight web frameworks

Search UI

Page 40: Lightweight web frameworks

Modules

Page 41: Lightweight web frameworks

cache = Cache(app)cache.init_app(app)cache = Cache(config={'CACHE_TYPE': 'simple'})

#Use a decorator to cache a specific template [email protected](timeout=50)def index(): return render_template('index.html')

Flask Cache

Page 42: Lightweight web frameworks

man = CouchDBManager()man.setup(app)

# Create a local proxy to get around the g.couch namespacecouch = LocalProxy(lambda: g.couch)

# Store a document and retrievedocument = dict(title="Hello", content="Hello, world!")couch[some_id] = documentdocument = couch.get(some_id)

Flask CouchDB

Page 43: Lightweight web frameworks

from flask_mail import Message

@app.route("/")def index():

msg = Message("Hello", sender="[email protected]", recipients=["[email protected]"])

Flask Mail

Page 44: Lightweight web frameworks

from flask import Flask, Response

from flask_principal import Principal, Permission, RoleNeed

app = Flask(__name__)

# load the extension

principals = Principal(app)

# Create a permission with a single Need, in this case a RoleNeed.

admin_permission = Permission(RoleNeed('admin'))

# protect a view with a principal for that need

@app.route('/admin')

@admin_permission.require()

def do_admin_index():

return Response('Only if you are an admin')

Flask Principles

Page 45: Lightweight web frameworks

Q&A