Git Product home page Git Product logo

rack-test's Introduction

Rack

Rack provides a minimal, modular, and adaptable interface for developing web applications in Ruby. By wrapping HTTP requests and responses in the simplest way possible, it unifies and distills the bridge between web servers, web frameworks, and web application into a single method call.

The exact details of this are described in the Rack Specification, which all Rack applications should conform to.

Version support

Version Support
3.0.x Bug fixes and security patches.
2.2.x Security patches only.
<= 2.1.x End of support.

Please see the Security Policy for more information.

Rack 3.0

This is the latest version of Rack. It contains API improvements but also some breaking changes. Please check the Upgrade Guide for more details about migrating servers, middlewares and applications designed for Rack 2 to Rack 3. For detailed information on specific changes, check the Change Log.

Rack 2.2

This version of Rack is receiving security patches only, and effort should be made to move to Rack 3.

Starting in Ruby 3.4 the base64 dependency will no longer be a default gem, and may cause a warning or error about base64 being missing. To correct this, add base64 as a dependency to your project.

Installation

Add the rack gem to your application bundle, or follow the instructions provided by a supported web framework:

# Install it generally:
$ gem install rack

# or, add it to your current application gemfile:
$ bundle add rack

If you need features from Rack::Session or bin/rackup please add those gems separately.

$ gem install rack-session rackup

Usage

Create a file called config.ru with the following contents:

run do |env|
  [200, {}, ["Hello World"]]
end

Run this using the rackup gem or another supported web server.

$ gem install rackup
$ rackup
$ curl http://localhost:9292
Hello World

Supported web servers

Rack is supported by a wide range of servers, including:

You will need to consult the server documentation to find out what features and limitations they may have. In general, any valid Rack app will run the same on all these servers, without changing anything.

Rackup

Rack provides a separate gem, rackup which is a generic interface for running a Rack application on supported servers, which include WEBRick, Puma, Falcon and others.

Supported web frameworks

These frameworks and many others support the Rack Specification:

Available middleware shipped with Rack

Between the server and the framework, Rack can be customized to your applications needs using middleware. Rack itself ships with the following middleware:

  • Rack::CommonLogger for creating Apache-style logfiles.
  • Rack::ConditionalGet for returning Not Modified responses when the response has not changed.
  • Rack::Config for modifying the environment before processing the request.
  • Rack::ContentLength for setting a content-length header based on body size.
  • Rack::ContentType for setting a default content-type header for responses.
  • Rack::Deflater for compressing responses with gzip.
  • Rack::ETag for setting etag header on bodies that can be buffered.
  • Rack::Events for providing easy hooks when a request is received and when the response is sent.
  • Rack::Files for serving static files.
  • Rack::Head for returning an empty body for HEAD requests.
  • Rack::Lint for checking conformance to the Rack Specification.
  • Rack::Lock for serializing requests using a mutex.
  • Rack::Logger for setting a logger to handle logging errors.
  • Rack::MethodOverride for modifying the request method based on a submitted parameter.
  • Rack::Recursive for including data from other paths in the application, and for performing internal redirects.
  • Rack::Reloader for reloading files if they have been modified.
  • Rack::Runtime for including a response header with the time taken to process the request.
  • Rack::Sendfile for working with web servers that can use optimized file serving for file system paths.
  • Rack::ShowException for catching unhandled exceptions and presenting them in a nice and helpful way with clickable backtrace.
  • Rack::ShowStatus for using nice error pages for empty client error responses.
  • Rack::Static for more configurable serving of static files.
  • Rack::TempfileReaper for removing temporary files creating during a request.

All these components use the same interface, which is described in detail in the Rack Specification. These optional components can be used in any way you wish.

Convenience interfaces

If you want to develop outside of existing frameworks, implement your own ones, or develop middleware, Rack provides many helpers to create Rack applications quickly and without doing the same web stuff all over:

  • Rack::Request which also provides query string parsing and multipart handling.
  • Rack::Response for convenient generation of HTTP replies and cookie handling.
  • Rack::MockRequest and Rack::MockResponse for efficient and quick testing of Rack application without real HTTP round-trips.
  • Rack::Cascade for trying additional Rack applications if an application returns a not found or method not supported response.
  • Rack::Directory for serving files under a given directory, with directory indexes.
  • Rack::MediaType for parsing content-type headers.
  • Rack::Mime for determining content-type based on file extension.
  • Rack::RewindableInput for making any IO object rewindable, using a temporary file buffer.
  • Rack::URLMap to route to multiple applications inside the same process.

Configuration

Rack exposes several configuration parameters to control various features of the implementation.

param_depth_limit

Rack::Utils.param_depth_limit = 32 # default

The maximum amount of nesting allowed in parameters. For example, if set to 3, this query string would be allowed:

?a[b][c]=d

but this query string would not be allowed:

?a[b][c][d]=e

Limiting the depth prevents a possible stack overflow when parsing parameters.

multipart_file_limit

Rack::Utils.multipart_file_limit = 128 # default

The maximum number of parts with a filename a request can contain. Accepting too many parts can lead to the server running out of file handles.

The default is 128, which means that a single request can't upload more than 128 files at once. Set to 0 for no limit.

