Skip to content

Commit

Permalink
feat(request): Add helper :get and :post class methods (#21)
Browse files Browse the repository at this point in the history
  • Loading branch information
2k-joker authored Aug 24, 2023
1 parent fcb3e8d commit e7427a6
Show file tree
Hide file tree
Showing 4 changed files with 136 additions and 2 deletions.
3 changes: 3 additions & 0 deletions .rubocop.yml
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,9 @@ Style/Semicolon:
Exclude:
- 'test/**/*.rb'

Style/Lambda:
Enabled: false

#### ::LAYOUT ####

Layout/DotPosition:
Expand Down
33 changes: 31 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -109,10 +109,39 @@ To use the default logger (`HTTPigeon::Logger`), simply pass a custom `:filter_k

**Running a request:**

You can pass a block to further customize a specific request:
* You can pass a block to further customize a specific request:
```ruby
# Returns a Hash (parsed JSON) response or a String if the original response was a string
request = HTTPigeon::Request.new(base_url: 'https://dummyjson.com', logger: CustomLogger.new)

# Returns a Hash (parsed JSON) response or a String if the original response was not valid JSON
request.run(path: '/users/1') { |request| request.headers['X-Request-Signature'] = Base64.encode64("#{method}::#{path}") }

# Access the raw Faraday response
request.response

# Quickly get the response status
request.response_status

# Quickly get the raw response body
request.response_body
```
* There is a convenient :get and :post class method you can use
```ruby
# @param endpoint [String] the URI endpoint you're trying to hit
# @param query [Hash] the request query params (default: {})
# @param headers [Hash] the request headers (default: {})
# @param event_type [String] the event type for logs grouping (default: 'http.outbound')
# @param log_filters [Array<HTTPigeon::Filter, Object>] specifies keys in headers and body to be redacted before logging.
# @return [HTTPigeon::Response] an object with attributes :request [HTTPigeon::Request], :parsed_response [Hash], and :raw_response [Faraday::Response]
response = HTTPigeon::Request.get(endpoint, query, headers, event_type, log_filters)

# @param endpoint [String] the URI endpoint you're trying to hit
# @param payload [Hash] the request payload/body (default: {})
# @param headers [Hash] the request headers (default: {})
# @param event_type [String] the event type for logs grouping (default: 'http.outbound')
# @param log_filters [Array<HTTPigeon::Filter, Object>] specifies keys in headers and body to be redacted before logging.
# @return [HTTPigeon::Response] an object with attributes :request [HTTPigeon::Request], :parsed_response [Hash], and :raw_response [Faraday::Response]
response = HTTPigeon::Request.post(endpoint, payload, headers, event_type, log_filters)
```

## Development
Expand Down
30 changes: 30 additions & 0 deletions lib/httpigeon/request.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,26 @@

module HTTPigeon
class Request
class << self
def get(endpoint, query = {}, headers = {}, event_type = nil, log_filters = [])
request = new(base_url: endpoint, headers: headers, event_type: event_type, log_filters: log_filters)
parsed_response = request.run(method: :get, path: '', payload: query) do |req|
yield(req) if block_given?
end

HTTPigeon::Response.new(request, parsed_response, request.response)
end

def post(endpoint, payload, headers = {}, event_type = nil, log_filters = [])
request = new(base_url: endpoint, headers: headers, event_type: event_type, log_filters: log_filters)
parsed_response = request.run(method: :post, path: '', payload: payload) do |req|
yield(req) if block_given?
end

HTTPigeon::Response.new(request, parsed_response, request.response)
end
end

attr_reader :connection, :response, :parsed_response

delegate :status, :body, to: :response, prefix: true
Expand Down Expand Up @@ -64,4 +84,14 @@ def default_headers
HTTPigeon.auto_generate_request_id ? { 'Accept' => 'application/json', 'X-Request-Id' => SecureRandom.uuid } : { 'Accept' => 'application/json' }
end
end

class Response
attr_reader :request, :parsed_response, :raw_response

def initialize(request, parsed_response, raw_response)
@request = request
@parsed_response = parsed_response
@raw_response = raw_response
end
end
end
72 changes: 72 additions & 0 deletions test/httpigeon/request_test.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,78 @@
require_relative "../test_helper"

class HTTPigeon::RequestTest < HTTPigeon::TestCase
# rubocop:disable Minitest/MultipleAssertions
describe '.get' do
it 'makes request with expected arguments' do
endpoint = 'https://dummyjson.com/users/search'
query = { q: 'John' }
event_type = 'some.event'
headers = { 'Foo' => 'Barzzz' }

request_mock = Minitest::Mock.new
request_mock.expect(:response, 'faraday-response')
request_mock.expect(:run, { hello: 'hi' }) do |**kwargs|
assert_equal :get, kwargs[:method]
assert_empty kwargs[:path]
assert_equal kwargs[:payload], query
end

request_on_new = ->(**kwargs) do
assert_equal kwargs[:base_url], endpoint
assert_equal kwargs[:headers], headers
assert_equal kwargs[:event_type], event_type
assert_empty kwargs[:log_filters]

request_mock
end

HTTPigeon::Request.stub(:new, request_on_new) do
response = HTTPigeon::Request.get(endpoint, query, headers, event_type)

assert response.is_a?(HTTPigeon::Response)
assert_equal Hash(hello: 'hi'), response.parsed_response
assert_equal 'faraday-response', response.raw_response
assert_mock request_mock
end
end
end

describe '.post' do
it 'makes request with expected arguments' do
endpoint = 'https://dummyjson.com/users/add'
payload = { firstName: 'John', lastName: 'Doe' }
event_type = 'some.event'
headers = { 'Foo' => 'Barzzz' }

request_mock = Minitest::Mock.new
request_mock.expect(:response, 'faraday-response')
request_mock.expect(:run, { hello: 'hi' }) do |**kwargs|
assert_equal :post, kwargs[:method]
assert_empty kwargs[:path]
assert_equal kwargs[:payload], payload
end

request_on_new = ->(**kwargs) do
assert_equal kwargs[:base_url], endpoint
assert_equal kwargs[:headers], headers
assert_equal kwargs[:event_type], event_type
assert_empty kwargs[:log_filters]

request_mock
end

HTTPigeon::Request.stub(:new, request_on_new) do
response = HTTPigeon::Request.post(endpoint, payload, headers, event_type)

assert response.is_a?(HTTPigeon::Response)
assert_equal Hash(hello: 'hi'), response.parsed_response
assert_equal 'faraday-response', response.raw_response
assert_mock request_mock
end
end
end
# rubocop:enable Minitest/MultipleAssertions

describe '#new' do
context 'when a custom logger is not provided' do
it 'uses the default :httpigeon_logger' do
Expand Down

0 comments on commit e7427a6

Please sign in to comment.