It says
The Slim Framework implements a version of the Rack protocol. As a
result, a Slim application can have middleware that may inspect,
analyze, or modify the application environment, request, and response
before and/or after the Slim application is invoked.
which means "something" to me. Like, it makes something to some things. Like middle in nowhere. Also it states that it is implementation of Rack protocol, something I have never heard in PHP.
Is there any practical use other than onions? What is the proper name of "middleware" in PHP?
Middlewares, in the Slim philosophy, is simply a sort of reusable and stacked hooks designed to alter the Slim environment progressively.
This is very useful - for example - when you need to authenticate an HTTP request, check if it is an AJAX request and log some data when a response is sent - this can be 3 separate middlewares.
The Rack protocol simply refers to the technology that inspired the author to build the Slim middlewares.
Related
I have a Rails application with Capybara for feature specs. I have some code that results in a url like this /Users/brandoncc/dev/app/public/uploads/.... This is a special circumstance in the test environment. I need to modify the response body before the browser gets it. Is that possible? I need to cut off the /Users/brandoncc/dev/app/public from image urls.
You have a number of options here - the top 3 are probably
A programmable proxy like puffing-billy
Write a rack middleware class and specify to use it in your config/environments/test.rb via config.middleware.use=
Write a rack app to wrap the app under test which modifies the responses before returning them and assign that to Capybara.app
Any of those approaches should do what you want, but you may be better off just figuring out why the code is putting full paths in the URLs and fix it to use something like the rails asset helpers instead.
Reason why I ask, is because there are some crawlers that plague my rails server with invalid requests.
So, I was wondering if it's possible to ignore any URL matching a regex matcher.
Like, wp-admin.php or {{.+}} or something like that?
I'm using rails 2.3.14
You probably don't want such requests reaching rails stack, so I'd suggest offloading work to your web server. However, leveraging rack middleware maybe another viable option. You can either use 3rd party code or write your own custom handler.
I would like to use the plugin em-eventsource ( https://github.com/AF83/em-eventsource ) for server-sent events in a Rails 3.1-project. My problem is, that there is only explained how to listen on events and receive messages, but not how to fire a specific event up and send the message. I would like to produce the event in an Active Record-Observer. Am I right when I think that I have to defer a operation with EventMachine to produce this event, or how can I solve this?
And yes, it has to be Ruby on Rails. If I don't get this to work with EventMachine, I would try to bypass the whole ruby-part with node.js.
Actually I worked on this library a little with the maintainer. I think you mixed the client part with the server one. em-eventsource is a client library which you can use to consume a ServerSentEvent API, it's not meant to fire SSE.
On the server side, it quite doesn't matter whether you are using Rails or any other stack (nodejs, php…) as long as the server you are running on supports streaming. The default web server shipped with Rails does not (Webrick) but there are many others which do: Thin, Puma, Goliath…
In order to fire SSE in Rails, you would have to use both a streaming-capable server among those cited, and abide by the SSE specification. It mostly falls down to, first, responding with the proper Content-type header ("text/event-stream") so that the client (browser) knows it should hang-on, and then start streaming on the socket. That latter part is the one not easily possible as of today in Rails 3 (yet not impossible!); Rails 4 actually now supports streaming in an easy way, with a clean and simple internal API, so it's definitely coming.
In the mean time, you'd either:
mess with Rack's API in Rails (using EventMachine I guess, there are some examples in the wild)
or have it smart and make use of the streaming feature provided by Sinatra, built on top of Rack (see https://gist.github.com/1476463 for an example of Sinatra app which can be mounted in a Rails one!)
or you could use an external service such as Pusher
or leverage a entirely different stack…
A good overview: http://blog.phusion.nl/2012/08/03/why-rails-4-live-streaming-is-a-big-deal/
Maybe I'm wrong, but if IIRC Rails can't support long pooling. Rails block whole server (or thread if you have more than one running inside server) for each request and can't reuse them unless whole response was send. That's why you should setup reverse proxy (like nginx) in front of Rails application if you suspect there could be many concurrent connections - to proxy slow client requests and send them to Rails when whole request is received. It's just how Rack works, there's not much you can do about this probably.
I'm using Rack middleware that accepts some configuration that I need to change at run time. So I need the instance of its class that's currently in memory. Is there a way to do obtain it?
I would follow an other way instead.
If you are using Rails 3, you can write the Rack middleware so that it accesses the shared application configuration available at Rails::Application.config.
Otherwise, no matter which is your Rails version, you can use a configuration library (such as the simple_config gem) and keep the current configuration value in memory so that the Middleware can access it.
Last but not least, remember that Rack has a Rack::Config middleware that you can adapt to your needs.
Within my Rails application, I'd like to generate requests that behave identically to "genuine" HTTP requests.
For a somewhat contrived example, suppose I were creating a system that could batch incoming HTTP requests for later processing. The interface for it would be something like:
Create a new batch resource via the usual CRUD methodology (POST, receive a location to the newly created resource).
Update the batch resource by sending it URLs, HTTP methods, and data to be added to the collection of requests it's supposed to later perform in bulk.
"Process" the batch resource, wherein it would iterate over its collection of requests (each of which might be represented by a URL, HTTP method, and a set of data), and somehow tell Rails to process those requests in the same way as it would were they coming in as normal, "non-batched" requests.
It seems to me that there are two important pieces of work that need to happen to make this functional:
First, the incoming requests need to be somehow saved for later. This could be simply a case of saving various aspects of the incoming request, such as the path, method, data, headers, etc. that are already exposed as part of the incoming request object within a controller. It would be nice if there was a more "automatic" way of handling this--perhaps something more like object marshaling or serialization--but the brute force approach of recording individual parameters should work as well.
Second, the saved requests need to be able to be re-injected into the rails application at a later time, and go through the same process that a normal HTTP request goes through: routing, controllers, views, etc. I'd like to be able to capture the response in a string, much as the HTTP client would have seen it, and I'd also like to do this using Rails' internal machinery rather than simply using an HTTP library to have the application literally make a new request to itself.
Thoughts?
a straight forward way of storing the arguments should be serializing the request object in your controller - this should contain all important data
to call the requests later on, i would consider using the Dispatcher.dispatch class method, that takes 3 arguments: the cgi request, the session options (CgiRequest::DEFAULT_SESSION_OPTIONS should be ok) and the stream which the output is written to
Rack Middleware
After doing a lot of investigation after I'd initially asked this question, I eventually experimented with and successfully implemented a solution using Rack Middleware.
A Basic Methodology
In the `call' method of the middleware:
Check to see if we're making a request as a nested resource of a
transaction object, or if it's an otherwise ordinary request. If it's
ordinary, proceed as normal through the middleware by making a call to
app.call(env), and return the status, headers, and response.
Unless this is a transaction commit, record the "interesting" parts of the
request's env hash, and save them to the database as an "operation" associated
with this transaction object.
If this is a transaction commit, retrieve all of the relevant operations
for this transaction. Either create a new request environment, or clone the
existing one and populate it with the values saved for the operation. Also
make a copy of the original request environment for later restoration, if
control is meant to pass through the application normally post-commit.
Feed the constructed environment into a call to app.call(env). Repeat for
each operation.
If the original request environment was preserved, restore it and make one
final call to app.call(env), returning from the invocation of `call' in the
middleware the status, headers, and response from this final call to
app.call(env).
A Sample Application
I've implemented an example implementation of the methodology I describe here, which I've made available on GitHub. It also contains an in-depth example describing how the implementation might look from an API perspective. Be warned: it's quite rough, totally undocumented (with the exception of the README), and quite possibly in violation of Rails good coding practices. It can be obtained here:
http://github.com/mcwehner/transact-example
A Plugin/Gem
I'm also beginning work on a plugin or gem that will provide this sort of interface to any Rails application. It's in its formative stages (in fact it's completely devoid of code at the moment), and work on it will likely proceed slowly. Explore it as it develops here:
http://github.com/mcwehner/transact
See also
Railscasts - Rack Middleware
Rails Guides - Rails on Rack