The Basecamp API has released. I am glad to see this because it means we can improve our use of the tools by creating a different interface to the data when necessary.
Thankfully, the API is XML over HTTP, which has proven to be a pragmatic and useful approach for us at Vitalsource.
A cool bit of code for accepting XML/YAML in a REST API.
UPDATE: Here’s a quick and dirty example:
app/controllers/foo_controller.rb
class FooController < RestController
def debug
end
end
app/controllers/rest_controller.rb
class RestController < ActionController::Base
before_filter :slurp_params
# Extract the parameters from the XML or YAML HTTP POST.
def slurp_params
return unless request.post?
slurp_method = "slurp_xml"
slurp_method = "slurp_#{request.post_format}" if request.post_format
if respond_to?(slurp_method)
send(slurp_method)
else
render_error "you suck"
end
end
# Extract parameters from posted YAML
def slurp_yaml
yaml = YAML.load(@request.raw_post)
@params.merge! yaml
end
# Extract parameters from posted XML
def slurp_xml
xml = XmlSimple.xml_in(@request.raw_post, 'ForceArray' => false)
@params.merge! xml
end
def render_error(message)
string = "<?xml version="1.0" encoding="UTF-8"?>\n<response>\n<error>1</error>\n<message>#{ message }</message>\n</response>"
render_text(string)
end
end
app/views/foo/debug.rhtml
<%="slurp_#{request.post_format}"%>
<% @params.each_pair { |key, value| %> <%=key%>: <%=value%><br /><%}%>
script/xmltest
#!/usr/bin/env ruby
require 'net/http'
h = Net::HTTP.new('localhost', 3000)
resp, data = h.post('/foo/debug', '
‘, { ‘Content-Type’ => ‘text/xml’ })
puts data
A test run:
slurp_xml
username: bob<br />action: debug<br />controller: foo<br />first_name: Bobby<br />password: bob<br />last_name: Bonez<br />
script/xmlbad (posts as an HTML Form would)
curl -X POST -d "<person username="bob" password="bob" first_name="Bobby" last_name="Bonez" />" http://localhost:3000/foo/debug
A test run:
<?xml version="1.0" encoding="UTF-8"?>
<response>
<error>1</error>
<message>you suck</message>
</response>