I need to promote this more.

Posted: April 5th, 2010 | Author: jay | Filed under: Uncategorized | No Comments »

Curl command to test JSON posts

1
curl -i -H "Content-Type: application/json" -H "Accept: application/json" -X POST -d '{"user":{"username_or_email":"username","password":"password"}}' http://fas/test_json_post
Posted: April 4th, 2010 | Author: jay | Filed under: Code | Tags: , , , , , | No Comments »

Lost sleep over JSON and Rack::PostBodyContentTypeParser

I’ve been fighting this issue the last couple nights. I wrote earlier about how Rack::PostBodyContentTypeParser can automagically turn a posted JSON object into a Rack / Sinatra params hash. So, I wrote some tests to make sure this was the case and moved on. Well, it turns out in real life things weren’t working and I couldn’t figure out why. Everything looked cool, but the hash wasn’t getting set when I did an AJAX call in the browser – everything was empty. I looked at everything, from the server, to the JS library, to the browser, to setting different content types in prototype.js etc… UGH!

The short of it is that Rack::PostBodyContentTypeParser requires exactly application/json in order to automagically turn the posted JSON object into Rack params and prototype.js (and jquery.js were adding an encoding type of charset=UTF-8 so the entire header entry was coming across as this CONTENT_TYPE: application/json; charset=UTF-8. So, as a fix, I’m just including the Rack::PostBodyContentTypeParser in the Sinatra application with one small change. Here’s the code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
module Rack
 
  # A Rack middleware for parsing POST/PUT body data when Content-Type is
  # not one of the standard supported types, like <tt>application/json</tt>.
  #
  # TODO: Find a better name.
  #
  class PostBodyContentTypeParser
 
    # Constants
    #
    CONTENT_TYPE = 'CONTENT_TYPE'.freeze
    POST_BODY = 'rack.input'.freeze
    FORM_INPUT = 'rack.request.form_input'.freeze
    FORM_HASH = 'rack.request.form_hash'.freeze
 
    # Supported Content-Types
    #
 
    ################## turned into regex so it matches type with encoding data...
    #APPLICATION_JSON = 'application/json'.freeze
    APPLICATION_JSON = /^application\/json/.freeze
 
    def initialize(app)
      @app = app
    end
 
    def call(env)
      case env[CONTENT_TYPE]
      when APPLICATION_JSON
        env.update(FORM_HASH => JSON.parse(env[POST_BODY].read), FORM_INPUT => env[POST_BODY])
      end
      @app.call(env)
    end
 
  end
end

I tested that this worked by writing the following:

1
2
3
4
5
6
7
8
9
10
def test_post_as_json_converts_to_params
  # sanity check that post with normal params works...
  post '/test_params_as_json', :param1=>"param one"
  assert_equal last_response.body,"params[:param1]=param one"
  post '/test_params_as_json', {:param1=>"param one"}.to_json, "CONTENT_TYPE"=>"application/json"
  assert_equal last_response.body,"params[:param1]=param one"
  # this is the problem, adding a charset to the content type seems to breaks rack-contrib/post_body_content_type_parser.rb
  post '/test_params_as_json', {:param1=>"param one"}.to_json, "CONTENT_TYPE"=>"application/json; charset=UTF-8"
  assert_equal last_response.body,"params[:param1]=param one"    
end
Posted: April 4th, 2010 | Author: jay | Filed under: Code | Tags: , , , , , , , , | 4 Comments »

Maybe I’ll start embedding code from gist…

Let’s see how this looks…

Posted: April 1st, 2010 | Author: jay | Filed under: Uncategorized | No Comments »

Couldn’t get that last thing to work so keeping it simple (stupid)

This could undoubtedly be more elegant, but it’s late and I want it to work now. May take another stab at it later…

TODO: limit the content types and only allow rendering if they are ok.

Setting up a before filter:

1
2
3
4
5
6
7
before do
  # remove and grab the file extension
  request.path_info.sub! %r{\.([^\./]+)$}, ''
  @format=$1 || 'html'
  @charset=mime_type($1) || 'text/html'
  content_type @charset, :charset => 'utf-8'
end

and using a case statement:

1
2
3
4
5
6
7
8
9
10
11
get "/home" do
  case @format
  when 'html'
    @stylesheet='home.css'
    haml :home, :layout=>:layout_simple
  when 'js'
    "{'js':true}"
  else
    pass
  end
end
Posted: April 1st, 2010 | Author: jay | Filed under: Code | Tags: , , , , | No Comments »

Doing something different depending on file extension (MIME type) in Sinatra

This looks like a solution: sinatra-respond_to

Posted: March 31st, 2010 | Author: jay | Filed under: Code | Tags: , , , | No Comments »

Using Rack middleware to parse JSON

In attempting to AJAX-ize the site, I had the desire to handle JSON as if it were form post data. Queue a Rack middleware solution. rack-contrib contains a bunch of common middleware extensions, one being the horribly named PostBodyContentTypeParser. To get this working I added:

1
require 'rack/contrib'

with all of the rest of the required files.

Added:

1
use Rack::PostBodyContentTypeParser

to my application class

And went about over testing it like so:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
def test_json_creates_params_hash
  params_hash={"user"=>{"username"=>"testuser","email"=>"test@test.com","password"=>"pass1","password_confirmation"=>"pass1"}}
  post '/test_json', params_hash
  assert !last_request.params.blank?
  assert_equal params_hash, last_request.params
  assert last_response.ok?
  json_string="{\"user\":{\"password_confirmation\":\"pass1\",\"username\":\"testuser\",\"password\":\"pass1\",\"email\":\"test@test.com\"}}"
  post '/test_json', JSON(json_string)
  assert !last_request.params.blank?
  assert_equal params_hash, last_request.params
  assert last_response.ok?
  post '/test_json', json_string, "CONTENT_TYPE"=>"application/json"
  assert_equal last_request.env["CONTENT_TYPE"], "application/json"
  assert !last_request.params.blank?
  assert_equal params_hash, last_request.params
  assert last_response.ok?
end
Posted: March 30th, 2010 | Author: jay | Filed under: Code | Tags: , , , , , , , | No Comments »

AJAX-izing

Working on making the site more app-like. In doing so, found the Prototype.js-based library, LivePipe. The documentation is poor, but what little I’ve seen, I like.

Now, I’m trying to figure out how much I should “gracefully degrade” or not.

Posted: March 29th, 2010 | Author: jay | Filed under: Code | Tags: , , , , | No Comments »

Close to perfection

Posted: March 29th, 2010 | Author: jay | Filed under: Fun | Tags: , , | No Comments »

Blogging system mostly in place

Title pretty much says it all.

Posted: March 28th, 2010 | Author: jay | Filed under: Code | Tags: , | No Comments »