Skip to content

Commit

Permalink
Merge pull request #36 from nate/feature/custom-http-verbs
Browse files Browse the repository at this point in the history
Allow the creation and use of custom actions
  • Loading branch information
hanshasselberg committed Feb 14, 2013
2 parents 9ca3259 + 0ada286 commit b48f6ec
Show file tree
Hide file tree
Showing 5 changed files with 230 additions and 5 deletions.
21 changes: 16 additions & 5 deletions lib/ethon/easy/http.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
require 'ethon/easy/http/delete'
require 'ethon/easy/http/patch'
require 'ethon/easy/http/options'
require 'ethon/easy/http/custom'

module Ethon
class Easy
Expand Down Expand Up @@ -35,7 +36,7 @@ module Http
#
# @see Ethon::Easy::Options
def http_request(url, action_name, options = {})
fabricate(action_name).new(url, options).setup(self)
fabricate(url, action_name, options).setup(self)
end

private
Expand All @@ -44,13 +45,23 @@ def http_request(url, action_name, options = {})
#
# @example Return the action.
# Action.fabricate(:get)
# Action.fabricate(:smash)
#
# @param [ String ] action_name The action name.
# @param [ String ] url The url.
# @param [ String ] action_name The http action name.
# @param [ Hash ] options The option hash.
#
# @return [ Class ] The action class.
def fabricate(action_name)
Ethon::Easy::Http.const_get(action_name.to_s.capitalize)
# @return [ Easy::Ethon::Actionable ] The request instance.
def fabricate(url, action_name, options)
constant_name = action_name.to_s.capitalize

if Ethon::Easy::Http.const_defined?(constant_name)
Ethon::Easy::Http.const_get(constant_name).new(url, options)
else
Ethon::Easy::Http::Custom.new(constant_name.upcase, url, options)
end
end

end
end
end
28 changes: 28 additions & 0 deletions lib/ethon/easy/http/custom.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
module Ethon
class Easy
module Http

# This class knows everything about making requests for custom HTTP verbs.
class Custom
include Ethon::Easy::Http::Actionable
include Ethon::Easy::Http::Postable

def initialize(verb, url, options)
@verb = verb
super(url, options)
end

# Setup easy to make a request.
#
# @example Setup.
# custom.set_params(easy)
#
# @param [ Easy ] easy The easy to setup.
def setup(easy)
super
easy.customrequest = @verb
end
end
end
end
end
176 changes: 176 additions & 0 deletions spec/ethon/easy/http/custom_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,176 @@
require 'spec_helper'

describe Ethon::Easy::Http::Custom do
let(:easy) { Ethon::Easy.new }
let(:url) { "http://localhost:3001/" }
let(:params) { nil }
let(:form) { nil }
let(:custom) { described_class.new("PURGE", url, {:params => params, :body => form}) }

describe "#setup" do
context "when nothing" do
it "sets url" do
custom.setup(easy)
expect(easy.url).to eq(url)
end

it "makes a custom request" do
custom.setup(easy)
easy.perform
expect(easy.response_body).to include('"REQUEST_METHOD":"PURGE"')
end
end

context "when params" do
let(:params) { {:a => "1&"} }

it "attaches escaped to url" do
custom.setup(easy)
expect(easy.url).to eq("#{url}?a=1%26")
end

context "when requesting" do
before do
easy.headers = { 'Expect' => '' }
custom.setup(easy)
easy.perform
end

it "is a custom verb" do
expect(easy.response_body).to include('"REQUEST_METHOD":"PURGE"')
end

it "does not use application/x-www-form-urlencoded content type" do
expect(easy.response_body).to_not include('"CONTENT_TYPE":"application/x-www-form-urlencoded"')
end

it "requests parameterized url" do
expect(easy.response_body).to include('"REQUEST_URI":"http://localhost:3001/?a=1%26"')
end
end
end

context "when body" do
context "when multipart" do
let(:form) { {:a => File.open(__FILE__, 'r')} }

it "sets httppost" do
easy.should_receive(:httppost=)
custom.setup(easy)
end

context "when requesting" do
before do
easy.headers = { 'Expect' => '' }
custom.setup(easy)
easy.perform
end

it "returns ok" do
expect(easy.return_code).to eq(:ok)
end

it "is a custom verb" do
expect(easy.response_body).to include('"REQUEST_METHOD":"PURGE"')
end

it "uses multipart/form-data content type" do
expect(easy.response_body).to include('"CONTENT_TYPE":"multipart/form-data')
end

it "submits a body" do
expect(easy.response_body).to match('"body":".+"')
end

it "submits the data" do
expect(easy.response_body).to include('"filename":"custom_spec.rb"')
end
end
end

context "when not multipart" do
let(:form) { {:a => "1&b=2"} }
let(:encoded) { "a=1%26b%3D2" }

it "sets escaped copypostfields" do
easy.should_receive(:copypostfields=).with(encoded)
custom.setup(easy)
end

it "sets postfieldsize" do
easy.should_receive(:postfieldsize=).with{ |value| expect(value).to be(encoded.bytesize) }
custom.setup(easy)
end

context "when requesting" do
before do
easy.headers = { 'Expect' => '' }
custom.setup(easy)
easy.perform
end

it "returns ok" do
expect(easy.return_code).to eq(:ok)
end

it "is a custom verb" do
expect(easy.response_body).to include('"REQUEST_METHOD":"PURGE"')
end

it "uses multipart/form-data content type" do
expect(easy.response_body).to include('"CONTENT_TYPE":"application/x-www-form-urlencoded')
end

it "submits a body" do
expect(easy.response_body).to match('"body":"a=1%26b%3D2"')
end

it "submits the data" do
expect(easy.response_body).to include('"rack.request.form_hash":{"a":"1&b=2"}')
end
end
end

context "when string" do
let(:form) { "{a: 1}" }

context "when requesting" do
before do
easy.headers = { 'Expect' => '' }
custom.setup(easy)
easy.perform
end

it "returns ok" do
expect(easy.return_code).to eq(:ok)
end

it "sends string" do
expect(easy.response_body).to include('"body":"{a: 1}"')
end
end
end
end

context "when params and body" do
let(:form) { {:a => "1"} }
let(:params) { {:b => "2"} }

context "when requesting" do
before do
easy.headers = { 'Expect' => '' }
custom.setup(easy)
easy.perform
end

it "url contains params" do
expect(easy.response_body).to include('"REQUEST_URI":"http://localhost:3001/?b=2"')
end

it "body contains form" do
expect(easy.response_body).to include('"body":"a=1"')
end
end
end
end
end
6 changes: 6 additions & 0 deletions spec/ethon/easy/http_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,12 @@
end
end
end

it "makes requests with custom HTTP verbs" do
easy.http_request(url, :purge, options)
easy.perform
expect(easy.response_body).to include(%{"REQUEST_METHOD":"PURGE"})
end
end
end
end
4 changes: 4 additions & 0 deletions spec/support/server.rb
Original file line number Diff line number Diff line change
Expand Up @@ -103,4 +103,8 @@
options '/**' do
request.env.merge!(:body => request.body.read).to_json
end

route 'PURGE', '/**' do
request.env.merge!(:body => request.body.read).to_json
end
end

0 comments on commit b48f6ec

Please sign in to comment.