<?xml version="1.0" encoding="UTF-8"?>
<commit>
  <added type="array"/>
  <modified type="array">
    <modified>
      <diff>@@ -44,7 +44,8 @@ module Halcyon
     USER_AGENT = &quot;JSON/#{JSON::VERSION} Compatible (en-US) Halcyon::Client/#{Halcyon.version}&quot;.freeze
     CONTENT_TYPE = &quot;application/x-www-form-urlencoded&quot;.freeze
     DEFAULT_OPTIONS = {
-      :raise_exceptions =&gt; false
+      :raise_exceptions =&gt; false,
+      :encode_post_body_as_json =&gt; false
     }
     
     attr_accessor :uri # The server URI
@@ -103,6 +104,7 @@ module Halcyon
     # except that it is not executed in a block.
     # 
     # The differences are purely semantic and of personal taste.
+    # 
     def initialize(uri, headers = {})
       self.uri = URI.parse(uri)
       self.headers = headers
@@ -112,21 +114,36 @@ module Halcyon
       end
     end
     
+    # Sets the option to raise exceptions when the response from the server is
+    # not a +200+ response.
+    # 
     def raise_exceptions!(setting = true)
       self.options[:raise_exceptions] = setting
     end
     
+    # Sets the option to encode the POST body as +application/json+ compatible.
+    # 
+    def encode_post_body_as_json!(setting = true)
+      if self.options[:encode_post_body_as_json] = setting
+        set_content_type &quot;application/json&quot;
+      else
+        set_content_type &quot;application/x-www-form-urlencoded&quot;
+      end
+    end
+    
     #--
     # Request Handling
     #++
     
     # Performs a GET request on the URI specified.
+    # 
     def get(uri, headers={})
       req = Net::HTTP::Get.new(uri)
       request(req, headers)
     end
     
     # Performs a POST request on the URI specified.
+    # 
     def post(uri, data = {}, headers={})
       req = Net::HTTP::Post.new(uri)
       req.body = format_body(data)
@@ -134,19 +151,21 @@ module Halcyon
     end
     
     # Performs a DELETE request on the URI specified.
+    # 
     def delete(uri, headers={})
       req = Net::HTTP::Delete.new(uri)
       request(req, headers)
     end
     
     # Performs a PUT request on the URI specified.
+    # 
     def put(uri, data = {}, headers={})
       req = Net::HTTP::Put.new(uri)
       req.body = format_body(data)
       request(req, headers)
     end
     
-  private
+    private
     
     # Performs an arbitrary HTTP request, receive the response, parse it with
     # JSON, and return it to the caller. This is a private method because the
@@ -160,6 +179,7 @@ module Halcyon
     # (defined in Halcyon::Exceptions) which all inherit from
     # +Halcyon::Exceptions+. It is up to the client to handle these
     # exceptions specifically.
+    # 
     def request(req, headers={})
       # set default headers
       req[&quot;User-Agent&quot;] = USER_AGENT
@@ -171,8 +191,10 @@ module Halcyon
         req[header] = value
       end
       
-      # prepare and send HTTP request
-      res = Net::HTTP.start(self.uri.host, self.uri.port) {|http|http.request(req)}
+      # prepare and send HTTP/S request
+      serv = Net::HTTP.new(self.uri.host, self.uri.port)
+      prepare_server(serv) if private_methods.include?('prepare_server')
+      res = serv.start { |http| http.request(req) }
       
       # parse response
       # unescape just in case any problematic characters were POSTed through
@@ -192,9 +214,24 @@ module Halcyon
     
     # Formats the data of a POST or PUT request (the body) into an acceptable
     # format according to Net::HTTP for sending through as a Hash.
+    # 
     def format_body(data)
       data = {:body =&gt; data} unless data.is_a? Hash