Can also be set via the RACK_MULTIPART_FILE_LIMIT environment variable.

(This is also aliased as multipart_part_limit and RACK_MULTIPART_PART_LIMIT for compatibility)

multipart_total_part_limit

The maximum total number of parts a request can contain of any type, including both file and non-file form fields.

The default is 4096, which means that a single request can't contain more than 4096 parts.

Set to 0 for no limit.

Can also be set via the RACK_MULTIPART_TOTAL_PART_LIMIT environment variable.

Changelog

See CHANGELOG.md.

Contributing

See CONTRIBUTING.md for specific details about how to make a contribution to Rack.

Please post bugs, suggestions and patches to GitHub Issues.

Please check our Security Policy for responsible disclosure and security bug reporting process. Due to wide usage of the library, it is strongly preferred that we manage timing in order to provide viable patches at the time of disclosure. Your assistance in this matter is greatly appreciated.

See Also

rack-contrib

The plethora of useful middleware created the need for a project that collects fresh Rack middleware. rack-contrib includes a variety of add-on components for Rack and it is easy to contribute new modules.

rack-session

Provides convenient session management for Rack.

Thanks

The Rack Core Team, consisting of

and the Rack Alumni

would like to thank:

  • Adrian Madrid, for the LiteSpeed handler.
  • Christoffer Sawicki, for the first Rails adapter and Rack::Deflater.
  • Tim Fletcher, for the HTTP authentication code.
  • Luc Heinrich for the Cookie sessions, the static file handler and bugfixes.
  • Armin Ronacher, for the logo and racktools.
  • Alex Beregszaszi, Alexander Kahn, Anil Wadghule, Aredridel, Ben Alpert, Dan Kubb, Daniel Roethlisberger, Matt Todd, Tom Robinson, Phil Hagelberg, S. Brent Faulkner, Bosko Milekic, Daniel Rodríguez Troitiño, Genki Takiuchi, Geoffrey Grosenbach, Julien Sanchez, Kamal Fariz Mahyuddin, Masayoshi Takahashi, Patrick Aljordm, Mig, Kazuhiro Nishiyama, Jon Bardin, Konstantin Haase, Larry Siden, Matias Korhonen, Sam Ruby, Simon Chiang, Tim Connor, Timur Batyrshin, and Zach Brock for bug fixing and other improvements.
  • Eric Wong, Hongli Lai, Jeremy Kemper for their continuous support and API improvements.
  • Yehuda Katz and Carl Lerche for refactoring rackup.
  • Brian Candler, for Rack::ContentType.
  • Graham Batty, for improved handler loading.
  • Stephen Bannasch, for bug reports and documentation.
  • Gary Wright, for proposing a better Rack::Response interface.
  • Jonathan Buch, for improvements regarding Rack::Response.
  • Armin Röhrl, for tracking down bugs in the Cookie generator.
  • Alexander Kellett for testing the Gem and reviewing the announcement.
  • Marcus Rückert, for help with configuring and debugging lighttpd.
  • The WSGI team for the well-done and documented work they've done and Rack builds up on.
  • All bug reporters and patch contributors not mentioned above.

License

Rack is released under the MIT License.

rack-test's People

Contributors

admtnnr avatar alan avatar brynary avatar christhesoul avatar dosire avatar fidalgo avatar h-lame avatar ihoka avatar ioquatix avatar jeremyevans avatar josh avatar junaruga avatar krekoten avatar manveru avatar nakajima avatar nicolasleger avatar noahd1 avatar nusco avatar olleolleolle avatar pdg137 avatar perlun avatar schinery avatar segiddins avatar sergio91pt avatar simi avatar smtlaissezfaire avatar sr avatar stevecrozz avatar szalansky avatar tricknotes avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

rack-test's Issues

No Referer header set when follow_redirect! is called

In a normal Rails application with Devise, I can sign up or sign in as a user and then be redirected to the root_path of my application. In the action at this point, I am able to make reference to request.referer to determine where the request came from. This is incredibly helpful if you want to show people who have recently signed up a slightly different page because they have to confirm their accounts before they can see this action. All is sunshine and rainbows in the wonderful world of rails server.

However, when I run my Cucumber tests to test this particular feature, the Referer header is NOT set by rack-test and therefore my features fail. I believe this is a problem to do with rack-test, as I can see no code which would set the Referer header upon a redirect.

I have attempted to patch this myself and haven't been able to find a clean way to implement it yet.

"Bad URI" error on unicode URIs

in rack/test.rb:171, URI.parse is used to create a URI instance. Unfortunately, the uri library cannot handle URIs with unicode characters in them: http://bugs.ruby-lang.org/issues/1787

It'd be nice if rack-test avoided URI or was able to take advantage of something like https://github.com/sporkmonger/addressable which handles unicode URIs correctly. Even allowing URI-like objects to be passed into Rack::Test methods without being parsed (so we could use Addressable ourselves) would be great.

Unordered hashes on ruby 1.8 break rack param parsing

