Sunday 22 December 2013

Rails Middleware Stack

3.3 Internal Middleware Stack

Much of Action Controller's functionality is implemented as Middlewares. The following list explains the purpose of each of them:
Rack::Sendfile
  • Sets server specific X-Sendfile header. Configure this via config.action_dispatch.x_sendfile_header option.
    ActionDispatch::Static
  • Used to serve static assets. Disabled if config.serve_static_assets is false.
    Rack::Lock
  • Sets env["rack.multithread"] flag to false and wraps the application within a Mutex.
    ActiveSupport::Cache::Strategy::LocalCache::Middleware
  • Used for memory caching. This cache is not thread safe.
    Rack::Runtime
  • Sets an X-Runtime header, containing the time (in seconds) taken to execute the request.
    Rack::MethodOverride
  • Allows the method to be overridden if params[:_method] is set. This is the middleware which supports the PUT and DELETE HTTP method types.
    ActionDispatch::RequestId
  • Makes a unique X-Request-Id header available to the response and enables the ActionDispatch::Request#uuid method.
    Rails::Rack::Logger
  • Notifies the logs that the request has began. After request is complete, flushes all the logs.
    ActionDispatch::ShowExceptions
  • Rescues any exception returned by the application and calls an exceptions app that will wrap it in a format for the end user.
    ActionDispatch::DebugExceptions
  • Responsible for logging exceptions and showing a debugging page in case the request is local.
    ActionDispatch::RemoteIp
  • Checks for IP spoofing attacks.
    ActionDispatch::Reloader
  • Provides prepare and cleanup callbacks, intended to assist with code reloading during development.
    ActionDispatch::Callbacks
  • Runs the prepare callbacks before serving the request.
    ActiveRecord::ConnectionAdapters::ConnectionManagement
  • Cleans active connections after each request, unless the rack.test key in the request environment is set to true.
    ActiveRecord::QueryCache
  • Enables the Active Record query cache.
    ActionDispatch::Cookies
  • Sets cookies for the request.
    ActionDispatch::Session::CookieStore
  • Responsible for storing the session in cookies.
    ActionDispatch::Flash
  • Sets up the flash keys. Only available if config.action_controller.session_store is set to a value.
    ActionDispatch::ParamsParser
  • Parses out parameters from the request into params.
    ActionDispatch::Head
  • Converts HEAD requests to GET requests and serves them as so.
    Rack::ConditionalGet
  • Adds support for "Conditional GET" so that server responds with nothing if page wasn't changed.
    Rack::ETag
  • Adds ETag header on all String bodies. ETags are used to validate cache.


API application (using ActionController::API) comes with the following controller modules by default:
  • ActionController::UrlFor: Makes url_for and friends available
  • ActionController::Redirecting: Support for redirect_to
  • ActionController::Rendering: Basic support for rendering
  • ActionController::Renderers::All: Support for render :json and friends
  • ActionController::ConditionalGet: Support for stale?
  • ActionController::ForceSSL: Support for force_ssl
  • ActionController::RackDelegation: Support for the request and response methods returningActionDispatch::Request and ActionDispatch::Response objects.
  • ActionController::DataStreaming: Support for send_file and send_data
  • AbstractController::Callbacks: Support for before_filter and friends
  • ActionController::Instrumentation: Support for the instrumentation hooks defined by ActionController (seethe source for more).
  • ActionController::Rescue: Support for rescue_from.
  • AbstractController::Translation: Support for the l and t localization and translation methods. These delegate to I18n.translate and I18n.localize.
  • ActionController::HttpAuthentication::Basic::ControllerMethods (or Digest or Token): Support for basic, digest or token HTTP authentication.
  • AbstractController::Layouts: Support for layouts when rendering.
  • ActionController::MimeResponds (and ActionController::ImplicitRender for Rails 4): Support for content negotiation (respond_torespond_with).
  • ActionController::Cookies: Support for cookies, which includes support for signed and encrypted cookies. This requires the cookie middleware.

why i love ruby?!


Saturday 14 December 2013

ruby % things

  • %r() is another way to write a regular expression.
  • %q() is another way to write a single-quoted string (and can be multi-line, which is useful)
  • %Q() gives a double-quoted string
  • %x() is a shell command
  • %i() gives an array of symbols (Ruby >= 2.0.0)

http://stackoverflow.com/questions/1274675/ruby-what-does-warray-mean

Thursday 12 December 2013

Using a WebSocket to access your CLI


➜  temp   wget http://download.websocketd.com/releases/websocketd/0.2.7/darwin_amd64/websocketd

