Extract some code out of the main Middleware class into a new BaseMiddleware class.
Extracted out a new rendering_started_at method to make it clearer what the "rendering_flag"
actually means.
Extract out two new methods, pdf_body and pdf_headers, into base class to simplify render_as_pdf!
Add some tests specifically for rendering_in_progress?, already_rendered?, and up_to_date?

Add a test for the Content-Type header.

Change rendering_in_progress? to return false when it would have returned nil.
Fix commented-out "should render a pdf file" test
Spell out test_file as 2 words.
Actually create an expectation from the value that valid_pdf returns.
Move test_file and valid_pdf to spec_helper.rb so that they can be reused from various test files.
Add app, main_app, and middleware_options methods to spec_helper.rb so that they can be reused from
various test files.

Enclose the definition of mock_app within a shared_context block so that we can have different
mock_app methods for different middleware test files.
Checking start_with? is simpler than matching a Regexp.
Set the tmpdir to a random, temporary dir in the tests instead of to Dir.tmpdir (which is a fixed
path like '/tmp').

This prevents intermittent test failures like this one that are caused by the file already existing
because it was leftover from the previous test run:

  1) Shrimp::Middleware matching pdf should return 503 the first time
     Failure/Error: last_response.status.should eq 503

       expected: 503
            got: 200
Add matching reader methods to Configuration for each option that already has a writer method.

Rename the misleading variable name @default_options to just @options, because the writer methods
(such as margin=) actually *modify* this hash, so they are not just the default values but rather
the current values.

Replace attr_accessor :default_options with a read-only to_h method for when you need to convert the
Configuration option to a Hash.

Add a Shrimp.config alias for Shrimp.configuration.
Change the default value for the tmpdir option to use mktmpdir (a subdirectory within /tmp like
/tmp/shrimp20131120-28880-1bll5ur) instead of just saving everything directly under /tmp
(Dir.tmpdir).

This way you can easily list or delete all shrimp-generated temp files with something like:

    rm -r /tmp/shrimp*
Rename fire_phantom to render_pdf to be more consistent with other methods like render_as_pdf and
already_rendered? that use the verb "render".
Moved the render_pdf method to BaseMiddleware so that it can be reused by both the current
middleware and other middlewares.

Added log_render_pdf_start and log_render_pdf_completion, which give useful debugging information if
config.debug is true.
Merge the options that were passed in to the middleware with the options configured in
Shrimp.config, so that you can override an option from Shrimp.config by passing in a different value
to the middleware.
Remove duplication between run and run! methods.

Change run! to simply call run and then check the @error status afterwards.
Add page_load_error and page_load_status_code methods to Phantom.
Add full response details to what rasterize.js outputs so that we can get the redirect URL, etc.

Add response and redirect_to methods to Phantom to make it easy to get at that data.

Add a .chomp to @result to get rid of the extra newline at the end.
Add a simpler middleware, SynchronousMiddleware, that runs the phantomjs command synchronously and
doesn't use any of the fancy polling that Shrimp::Middleware uses.  It also avoids showing the user
an ugly "Preparing pdf..." page, which doesn't even go away after the PDF file has been downloaded.

The caveat is that you must make sure that your web server is able to process any number of
concurrent requests (or at least enough concurrent requests that you aren't worried).  If your web
server reaches its concurrency limit and then receives a request for a .pdf resource, then when
phantomjs attempts to request the .html version of the resource, this new HTTP request will have to
wait until the server finishes some other request and is able to serve this new HTTP request.

That should generally be okay as long as most of the other requests are quick enough.  But in the
worst case, where each of the requests currently being served is a request for a .pdf resource
(which must generate an additional request for the .html request), then it will create a deadlock,
because request A blocks while waiting for request B to complete, while at the same time request B
can't complete because it is blocking while waiting for request A to finish (in the simple case
where the max concurrency is 2).

In Rails, if you are using a multi-threaded web server such as puma, then you *must* set
config.allow_concurrency = true to allow concurrent requests.  Otherwise, the Rack::Lock middleware
will prevent the 2nd request (that PhantomJS generates) from being processed until the 1st request
(for the .pdf file) has completed, which immediately creates a deadlock!