<?xml version="1.0" encoding="UTF-8"?>
<commit>
  <added type="array"/>
  <modified type="array">
    <modified>
      <diff>@@ -297,9 +297,17 @@ filters are accessible by routes and templates:
     params[:splat] #=&gt; 'bar/baz'
   end
 
+After filter are evaluated after each request within the context of the
+require and can also modify the request and response. Instance variables
+set in before filters and routes are accessible by after filters:
+
+  after do
+    puts response.status
+  end
+
 == Halting
 
-To immediately stop a request during a before filter or route use:
+To immediately stop a request within a filter or route use:
 
   halt
 
@@ -398,7 +406,7 @@ running under the development environment.
 When using &lt;tt&gt;send_file&lt;/tt&gt; or static files you may have mime types Sinatra
 doesn't understand. Use +mime+ to register them by file extension:
 
-  mime :foo, 'text/foo'
+  mime_type :foo, 'text/foo'
 
 == Rack Middleware
 </diff>
      <filename>README.rdoc</filename>
    </modified>
    <modified>
      <diff>@@ -65,7 +65,7 @@ module Sinatra
     def code ; 404 ; end
   end
 
-  # Methods available to routes, before filters, and views.
+  # Methods available to routes, before/after filters, and views.
   module Helpers
     # Set or retrieve the response status code.
     def status(value=nil)
@@ -428,9 +428,15 @@ module Sinatra
 
   private
     # Run before filters defined on the class and all superclasses.
-    def filter!(base=self.class)
-      filter!(base.superclass) if base.superclass.respond_to?(:filters)
-      base.filters.each { |block| instance_eval(&amp;block) }
+    def before_filter!(base=self.class)
+      before_filter!(base.superclass) if base.superclass.respond_to?(:before_filters)
+      base.before_filters.each { |block| instance_eval(&amp;block) }
+    end
+
+    # Run after filters defined on the class and all superclasses.
+    def after_filter!(base=self.class)
+      after_filter!(base.superclass) if base.superclass.respond_to?(:after_filters)
+      base.after_filters.each { |block| instance_eval(&amp;block) }
     end
 
     # Run routes defined on the class and all superclasses.
@@ -560,12 +566,14 @@ module Sinatra
     # Dispatch a request with error handling.
     def dispatch!
       static! if settings.static? &amp;&amp; (request.get? || request.head?)
-      filter!
+      before_filter!
       route!
     rescue NotFound =&gt; boom
       handle_not_found!(boom)
     rescue ::Exception =&gt; boom
       handle_exception!(boom)
+    ensure
+      after_filter!
     end
 
     def handle_not_found!(boom)
@@ -619,16 +627,17 @@ module Sinatra
     end
 
     class &lt;&lt; self
-      attr_reader :routes, :filters, :templates, :errors
+      attr_reader :routes, :before_filters, :after_filters, :templates, :errors
 
       def reset!
-        @conditions = []
-        @routes     = {}
-        @filters    = []
-        @errors     = {}
-        @middleware = []
-        @prototype  = nil
-        @extensions = []
+        @conditions     = []
+        @routes         = {}
+        @before_filters = []
+        @after_filters  = []
+        @errors         = {}
+        @middleware     = []
+        @prototype      = nil
+        @extensions     = []
 
         if superclass.respond_to?(:templates)
           @templates = Hash.new { |hash,key| superclass.templates[key] }
@@ -744,11 +753,18 @@ module Sinatra
         Rack::Mime::MIME_TYPES[type] = value
       end
 
-      # Define a before filter. Filters are run before all requests
-      # within the same context as route handlers and may access/modify the
-      # request and response.
+      # Define a before filter; runs before all requests within the same
+      # context as route handlers and may access/modify the request and
+      # response.
       def before(&amp;block)
-        @filters &lt;&lt; block
+        @before_filters &lt;&lt; block
+      end
+
+      # Define an after filter; runs after all requests within the same
+      # context as route handlers and may access/modify the request and
+      # response.
+      def after(&amp;block)
+        @after_filters &lt;&lt; block
       end
 
       # Add a route condition. The route is considered non-matching when the
@@ -1097,8 +1113,8 @@ module Sinatra
       end
     end
 