-      Rack::Utils.build_query(data)
+      case CONTENT_TYPE
+      when &quot;application/x-www-form-urlencoded&quot;
+        Rack::Utils.build_query(data)
+      when &quot;application/json&quot;
+        data.to_json
+      else
+        raise ArgumentError.new(&quot;Unsupported Content-Type for POST body: #{CONTENT_TYPE}&quot;)
+      end
+    end
+    
+    # Sets the +CONTENT_TYPE+ to the appropriate type.
+    # 
+    def set_content_type(content_type)
+      self.class.send(:remove_const, :CONTENT_TYPE)
+      self.class.const_set(:CONTENT_TYPE, content_type.freeze)
     end
     
   end</diff>
      <filename>lib/halcyon/client.rb</filename>
    </modified>
    <modified>
      <diff>@@ -4,34 +4,10 @@ module Halcyon
   class Client
     private
     
-    def request(req, headers={})
-      # set default headers
-      req[&quot;Content-Type&quot;] = CONTENT_TYPE
-      req[&quot;User-Agent&quot;] = USER_AGENT
-      
-      # apply provided headers
-      self.headers.merge(headers).each do |(header, value)|
-        req[header] = value
-      end
-      
-      # prepare and send HTTPS request
-      serv = Net::HTTP.new(self.uri.host, self.uri.port)
+    # Sets the SSL-specific options for the Server.
+    # 
+    def prepare_server(serv)
       serv.use_ssl = true if self.uri.scheme == 'https'
-      res = serv.start {|http|http.request(req)}
-      
-      # parse response
-      body = JSON.parse(res.body).to_mash
-      
-      # handle non-successes
-      if self.options[:raise_exceptions] &amp;&amp; !res.kind_of?(Net::HTTPSuccess)
-        raise self.class.const_get(Exceptions::HTTP_STATUS_CODES[body[:status]].tr(' ', '_').camel_case.gsub(/( |\-)/,'')).new
-      end
-      
-      # return response
-      body
-    rescue Halcyon::Exceptions::Base =&gt; e
-      # log exception if logger is in place
-      raise
     end
     
   end</diff>
      <filename>lib/halcyon/client/ssl.rb</filename>
    </modified>
    <modified>
      <diff>@@ -55,7 +55,7 @@ describe &quot;Halcyon::Client&quot; do
     @client.get('/nonexistent/route')[:status].should == 404
     
     # tell it to raise exceptions
-    @client.raise_exceptions! true
+    @client.raise_exceptions!
     should.raise(Halcyon::Exceptions::NotFound) { @client.get('/nonexistent/route') }
     @client.get('/time')[:status].should == 200
   end
@@ -80,4 +80,25 @@ describe &quot;Halcyon::Client&quot; do
     response[:body].should == {'controller' =&gt; 'application', 'action' =&gt; 'returner', 'key' =&gt; &quot;%todd&quot;}
   end
   
+  it &quot;should render the POST body with the correct content type, allowing application/json is set&quot; do
+    body = {:key =&gt; &quot;value&quot;}
+    
+    # default behavior is to set the POST body to application/x-www-form-urlencoded
+    @client.send(:format_body, body) == &quot;key=value&quot;
+    @client.post('/returner', body)[:body][:key].should == &quot;value&quot;
+    
+    # tell it to send as application/json
+    @client.encode_post_body_as_json!
+    @client.send(:format_body, body).should == body.to_json
+    @client.post('/returner', body)[:body][:key].should == nil
+    # The server will not return the values from the POST body because it is
+    # not set to parse application/json values. Like your own apps, you must
+    # set it manually to accept this type of body encoding.
+    
+    # set it back to ensure that the change is reversed
+    @client.encode_post_body_as_json! false
+    @client.send(:format_body, body) == &quot;key=value&quot;
+    @client.post('/returner', body)[:body][:key].should == &quot;value&quot;
+  end
+  
 end</diff>
      <filename>spec/halcyon/client_spec.rb</filename>
    </modified>
    <modified>
      <diff>@@ -5,4 +5,9 @@ $:.unshift(Halcyon.root/'lib')
 puts &quot;(Starting in #{Halcyon.root})&quot;
 
 Thin::Logging.silent = true if defined? Thin
+
+# Uncomment if you plan to allow clients to send requests with the POST body
+# Content-Type as application/json.
+# use Rack::PostBodyContentTypeParsers
+
 run Halcyon::Runner.new</diff>
      <filename>support/generators/halcyon/templates/runner.ru</filename>
    </modified>
    <modified>
      <diff>@@ -5,4 +5,8 @@ puts &quot;(Starting in #{Halcyon.root})&quot;
 
 Thin::Logging.silent = true if defined? Thin
 
+# Uncomment if you plan to allow clients to send requests with the POST body
+# Content-Type as application/json.
+# use Rack::PostBodyContentTypeParsers
+
 run Halcyon::Runner.new</diff>
      <filename>support/generators/halcyon_flat/templates/runner.ru</filename>
    </modified>
  </modified>
  <removed type="array"/>
  <parents type="array">
    <parent>
      <id>6d6fa12b697c069ab50a350348b1a79ccd3d7572</id>
    </parent>
  </parents>
  <author>
    <name>Matt Todd</name>
    <email>chiology@gmail.com</email>
  </author>
  <url>http://github.com/mtodd/halcyon/commit/238909fc750e790d26a7bb4266b3a01679c1b59d</url>
  <id>238909fc750e790d26a7bb4266b3a01679c1b59d</id>
  <committed-date>2008-09-12T02:02:52-07:00</committed-date>
  <authored-date>2008-09-12T02:02:52-07:00</authored-date>
  <message>Set it up to have simpler expansion to support SSL etc. Made the Halcyon::Client support having the Content-TType specified for the client and formatting the body appropriately. Also expanded specs. [#61 state:resolved]</message>
  <tree>60d80689d294d97a5bf63f170d6e4f235b908ee8</tree>
  <committer>
    <name>Matt Todd</name>
    <email>chiology@gmail.com</email>
  </committer>
</commit>