When posting hash params to a server using rack-test, the ordering of elements can cause problems. This isn't a problem in a non-test scenario because the ordering in html determines the ordering of the param string, which gets parsed correctly by rack.
For example, in the following request, a change in the iterated order of the last hash param causes the "fairly" key to get associated with the previous hash when rack parses the generated query string. No idea how one would fix this short of using an OrderedHash in client's test code, but thought I'd mention it in case someone has an idea.

params = {'priorities' => [
    {"pattern" => "foo"},
    {"pattern" => "default"},
    {"pattern" => "bar", "fairly" => "true"}
]}
post "/queuepriority", params 

1.9
rack test generates: "priorities[][pattern]=foo&priorities[][pattern]=default&priorities[][pattern]=bar&priorities[][fairly]=true"
rack parses to: {"priorities"=>[{"pattern"=>"foo"}, {"pattern"=>"default"}, {"pattern"=>"bar", "fairly"=>"true"}]}

1.8
rack-test generates: "priorities[][pattern]=foo&priorities[][pattern]=default&priorities[][fairly]=true&priorities[][pattern]=bar"
rack parses to: {"priorities"=>[{"pattern"=>"foo"}, {"fairly"=>"true", "pattern"=>"default"}, {"pattern"=>"bar"}]}

Content type header gets stomped

I tried setting the Content-Type header like so:

header 'Content-Type', 'application/json'
get 'some/path'

However, rack-test stomps the content type header. First, #headers_for_environment converts it to HTTP_CONTENT_TYPE. Then #env_for sets the content type to application/x-www-form-urlencoded here. Since my content type header was converted to HTTP_CONTENT_TYPE, CONTENT_TYPE has no value and the ||= stomps it.

I'm willing to take a crack at fixing it and submitting a patch, but I'm not sure of the reason for the conversion to HTTP_CONTENT_TYPE. What's the best way to fix this?

Rack::Utils.parse_nested_query must be used to parse query strings

Rack uses its parse_nested_query method to parse query strings, not parse_query: http://github.com/chneukirchen/rack/blob/master/lib/rack/request.rb#L265

Rack::Test uses the later: http://github.com/brynary/rack-test/blob/master/lib/rack/test.rb#L178