-    delegate :get, :put, :post, :delete, :head, :template, :layout, :before,
-             :error, :not_found, :configure, :set, :mime_type,
+    delegate :get, :put, :post, :delete, :head, :template, :layout,
+             :before, :after, :error, :not_found, :configure, :set, :mime_type,
              :enable, :disable, :use, :development?, :test?,
              :production?, :use_in_file_templates!, :helpers
   end</diff>
      <filename>lib/sinatra/base.rb</filename>
    </modified>
    <modified>
      <diff>@@ -1,6 +1,6 @@
 require File.dirname(__FILE__) + '/helper'
 
-class FilterTest &lt; Test::Unit::TestCase
+class BeforeFilterTest &lt; Test::Unit::TestCase
   it &quot;executes filters in the order defined&quot; do
     count = 0
     mock_app do
@@ -21,7 +21,7 @@ class FilterTest &lt; Test::Unit::TestCase
     assert_equal 'Hello World', body
   end
 
-  it &quot;allows filters to modify the request&quot; do
+  it &quot;can modify the request&quot; do
     mock_app {
       get('/foo') { 'foo' }
       get('/bar') { 'bar' }
@@ -44,7 +44,7 @@ class FilterTest &lt; Test::Unit::TestCase
     assert_equal 'bar', body
   end
 
-  it &quot;allows redirects in filters&quot; do
+  it &quot;allows redirects&quot; do
     mock_app {
       before { redirect '/bar' }
       get('/foo') do
@@ -109,3 +109,87 @@ class FilterTest &lt; Test::Unit::TestCase
     assert_equal 'hello from superclass', body
   end
 end
+
+class AfterFilterTest &lt; Test::Unit::TestCase
+  it &quot;executes filters in the order defined&quot; do
+    invoked = 0
+    mock_app do
+      before   { invoked = 2 }
+      get('/') { invoked += 2 }
+      after    { invoked *= 2 }
+    end
+
+    get '/'
+    assert ok?
+
+    assert_equal 8, invoked
+  end
+
+  it &quot;executes filters in the order defined&quot; do
+    count = 0
+    mock_app do
+      get('/') { 'Hello World' }
+      after {
+        assert_equal 0, count
+        count = 1
+      }
+      after {
+        assert_equal 1, count
+        count = 2
+      }
+    end
+
+    get '/'
+    assert ok?
+    assert_equal 2, count
+    assert_equal 'Hello World', body
+  end
+
+  it &quot;allows redirects&quot; do
+    mock_app {
+      get('/foo') { 'ORLY' }
+      after { redirect '/bar' }
+    }
+
+    get '/foo'
+    assert redirect?
+    assert_equal '/bar', response['Location']
+    assert_equal '', body
+  end
+
+  it &quot;does not modify the response with its return value&quot; do
+    mock_app {
+      get('/foo') { 'cool' }
+      after { 'Hello World!' }
+    }
+
+    get '/foo'
+    assert ok?
+    assert_equal 'cool', body
+  end
+
+  it &quot;does modify the response with halt&quot; do
+    mock_app {
+      get '/foo' do
+        &quot;should not be returned&quot;
+      end
+      after { halt 302, 'Hi' }
+    }
+
+    get '/foo'
+    assert_equal 302, response.status
+    assert_equal 'Hi', body
+  end
+
+  it &quot;runs filters defined in superclasses&quot; do
+    count = 2
+    base = Class.new(Sinatra::Base)
+    base.after { count *= 2 }
+    mock_app(base) {
+      get('/foo') { count += 2 }
+    }
+
+    get '/foo'
+    assert_equal 8, count
+  end
+end</diff>
      <filename>test/filter_test.rb</filename>
    </modified>
  </modified>
  <removed type="array"/>
  <parents type="array">
    <parent>
      <id>5c6332c358d95832fcf52adc86a7a9094c650bcc</id>
    </parent>
  </parents>
  <author>
    <name>Jimmy Schementi</name>
    <email>jschementi@gmail.com</email>
  </author>
  <url>http://github.com/rtomayko/sinatra/commit/c4b0fc3eb7894e627ce3e812da46385f0d93f804</url>
  <id>c4b0fc3eb7894e627ce3e812da46385f0d93f804</id>
  <committed-date>2009-10-16T23:12:14-07:00</committed-date>
  <authored-date>2008-12-21T18:36:14-08:00</authored-date>
  <message>Adds after filters

Originally by jschementi (http://bit.ly/1RTt2H)
Updated for Sinatra 1.0 by rtomayko</message>
  <tree>1a1fe899a65caaaacf2ae0d929920f08b81663bb</tree>
  <committer>
    <name>Ryan Tomayko</name>
    <email>rtomayko@gmail.com</email>
  </committer>
</commit>