--2013-12-13 14:53:14--  http://download.websocketd.com/releases/websocketd/0.2.7/darwin_amd64/websocketd
Resolving download.websocketd.com... 176.32.98.233
Connecting to download.websocketd.com|176.32.98.233|:80... connected.
HTTP request sent, awaiting response... 200 OK
Length: 5970144 (5.7M) [application/octet-stream]
Saving to: ‘websocketd’

100%[===========================================================>] 5,970,144    962KB/s   in 11s    

2013-12-13 14:53:27 (551 KB/s) - ‘websocketd’ saved [5970144/5970144]

➜  temp  chmod +x websocketd

Test it:
➜  temp  ./websocketd --help
websocketd (0.2.7)

websocketd is a command line tool that will allow any executable program
that accepts input on stdin and produces output on stdout to be turned into
a WebSocket server....


create an app
count.sh:
#!/bin/bash

# Count from 1 to 10, pausing for a second between each iteration.
for COUNT in $(seq 1 10); do
  echo $COUNT
  sleep 1
done
Make it executable:
$ chmod +x ./count.sh

Start the server:
➜  websockets  ./websocketd --port=8080 ./count.sh
Fri, 13 Dec 2013 14:58:11 +1100 | INFO   | server     |  | Starting WebSocket server   : ws://0.0.0.0:8080/
Fri, 13 Dec 2013 14:58:11 +1100 | INFO   | server     |  | Serving using application   : ./count.sh 


In a web-page:
var ws = new WebSocket('ws://localhost:8080/');

ws.onmessage = function(event) {
  console.log('Count is: ' + event.data);
};


bam:

function (event) { console.log('Count is: ' + event.data); }
Count is: 1 VM499:5
Count is: 2 VM499:5
Count is: 3 VM499:5
Count is: 4 VM499:5
Count is: 5 VM499:5
Count is: 6 VM499:5
Count is: 7 VM499:5
Count is: 8 VM499:5
Count is: 9 VM499:5
Count is: 10 VM499:5



Server logs:
➜  websockets  ./websocketd --port=8080 ./count.sh
Fri, 13 Dec 2013 14:58:11 +1100 | INFO   | server     |  | Starting WebSocket server   : ws://0.0.0.0:8080/
Fri, 13 Dec 2013 14:58:11 +1100 | INFO   | server     |  | Serving using application   : ./count.sh 
Fri, 13 Dec 2013 14:59:38 +1100 | ACCESS | session    | url:'http://[::1]:56042/' remote:'localhost' id:'1386907178885478031' origin:'http://www.blogger.com' | CONNECT
Fri, 13 Dec 2013 14:59:48 +1100 | ACCESS | session    | url:'http://[::1]:56042/' remote:'localhost' id:'1386907178885478031' origin:'http://www.blogger.com' command:'./count.sh' pid:'46495' | DISCONNECT


test it with --devconsole
./websocketd --port=8080 --devconsole ./count.sh

and open http://localhost:8080/


connect with an javascript WebSocket
create a file count.html:
<!DOCTYPE html>
<html>
  <head>
    <title>websocketd count example</title>
    <style>
      #count {
        font: bold 150px arial;
        margin: auto;
        padding: 10px;
        text-align: center;
      }
    </style>
  </head>
  <body>

    <div id="count"></div>

    <script>
      var ws = new WebSocket('ws://localhost:8080/');
      ws.onopen = function() {
        document.body.style.backgroundColor = '#cfc';
      };
      ws.onclose = function() {
        document.body.style.backgroundColor = null;
      };
      ws.onmessage = function(event) {
        document.getElementById('count').innerText = event.data;
      };
    </script>

  </body>
</html>
Open this page in your web-browser. It will even work if you open it directly from disk using afile:// URL.



Test it with greeter.sh


make a file greeter.sh


while read LINE
do
        echo "Hello $LINE!"
done


and run it

➜  temp  ./websocketd --port=8080 --devconsole ./greeter.sh
Fri, 13 Dec 2013 15:30:02 +1100 | INFO   | server     |  | Starting WebSocket server   : ws://0.0.0.0:8080/
Fri, 13 Dec 2013 15:30:02 +1100 | INFO   | server     |  | Developer console enable  d : http://0.0.0.0:8080/
Fri, 13 Dec 2013 15:30:02 +1100 | INFO   | server     |  | Serving using application   : ./greeter.sh 


open console

http://localhost:8080/
connect and type your name

send>> "Yannis" 
onmessage: Hello "Yannis"! 




UPDATE:
use this small example to run remote terminal commands
https://github.com/msroot/SockeTerm

read more:
https://github.com/joewalnes/websocketd/wiki/Ten-second-tutorial