As the result of this inconsistency, query strings like 'a=1&a=2' are parsed to {:a => ['1', '2']} when testing with Rack::Test, but to {:a => '2'} when running the application with Rack (An explanation of why this approach has been chosen for Rack can be found here: http://groups.google.com/group/rack-devel/browse_thread/thread/61e0cfbfa0dd8dbd/c42e55d2cb6866dd?lnk=gst)

This patch fixes the issue: http://gist.github.com/587525

Thanks

Rack::Test's build_nested_query does not correlate with Rack's parse_nested_query for array of hashes

Hi,

Thanks for this awesome library!

It seems that the conversion of arrays of hashes does not match with Rack's actual behaviour.

here's a spec that shows the issue. I basicallu reversed the direction of one of your existing specs for build_nested_query.

(to be added here: http://github.com/brynary/rack-test/blob/master/spec/rack/test/utils_spec.rb#L51)

    it "arrays of hashes conversion be correlate of Rack's parse_nested_query" do
      Rack::Utils.parse_nested_query("a[][b]=2&a[][c]=3").should == {"a" => [{"b" => "2"}, {"c" => "3"}]}
    end

The result of the spec is this:

expected: {"a"=>[{"b"=>"2"}, {"c"=>"3"}]},
     got: {"a"=>[{"b"=>"2", "c"=>"3"}]} (using ==)

Before I proceed with filing a bug against Rack, I'd like to know what you think the expected behaviour is.

My situation is that a cuke doesn't work with Rack::Test (the failure being to do with param parsing) but does work using the selenium driver, and in the actual app. This leads me to believe something is going screwy with Rack::Test...

Cheers,
Ian

encoding_aware in rack-test 0.5.5

In which ruby versions does String#encoding_aware? work? It was introduced in 0.5.5 and seems to break under 1.9.1-p378 and 1.8.7-p302. I'm running via cucumber and I suddenly had these "undefined method `encoding_aware?' for #String:0x5957c84 (NoMethodError)" errors that I traced back to the new rack-test code.

Patch: Setting default request host for sessions.

I've got an app that uses hostnames to separate customers, and couldn't find an easy way to set the default_host for MockSession.

Googling showed that a number of other people have had the same problem, so I implemented a host-setter method, as well as added delegation for cookie_jar for easier cookie-related testing. The net result is two new methods for Rack::Test::Methods, and no changes to existing functionality.

I want to contribute the changes back, but I'm not sure how. I can just submit a patch, but it would be nice to include additional test cases covering the new functionality. Of course, I can fork the project, but I don't want to create Yet Another Copy Of Rack::Test For People To Choose From.

So, what should I do...?

gemspec file and spec_helper don't agree on required version

The gemspec file lists that >rack-1.0.0 is required, but the spec_helper tries to load ~>1.0.0.

I've just ran the specs against rack 1.1.0 and from other bug reports and patches it seems that rack 1.1.0 is also supported, so probably the requirement in the spec_helper should be fixed? In any case it would be nice if both requirements matched.

rack-test/MiniTest matchers?

I use rack-test and MiniTest religiously to functional and integration test my rack apps. For the most part it's a lot of parsing JSON and then comparing or inspecting hashes. But one thing I do in every test is check the response status (code). I'm constantly writing assert last_response.ok?, or since rack only provides helper methods for the most common response statuses, more often I'm comparing directly against integers, e.g. assert_equal last_response.status, 401. I got tired of the inconsistency of checking helpers and integers, so I eventually stopped asserting the helpers altogether. Then I moved to MiniTest's spec-style, but had to continue using the old/normal-style assertions mixed in with the spec-style, which I really didn't like. So I wrote my own little helpers gem brandonweiss/rack-minitest to add spec-style MiniTest matchers to rack-test for checking response statuses, like so.

This works fine, but I know so many people that do this themselves already, I'm wondering if there isn't some way to get official support for this, although I don't really know what that would look like, hence this thread.

Would it make sense for rack-test to be aware of MiniTest? I can certainly see arguments for and against. Or does it make sense to maintain a separate gem a bridge between the two that other people can use, like I've been doing?

OAuth authorisation header converted to HTTP_AUTHORIZATION

OAuth2 uses an authorisation header similar to digest authentication. The header is typically of the form:

Authorization: OAuth #{token}

You can see this was implemented in the OAuth2 gem in this commit.

If you use #header within Rack::Test::Methods to try to set the Authorize header authorisation won't work due to the key being rewritten. Perhaps #header could take an optional third argument, which explicitly preserves the key passed?

Please release 0.6.3

I am looking to use some of the env features now available in master, but not available in 0.6.2. Could you do a version bump for those features, added about a year ago now?

Problem with rack_mock_session.cookie_jar

I'm including Rack::Test::Methods. After doing a request I do

rack_mock_session.cookie_jar.to_hash

But can't get the actual session that is set in my Sinatra app (it's sid). What I get is

{"rack.session"=>"BAh7BjoIc2lkSSI9RTlGWU5ndkw2M1psU01FcW1rQ2RWTnFsV1ppQkt6N3pt\nM05IRzBSSHIreVdLMDJJS2pSNFRRPT0GOg1lbmNvZGluZyINVVMtQVNDSUk=\n"}

Performing a base 64 decode I get

{"rack.session"=>"x04\b{\x06:\bsidI\"=E9FYNgvL63ZlSMEqmkCdVNqlWZiBKz7zm\x9C\xCD9!\x1C\xC1I!\xC8\xAD\xE5],\xC0\xC9%-\xA9H\xD1QD\xF4\xF4\x18\xE85\x95\xB9\x8D\xBD\x91\xA5\xB9\x9C\x885UL\xB5\x05M\r%$"}

I can see my sid cookie in there. Why is this only delivered like this? How can I get a hold of the actual session?

How to pass JSON Data via POST?

I'm using Rack::Test to test my app and need to test posting of data via AJAX. I've had no issues doing this with GET requests and AJAX but for POST I just can't get it to work.

My test looks like:

describe 'POST /user/' do
  include Rack::Test::Methods
  it 'must allow user registration with valid information' do
    post '/user', {
      username: 'test_reg',
      password: 'test_pass',
      email: '[email protected]'
    }.to_json, {"CONTENT_TYPE" => 'application/json', "HTTP_X_REQUESTED_WITH" => "XMLHttpRequest"}
    last_response.must_be :ok?
    last_response.body.must_match 'test_reg has been saved'
  end
end

Note I've also tried this by passing the hash and not the to_json string.

Is what I'm trying to do possible?

(FYI I have also posted this as a question on Stackoverflow).

error when using digest with parameters

I'm using digest authentication in my app and when writing test it seems I can't use get parameters because Rack::Auth::Digest::MD5#call does

if !auth.digest? || !auth.correct_uri? || !valid_qop?(auth)
  return bad_request
end

and auth.correct_uri is

def correct_uri?
  request.fullpath == uri
end

and when I call get '/users', 'limit' => '1' auth.request.fullpath is /users?limit=1 but auth.uri is /users so the request fail with an http 400, it seems to comes from Rack::Test::Session#process_request where we parse the uri but I'm not sure of it

see https://github.com/parisrb/httpcron/blob/test-params/test/admin_params_test.rb for a test that show the error

Basic auth does not set headers

Not quite sure if it's an issue or me doing something wrong.
I define my Cucumber (Capybara + Rack::Test as web driver are used) step like this :

When /log in with (.+):(.+)$/ do |username, password|
  basic_authorize(username, password) #or just authorize(username, password)
end

In my controller before_filter method I log request header like this:

Rails.logger.info "#{request.headers['HTTP_AUTHORIZATION'].inspect}" 

Logger outputs nil.

If I change my step definition to:

When /log in with (.+):(.+)$/ do |username, password|
  page.driver.browser.basic_authorize(username, password)
end

Auth works fine.

Gem versions used:
capybara (1.1.1)
cucumber (1.1.0)
cucumber-rails (1.1.0)
rack (1.3.3)
rack-test (0.6.1)

Maybe it's cucumber/capybara issue and not a Rack::Test problem ?

Posting an array of uploaded files

Hi,

Thanks so much for Rack::Test; it's an incredibly useful library for me.

I think I might have uncovered a bug. I'd like to be able to specify an array of file uploads as params to a post request:

foo = Rack::Test::UploadedFile.new('foo.txt', 'text/plain')
bar = Rack::Test::UploadedFile.new('bar.txt', 'text/plain')

post "photos", :photo => { :file => [foo, bar]}

But in the controller, I receive the following params:

{"photo"=>{"file"=>[{"foo"=>"", "bar"=>""}]}, "action"=>"create", "controller"=>"photos"}

When posting a single file, the file is available in the params, as expected:

{"photo"=>{"file"=>#<File:/var/folders/QR/QR1Z8LNdGlaaW1vRT-ls2E+++TI/-Tmp-/RackMultipart20100322-9449-1o9a6i1-0>}, "action"=>"create", "controller"=>"photos"}

I'm happy to try a patch, but thought I'd ask whether I'm doing something stupid first!

Thanks very much.

Rack-test should ignore the first leading newline inside textarea tag

Rails recently introduced a newline after opening <textarea> tag (rails/rails#4000). All browsers ignore this newline.

But rack-test does not. So if the test opens edit page with textarea, and clicks 'Save', then an additional trailing newline is added to the value, sent to the controller and saved to the DB.

The proof app is here: https://github.com/khustochka/newline_test

It has two integration tests, one driven with Selenium, another with rack-test. The first passes, the second fails.

get with missing slash and cookies

I was using capybara to test my application and it was calling Rack::Test#get with http://www.doorkeeper.jp. As this did not include a trailing slash, cookies were not being set (as uri.path was nil, which doesn't match the regex), although the request otherwise responded normally. I don't want anyone else to go through the debugging headache, so it would be nice to fix this. Is RackTest the appropriate place to fix this? If so, what is your recommended approach (warning, exception, add the slash, etc)?

Deadlock; Recursive Locking Problem

When attempting to test a view using Cucumber that contains the javascript_include_tag helper I get the following error,

Attempt to unlock a mutex which is not locked (ThreadError)

However after I comment out the helper all is well. Any suggestions as to what is causing this problem?

Brian

release 0.6.2

We'd really like to use the PATCH method that's on master but not released in any gems. It's been more than year since the last release and the additions that have been added seem relatively harmless.

Is there any reason to not release 0.6.2?

Please provide a public API to access the request headers that have been set

rack-test provides the header method that sets request headers, but there's no corresponding headers method to query what headers have been set. It would be really nice if such a method existed. Currently, we're doing current_session.instance_variable_get(:@headers) to get access to the headers, which feels like a brittle hack.

Escape only double-quote but no other ASCII char in multipart uploaded filenames

Please see related discussion and research in rack/rack#323.

RFC 1867 does not say to escape ASCII chars in filenames in multipart uploads using %XX (the URL-encoding scheme from RFC 1738). No browser I tried (see list in rack/rack#323) escapes ASCII filename characters in this way so Rack shouldn't either, with one exception: it could emulate either Firefox or Webkit by escaping only the double-quote character.

  • Firefox escapes double-quote as \".
  • Webkit escapes double-quote as %22.

All other ASCII characters--including single quote ('), percent (%), ampersand (&), question mark (?), backslash (\)--should be passed straight through without encoding.

Background: this bit me because rack-test escapes the entire filename using RFC 1738 encoding and rack unescapes the filename using the same method. I had a passing test in my app to verify that special characters were allowed in filenames and it was passing, but later I discovered that in a real browser with a % sign in the filename it raised an error in rack. The real browser did not escape the % sign but rack tried to unescape it. If rack-test were behaving more like a real browser and not escape percent signs, my test would have told me something was wrong.

The correct fix is for both rack-test and rack to be updated (which is why rack/rack#323 was filed along with this one).

Thanks!

cc @raggi

params and :input appear to be mutually exclusive

I was trying to use rack-test to perform a PUT with an api_key in the params and JSON in the input.

put "/data", {api_key: user.api_key}, {input: data.to_json, content_type: 'application/json'}

However, it appears the way env_for is implemented, it's not possible to mix params with :input.

Rack Test redirects not working properly

I'm currently developing an app where many redirects occur.
The redirects are working properly, tests are working too for redirects which happens in "namespace"

map '/' 

But for tests where redirects occur in another namespace (eg.: map '/admin') the redirect is broken, last_response after follow_redirect! returns route not found

Created a repo where the error is reproduced: https://github.com/Benny1992/rack_redirect_bug

Run the tests with:

cd test
ruby admin_controller_test.rb
ruby root_controller_test.rb

honor SERVER_PORT

currently, rack test does not honor the "SERVER_PORT" option.

Here's how the behavior should work:

describe "request" do
  it "allows SERVER_PORT to be set" do
    request "/", "SERVER_PORT" => "9000"
    last_request.port.should == 9000
    last_request.env["SERVER_PORT"].should == "9000"
  end

  it "honors a port set in HTTP_HOST" do
    request "/", "HTTP_HOST" => "example.org:9000"
    last_request.port.should == 9000
    last_request.env["HTTP_HOST"].should == "example.org:9000"
  end

  it "honors a port set via the Host header" do
    header "Host", "example.org:9000"
    request "/"
    last_request.port.should == 9000
    last_request.env["HTTP_HOST"].should == "example.org:9000"
  end
end

Use CI for testing.

Hello @brynary. It will be nice to add some CI (for example Travis). I just fixed some warning in specs for MRI 2.0 and it will be nice to prove it in some CI links.

calling tempfile on Rack::Test::UploadedFile fails

I have a monkyepatch:

# Monkeypatch fixing missing tempfile handler in rack-test
class Rack::Test::UploadedFile
  def tempfile
    @tempfile
  end
end

Because I call tempfile on an uploaded file in an application.

This also mignt indicate that there is a problem with the real uploaded file in Rails 3.1.1, since it does not accept a call to closed? and tempfile does.

Sending raw octet-streams with Rack-Test

I am trying to emulate this behaviour:

curl -X POST "http://localhost:8080/test/uniqueuuid1337" \
     --data-binary "@a_small_image.jpg" \
     -v \

When I do this, I can actually read the image-file from the request body like this:

temp_file = Tempfile.new("pict")
request.body.rewind
temp_file.write(request.body.read)
temp_file.seek(0)
temp_file

But when I try to do the same with Rack-Test it fails in all kind of strange ways.

it "should upload an image" do
  file = File.open(File.expand_path("spec/images/a_small_image.jpg"))
  post "https://test.com/test/uniqueuuid1337", file
  # NoMethodError: undefined method `length' for #<File:0x007fb194a62578>
  # from /Users/kaspergrubbe/.rbenv/versions/2.1.0/lib/ruby/gems/2.1.0/gems/rack-
  #1.5.2/lib/rack/mock.rb:135:in `env_for'
end
it "should upload an image" do
  file = File.open(File.expand_path("spec/images/a_small_image.jpg"))
  post "https://test.com/test/uniqueuuid1337", file.read
  # ArgumentError: invalid byte sequence in UTF-8
  # from /Users/kaspergrubbe/.rbenv/versions/2.1.0/lib/ruby/gems/2.1.0/gems/rack-
  #1.5.2/lib/rack/utils.rb:104:in `normalize_params'
end
it "should upload an image" do
  file = File.open(File.expand_path("spec/images/a_small_image.jpg"))
  post "https://test.com/test/uniqueuuid1337", Rack::Test::UploadedFile.new("spec/images/a_small_image.jpg", "application/octet-stream")
  # ArgumentError: invalid byte sequence in UTF-8
  # from /Users/kaspergrubbe/.rbenv/versions/2.1.0/lib/ruby/gems/2.1.0/gems/rack-
  #1.5.2/lib/rack/utils.rb:104:in `normalize_params'
end

Is there any way to send the same kind of request like curl does?

Params hash leaves keys available as symbols

If a params hash is passed in with symbols for keys, the resulting params object inside the app can access the values using either the symbol or the string. Rack makes these values accessible through strings only.

The following test, therefore, passes when it should fail:

# in test
it "should send an email" do
  post '/email', to: '[email protected]'
  last_response.status.should == 204
end

# in sinatra app.rb
post '/email' do
  #snip
  begin
    @mailer.send params.clone.freeze
    halt 204
  rescue ArgumentError
    halt 422
  end
end

# in mailer.rb
def send(params)
  raise ArgumentError unless params.has_key? :to
  #snip
end

Middleware that consumes rack.input clears out params?

I'm testing a Grape API through Rack::Test standalone (without Rails). It appears that when my Rack middleware consumes env['rack.input'] the grape API will see the params hash as being empty.

My midleware has code like this:

request_params = env['rack.input'].read

When I turn the same spec into a Rails request spec, it works just fine. I also know when calling the API from the command line (curl), I can get both my middleware and the request to process correctly, so there is some issue specific to use Rack::Test.

I've read through the Rack::Test code, but I'm not sure why consuming the rack.input seems to destroy it. Perhaps it's a different type of object in the mock request than it would normally be in real life, such that calling #read on env['rack.input'] causes the buffer to become empty?

Any insight would be appreciated. I am more than willing to put in some time doing a pull request if you could help me look in the right direction. Thanks!

undefined method `parse' for Time:Class

When running capybara using rack-test, I'm getting this error:

undefined method parse' for Time:Class # /home/lunks/.rvm/gems/ruby-1.9.2-preview3@r3/gems/rack-test-0.5.4/lib/rack/test/cookie_jar.rb:58:inexpires'
# /home/lunks/.rvm/gems/ruby-1.9.2-preview3@r3/gems/rack-test-0.5.4/lib/rack/test/cookie_jar.rb:63:in expired?' # /home/lunks/.rvm/gems/ruby-1.9.2-preview3@r3/gems/rack-test-0.5.4/lib/rack/test/cookie_jar.rb:82:inmatches?'
# /home/lunks/.rvm/gems/ruby-1.9.2-preview3@r3/gems/rack-test-0.5.4/lib/rack/test/cookie_jar.rb:167:in block in hash_for' # /home/lunks/.rvm/gems/ruby-1.9.2-preview3@r3/gems/rack-test-0.5.4/lib/rack/test/cookie_jar.rb:166:ineach'
# /home/lunks/.rvm/gems/ruby-1.9.2-preview3@r3/gems/rack-test-0.5.4/lib/rack/test/cookie_jar.rb:166:in hash_for' # /home/lunks/.rvm/gems/ruby-1.9.2-preview3@r3/gems/rack-test-0.5.4/lib/rack/test/cookie_jar.rb:143:infor'
# /home/lunks/.rvm/gems/ruby-1.9.2-preview3@r3/gems/rack-test-0.5.4/lib/rack/mock_session.rb:28:in request' # /home/lunks/.rvm/gems/ruby-1.9.2-preview3@r3/gems/rack-test-0.5.4/lib/rack/test.rb:207:inprocess_request'
# /home/lunks/.rvm/gems/ruby-1.9.2-preview3@r3/gems/rack-test-0.5.4/lib/rack/test.rb:57:in get' # /home/lunks/.rvm/gems/ruby-1.9.2-preview3@r3/gems/rack-test-0.5.4/lib/rack/test.rb:154:infollow_redirect!'
# /home/lunks/.rvm/gems/ruby-1.9.2-preview3@r3/gems/capybara-0.3.9/lib/capybara/driver/rack_test_driver.rb:249:in block in follow_redirects!' # /home/lunks/.rvm/gems/ruby-1.9.2-preview3@r3/gems/capybara-0.3.9/lib/capybara/driver/rack_test_driver.rb:248:intimes'
# /home/lunks/.rvm/gems/ruby-1.9.2-preview3@r3/gems/capybara-0.3.9/lib/capybara/driver/rack_test_driver.rb:248:in follow_redirects!' # /home/lunks/.rvm/gems/ruby-1.9.2-preview3@r3/gems/capybara-0.3.9/lib/capybara/driver/rack_test_driver.rb:204:inprocess'
# /home/lunks/.rvm/gems/ruby-1.9.2-preview3@r3/gems/capybara-0.3.9/lib/capybara/driver/rack_test_driver.rb:85:in click' # /home/lunks/.rvm/gems/ruby-1.9.2-preview3@r3/gems/capybara-0.3.9/lib/capybara/session.rb:46:inclick'
# /home/lunks/.rvm/gems/ruby-1.9.2-preview3@r3/gems/capybara-0.3.9/lib/capybara/dsl.rb:55:in click' # ./spec/integration/sign_in_guest_spec.rb:28:inblock (3 levels) in <top (required)>'

I realize it should be solved by requiring 'time' as it's being done now on cookie_jar.rb, but the error is still ocurring. Using Ruby 1.9.2 with Rails 3 and RSpec 2.

build_parts() doesn't handle multipart forms with multiple fields with the same name correctly

When building a multipart request, with multiple fields of the same name (specifically from Capybara) which has parameters formatted in the input hash like:

{'name' => 'John', 'language[]' => ['en', 'de']}

Rack-test incorrectly formulates the request with language[] as one field with the value set to the to_s value of the Ruby array (i.e.):

Content-Disposition: form-data; name="language[]"

["en", "de"]

instead of:

Content-Disposition: form-data; name="language[]"

en

Content-Disposition: form-data; name="language[]"

de

This causes Rails to parse the form inputs incorrectly.

I have created the following patch which fixes the issue on my side, but I am unsure of how this affects other functionality:

http://pastebin.com/jDPpFXp0

POST a JSON string to the Rack application

Is this possible? I need to test an API using JSON as the payload, but it looks like Rack::Test always assumes it's simulating a form submission. Do you know any way to make this work?

Header Capitalization and Underscorizing

Bryan,

First thanks for all you awesome work on Rack::Test!

We are using Rack::Test to test the interplay of several rack apps. We've been using some custom headers, similar to X-Custom-Header. Our code expects that the request env should contain env['HTTP_X_CUSTOM_HEADER']. Looking through Rack::Test, we saw that headers are not renamed when Rack::Test::Session#header('X-Custom-Header','value') was used.

Is this intentional?

According to Google, all web servers send headers in this uppercase, underscorized form to CGI apps. Is this something Rack::Test should emulate or should we roll our own solution?

Thanks!

-Derek

rack test is rejecting cookie set to subpath

I believe rack tests's cookie validation is too strict, in https://github.com/brynary/rack-test/blob/master/lib/rack/test/cookie_jar.rb#L77 it requires that the cookie's path attribute matches the request's path. I.e. it restricts the cookie path based on the requests's path and doesn't allow arbitrary paths. But I can't find any mention of that in the RFC (http://tools.ietf.org/id/draft-ietf-httpstate-cookie-23.txt).
I tested this also with Chrome, it allows to set cookies with arbitrary paths.
Thus I think the path check should be removed.

Rack::Test::CookieJar cannot handle multiple 'path' values in the Cookie.

While testing a Rack middleware that proxies requests, I noticed that rack-test was giving me the following exception:

/home/hal/.rvm/gems/ruby-1.9.2-p0/gems/rack-test-0.5.4/lib/rack/test/cookie_jar.rb:53:in `path': undefined method `strip' for #<Array:0x0000000377c4e8> (NoMethodError)
from /home/hal/.rvm/gems/ruby-1.9.2-p0/gems/rack-test-0.5.4/lib/rack/test/cookie_jar.rb:77:in `valid?'
from /home/hal/.rvm/gems/ruby-1.9.2-p0/gems/rack-test-0.5.4/lib/rack/test/cookie_jar.rb:128:in `block in merge'
from /home/hal/.rvm/gems/ruby-1.9.2-p0/gems/rack-test-0.5.4/lib/rack/test/cookie_jar.rb:126:in `each'
from /home/hal/.rvm/gems/ruby-1.9.2-p0/gems/rack-test-0.5.4/lib/rack/test/cookie_jar.rb:126:in `merge'
from /home/hal/.rvm/gems/ruby-1.9.2-p0/gems/rack-test-0.5.4/lib/rack/mock_session.rb:35:in `request'
from /home/hal/.rvm/gems/ruby-1.9.2-p0/gems/rack-test-0.5.4/lib/rack/test.rb:207:in `process_request'
from /home/hal/.rvm/gems/ruby-1.9.2-p0/gems/rack-test-0.5.4/lib/rack/test.rb:57:in `get'
from /vault/1/code/ronin/ronin-web/spec/web/middleware/proxy_spec.rb:29:in `block (2 levels) in <top (required)>'

The problem stems from CookieJar#path assuming the path option will always be a String:

  # :api: private
  def path
    @options["path"].strip || "/"
  end

The path option is originally generated by Rack::Utils#parse_query, which will return an Array if query params are repeated:

include Rack::Utils

parse_query("csrf_id=8d0c781f207dfcc0e8db55bd467b01e0; path=/, _github_ses=BAh7BzoRbG9jYWxlX2d1ZXNzMCIKZmxhc2hJQzonQWN0aW9uQ29udHJvbGxlcjo6Rmxhc2g6OkZsYXNoSGFzaHsABjoKQHVzZWR7AA%3D%3D--e10506e0f6935897cafe4f56774e20aa35e579a5; path=/; expires=Wed, 01 Jan 2020 08:00:00 GMT; HttpOnly")['path']
# => ["/, _github_ses=BAh7BzoRbG9jYWxlX2d1ZXNzMCIKZmxhc2hJQzonQWN0aW9uQ29udHJvbGxlcjo6Rmxhc2g6OkZsYXNoSGFzaHsABjoKQHVzZWR7AA==--e10506e0f6935897cafe4f56774e20aa35e579a5", "/"]

Getting errors from the cookie jar with Rails 2.3.8 and rack 1.1

I'm using rack-test in a rails app--both through cucumber/capybara and also in some standalone specs for the application's API. I tried upgrading to Rails 2.3.8 today (which includes an upgrade to rack 1.1), but I'm getting tons of errors like these:

undefined method `downcase' for nil:NilClass
/Users/myronmarston/code/Cuponice/.bundle/gems/activesupport-2.3.8/lib/active_support/whiny_nil.rb:52:in `method_missing'
/Users/myronmarston/code/Cuponice/.bundle/gems/rack-test-0.5.3/lib/rack/test/cookie_jar.rb:29:in `replaces?'
/Users/myronmarston/code/Cuponice/.bundle/gems/rack-test-0.5.3/lib/rack/test/cookie_jar.rb:130:in `<<'
/Users/myronmarston/code/Cuponice/.bundle/gems/rack-test-0.5.3/lib/rack/test/cookie_jar.rb:129:in `reject!'
/Users/myronmarston/code/Cuponice/.bundle/gems/rack-test-0.5.3/lib/rack/test/cookie_jar.rb:129:in `<<'
/Users/myronmarston/code/Cuponice/.bundle/gems/rack-test-0.5.3/lib/rack/test/cookie_jar.rb:124:in `merge'
/Users/myronmarston/code/Cuponice/.bundle/gems/rack-test-0.5.3/lib/rack/test/cookie_jar.rb:122:in `each'
/Users/myronmarston/code/Cuponice/.bundle/gems/rack-test-0.5.3/lib/rack/test/cookie_jar.rb:122:in `merge'
/Users/myronmarston/code/Cuponice/.bundle/gems/rack-test-0.5.3/lib/rack/mock_session.rb:35:in `request'
/Users/myronmarston/code/Cuponice/.bundle/gems/rack-test-0.5.3/lib/rack/test.rb:207:in `process_request'
/Users/myronmarston/code/Cuponice/.bundle/gems/rack-test-0.5.3/lib/rack/test.rb:57:in `get'

I've done some digging, and the reason for these errors is that CookieJar#merge is receiving a raw_cookies string like:

geography_id=4; path=/; expires=Mon, 25-May-2020 16:24:40 GMT

_cuponice_session=BAh7BjoPc2Vzc2lvbl9pZCIlZDg4M2Y4ZjYyNGI3ZjdkN2NjOTFkOTc3NDFmM2I2NzI%3D--208977a32d3a7b79904dd0f6144ea01da60c26e6; path=/; HttpOnly

This includes two newline characters in a row, and the method splits on newlines. I wind up with some blank cookies ("") and the code doesn't handle them well.

Is there a bug in rack 1.1 or rails 2.3.8 that's causing the extra newline? Or should rack-test be updated to handle the extra newlines?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.