From eb6837670e5b984cb44a85a84368ff6ca8111487 Mon Sep 17 00:00:00 2001 From: Maxim Ivanov Date: Fri, 16 Feb 2018 18:43:10 -0500 Subject: [PATCH 1/5] handle json post requests --- .gitignore | 1 + lib/twitter/rest/request.rb | 37 +++++++++++++++++++++++++++---------- 2 files changed, 28 insertions(+), 10 deletions(-) diff --git a/.gitignore b/.gitignore index af948e388..9f1724a79 100644 --- a/.gitignore +++ b/.gitignore @@ -9,3 +9,4 @@ doc/* log/* measurement/* pkg/* +*.swp diff --git a/lib/twitter/rest/request.rb b/lib/twitter/rest/request.rb index db34abbe1..513bcf51e 100644 --- a/lib/twitter/rest/request.rb +++ b/lib/twitter/rest/request.rb @@ -14,7 +14,7 @@ class Request include Twitter::Utils BASE_URL = 'https://api.twitter.com'.freeze attr_accessor :client, :headers, :options, :path, :rate_limit, - :request_method, :uri + :request_method, :uri, :options_key alias verb request_method # @param client [Twitter::Client] @@ -25,15 +25,14 @@ class Request def initialize(client, request_method, path, options = {}) @client = client @uri = Addressable::URI.parse(path.start_with?('http') ? path : BASE_URL + path) - set_multipart_options!(request_method, options) + set_request_options!(request_method, options) @path = uri.path @options = options end # @return [Array, Hash] def perform - options_key = @request_method == :get ? :params : :form - response = http_client.headers(@headers).public_send(@request_method, @uri.to_s, options_key => @options) + response = http_client.headers(@headers).public_send(@request_method, @uri.to_s, @options_key => @options) response_body = response.body.empty? ? '' : symbolize_keys!(response.parse) response_headers = response.headers fail_or_return_response_body(response.code, response_body, response_headers) @@ -52,14 +51,32 @@ def merge_multipart_file!(options) end end - def set_multipart_options!(request_method, options) + def set_multipart_options!(options) + merge_multipart_file!(options) + @request_method = :post + @options_key = :form + @headers = Twitter::Headers.new(@client, @request_method, @uri).request_headers + end + + def set_json_options! + @options_key = :json + @request_method = :post + @headers = Twitter::Headers.new(@client, @request_method, @uri).request_headers + end + + def set_standard_options!(request_method, options) + @request_method = request_method + @options_key = @request_method == :get ? :params : :form + @headers = Twitter::Headers.new(@client, @request_method, @uri, options).request_headers + end + + def set_request_options!(request_method, options) if request_method == :multipart_post - merge_multipart_file!(options) - @request_method = :post - @headers = Twitter::Headers.new(@client, @request_method, @uri).request_headers + set_multipart_options!(options) + elsif request_method == :json_post + set_json_options! else - @request_method = request_method - @headers = Twitter::Headers.new(@client, @request_method, @uri, options).request_headers + set_standard_options!(request_method, options) end end From 14084e0b7db1e7febbdd2093ac2e45bcc2ef9fe8 Mon Sep 17 00:00:00 2001 From: Maxim Ivanov Date: Fri, 16 Feb 2018 20:05:37 -0500 Subject: [PATCH 2/5] add spec --- Gemfile | 2 +- spec/helper.rb | 1 + spec/twitter/rest/request_spec.rb | 16 ++++++++++++++++ 3 files changed, 18 insertions(+), 1 deletion(-) diff --git a/Gemfile b/Gemfile index cb1f9afd5..b3a9d347b 100644 --- a/Gemfile +++ b/Gemfile @@ -4,7 +4,7 @@ gem 'jruby-openssl', platforms: :jruby gem 'rake' gem 'yard' -group :development do +group :development, :test do gem 'pry' end diff --git a/spec/helper.rb b/spec/helper.rb index f3279d3b4..5b4acc056 100644 --- a/spec/helper.rb +++ b/spec/helper.rb @@ -15,6 +15,7 @@ require 'tempfile' require 'timecop' require 'webmock/rspec' +require 'pry' require_relative 'support/media_object_examples' diff --git a/spec/twitter/rest/request_spec.rb b/spec/twitter/rest/request_spec.rb index d13dfec7b..188a9c788 100644 --- a/spec/twitter/rest/request_spec.rb +++ b/spec/twitter/rest/request_spec.rb @@ -19,6 +19,22 @@ expect(a_post('/1.1/statuses/update.json').with(body: {status: 'Update', media_ids: '470030289822314497'})).to have_been_made end + context 'when posting JSON' do + it 'makes a proper json encoded request' do + stub_post('/1.1/json-post-endpoint.json') + .with({ + body: {test_key: 'test value'}, + headers: {content_type: 'application/json; charset=UTF-8'} + }) + .to_return({ + body: '{"success":true}', + headers: {content_type: 'application/json; charset=utf-8'} + }) + Twitter::REST::Request.new(@client, :json_post, '/1.1/json-post-endpoint.json', test_key: 'test value').perform + expect(a_post('/1.1/json-post-endpoint.json').with(body: {test_key: 'test value'})).to have_been_made + end + end + context 'when using a proxy' do before do @client = Twitter::REST::Client.new(consumer_key: 'CK', consumer_secret: 'CS', access_token: 'AT', access_token_secret: 'AS', proxy: {host: '127.0.0.1', port: 3328}) From 7334ecd37cc918f6751e5093e15baf547f1ee118 Mon Sep 17 00:00:00 2001 From: Maxim Ivanov Date: Fri, 16 Feb 2018 20:20:16 -0500 Subject: [PATCH 3/5] clean code --- lib/twitter/rest/request.rb | 58 ++------------------------- lib/twitter/rest/request_options.rb | 62 +++++++++++++++++++++++++++++ spec/twitter/rest/request_spec.rb | 8 ++-- 3 files changed, 69 insertions(+), 59 deletions(-) create mode 100644 lib/twitter/rest/request_options.rb diff --git a/lib/twitter/rest/request.rb b/lib/twitter/rest/request.rb index 513bcf51e..9a7b6beef 100644 --- a/lib/twitter/rest/request.rb +++ b/lib/twitter/rest/request.rb @@ -4,14 +4,15 @@ require 'json' require 'openssl' require 'twitter/error' -require 'twitter/headers' require 'twitter/rate_limit' require 'twitter/utils' +require 'twitter/rest/request_options' module Twitter module REST class Request include Twitter::Utils + include Twitter::REST::RequestOptions BASE_URL = 'https://api.twitter.com'.freeze attr_accessor :client, :headers, :options, :path, :rate_limit, :request_method, :uri, :options_key @@ -25,7 +26,7 @@ class Request def initialize(client, request_method, path, options = {}) @client = client @uri = Addressable::URI.parse(path.start_with?('http') ? path : BASE_URL + path) - set_request_options!(request_method, options) + create_request_options!(request_method, options) @path = uri.path @options = options end @@ -40,59 +41,6 @@ def perform private - def merge_multipart_file!(options) - key = options.delete(:key) - file = options.delete(:file) - - options[key] = if file.is_a?(StringIO) - HTTP::FormData::File.new(file, mime_type: 'video/mp4') - else - HTTP::FormData::File.new(file, filename: File.basename(file), mime_type: mime_type(File.basename(file))) - end - end - - def set_multipart_options!(options) - merge_multipart_file!(options) - @request_method = :post - @options_key = :form - @headers = Twitter::Headers.new(@client, @request_method, @uri).request_headers - end - - def set_json_options! - @options_key = :json - @request_method = :post - @headers = Twitter::Headers.new(@client, @request_method, @uri).request_headers - end - - def set_standard_options!(request_method, options) - @request_method = request_method - @options_key = @request_method == :get ? :params : :form - @headers = Twitter::Headers.new(@client, @request_method, @uri, options).request_headers - end - - def set_request_options!(request_method, options) - if request_method == :multipart_post - set_multipart_options!(options) - elsif request_method == :json_post - set_json_options! - else - set_standard_options!(request_method, options) - end - end - - def mime_type(basename) - case basename - when /\.gif$/i - 'image/gif' - when /\.jpe?g/i - 'image/jpeg' - when /\.png$/i - 'image/png' - else - 'application/octet-stream' - end - end - def fail_or_return_response_body(code, body, headers) error = error(code, body, headers) raise(error) if error diff --git a/lib/twitter/rest/request_options.rb b/lib/twitter/rest/request_options.rb new file mode 100644 index 000000000..5c46d15f7 --- /dev/null +++ b/lib/twitter/rest/request_options.rb @@ -0,0 +1,62 @@ +require 'twitter/headers' + +module Twitter + module REST + module RequestOptions + def create_request_options!(request_method, options) + if request_method == :multipart_post + create_multipart_options!(options) + elsif request_method == :json_post + create_json_options! + else + create_standard_options!(request_method, options) + end + end + + private + + def merge_multipart_file!(options) + key = options.delete(:key) + file = options.delete(:file) + + options[key] = if file.is_a?(StringIO) + HTTP::FormData::File.new(file, mime_type: 'video/mp4') + else + HTTP::FormData::File.new(file, filename: File.basename(file), mime_type: mime_type(File.basename(file))) + end + end + + def create_multipart_options!(options) + merge_multipart_file!(options) + @request_method = :post + @options_key = :form + @headers = Twitter::Headers.new(@client, @request_method, @uri).request_headers + end + + def create_json_options! + @options_key = :json + @request_method = :post + @headers = Twitter::Headers.new(@client, @request_method, @uri).request_headers + end + + def create_standard_options!(request_method, options) + @request_method = request_method + @options_key = @request_method == :get ? :params : :form + @headers = Twitter::Headers.new(@client, @request_method, @uri, options).request_headers + end + + def mime_type(basename) + case basename + when /\.gif$/i + 'image/gif' + when /\.jpe?g/i + 'image/jpeg' + when /\.png$/i + 'image/png' + else + 'application/octet-stream' + end + end + end + end +end diff --git a/spec/twitter/rest/request_spec.rb b/spec/twitter/rest/request_spec.rb index 188a9c788..ec9be033c 100644 --- a/spec/twitter/rest/request_spec.rb +++ b/spec/twitter/rest/request_spec.rb @@ -22,14 +22,14 @@ context 'when posting JSON' do it 'makes a proper json encoded request' do stub_post('/1.1/json-post-endpoint.json') - .with({ + .with( body: {test_key: 'test value'}, headers: {content_type: 'application/json; charset=UTF-8'} - }) - .to_return({ + ) + .to_return( body: '{"success":true}', headers: {content_type: 'application/json; charset=utf-8'} - }) + ) Twitter::REST::Request.new(@client, :json_post, '/1.1/json-post-endpoint.json', test_key: 'test value').perform expect(a_post('/1.1/json-post-endpoint.json').with(body: {test_key: 'test value'})).to have_been_made end From 47a846b688edbf6fba070b0a0f215e1e29daab77 Mon Sep 17 00:00:00 2001 From: Maxim Ivanov Date: Fri, 16 Feb 2018 20:37:10 -0500 Subject: [PATCH 4/5] update to oldest officially supported ruby version as per rubocop --- twitter.gemspec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/twitter.gemspec b/twitter.gemspec index b43d34f6f..7321f54bb 100644 --- a/twitter.gemspec +++ b/twitter.gemspec @@ -22,7 +22,7 @@ Gem::Specification.new do |spec| spec.licenses = %w[MIT] spec.name = 'twitter' spec.require_paths = %w[lib] - spec.required_ruby_version = '>= 1.9.3' + spec.required_ruby_version = '>= 2.1.0' spec.summary = spec.description spec.version = Twitter::Version end From 71b67b76e4145f2985265e1747cfde0816403387 Mon Sep 17 00:00:00 2001 From: Maxim Ivanov Date: Fri, 16 Feb 2018 20:57:30 -0500 Subject: [PATCH 5/5] address more CI complaints --- .travis.yml | 1 - lib/twitter/rest/request_options.rb | 5 +++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 8fbe6af07..d9013558d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,7 +3,6 @@ cache: bundler language: ruby rvm: - - 2.0.0 - 2.1 - 2.2 - 2.3.3 diff --git a/lib/twitter/rest/request_options.rb b/lib/twitter/rest/request_options.rb index 5c46d15f7..a82c7c088 100644 --- a/lib/twitter/rest/request_options.rb +++ b/lib/twitter/rest/request_options.rb @@ -3,6 +3,11 @@ module Twitter module REST module RequestOptions + # Set the request method, content type, and headers on the client + # + # @param request_method [Symbol] Desired request method + # @param options [Hash] the content body + # @return [void] def create_request_options!(request_method, options) if request_method == :multipart_post create_multipart_options!(options)