Permalink
Browse files

EnforceValidEncoding middleware.

  • Loading branch information...
1 parent 6f33726 commit 39fbc43cf524b311a5cb0936911804b82a3c6309 @mipearson committed Dec 16, 2012
Showing with 70 additions and 0 deletions.
  1. +17 −0 lib/rack/contrib/enforce_valid_encoding.rb
  2. +53 −0 test/spec_rack_enforce_valid_encoding.rb
@@ -0,0 +1,17 @@
+module Rack
+ class EnforceValidEncoding
+
+ def initialize app
+ @app = app
+ end
+
+ def call env
+ full_path = (env.fetch('PATH_INFO', '') + env.fetch('QUERY_STRING', ''))
+ if full_path.valid_encoding? && Rack::Utils.unescape(full_path).valid_encoding?
+ @app.call env
+ else
+ [400, {'Content-Type'=>'text/plain'}, ['Bad Request']]
+ end
+ end
+ end
+end
@@ -0,0 +1,53 @@
+# -*- encoding : us-ascii -*-
+if "a string".respond_to?(:valid_encoding?)
+ require 'rack/mock'
+ require 'rack/contrib/enforce_valid_encoding'
+
+ VALID_PATH = "h%C3%A4ll%C3%B2"
+ INVALID_PATH = "/%D1%A1%D4%F1%D7%A2%B2%E1%D3%C3%BB%A7%C3%FB"
+
+ describe "Rack::EnforceValidEncoding" do
+ before do
+ @app = Rack::EnforceValidEncoding.new(lambda { |env|
+ [200, {'Content-Type'=>'text/plain'}, ['Hello World']]
+ })
+ end
+
+ describe "contstant assertions" do
+ it "INVALID_PATH should not be a valid UTF-8 string when decoded" do
+ Rack::Utils.unescape(INVALID_PATH).valid_encoding?.should.equal false
+ end
+
+ it "VALID_PATH should be valid when decoded" do
+ Rack::Utils.unescape(VALID_PATH).valid_encoding?.should.equal true
+ end
+ end
+
+ it "should accept a request with a correctly encoded path" do
+ response = Rack::MockRequest.new(@app).get(VALID_PATH)
+ response.body.should.equal("Hello World")
+ response.status.should.equal(200)
+ end
+
+ it "should reject a request with a poorly encoded path" do
+ response = Rack::MockRequest.new(@app).get(INVALID_PATH)
+ response.status.should.equal(400)
+ end
+
+ it "should accept a request with a correctly encoded query string" do
+ response = Rack::MockRequest.new(@app).get('/', 'QUERY_STRING' => VALID_PATH)
+ response.body.should.equal("Hello World")
+ response.status.should.equal(200)
+ end
+
+ it "should reject a request with a poorly encoded query string" do
+ response = Rack::MockRequest.new(@app).get('/', 'QUERY_STRING' => INVALID_PATH)
+ response.status.should.equal(400)
+ end
+
+ it "should reject a request containing malformed multibyte characters" do
+ response = Rack::MockRequest.new(@app).get('/', 'QUERY_STRING' => Rack::Utils.unescape(INVALID_PATH, Encoding::ASCII_8BIT))
+ response.status.should.equal(400)
+ end
+ end
+end

0 comments on commit 39fbc43

Please sign in to comment.