hookd-client 0.1.1 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 6e733c25ddc48c4abc81de335f540b1c04b25e93d1ae662c4140ee1b4d735afc
4
- data.tar.gz: 221c74e9d5d1bb915799cb9ec852f54e8ea1cea894bd5246982fab00726769c7
3
+ metadata.gz: ba2b5b2434c982f13d1515e488d1bcc30056f66448fe34d9529004ae0ea1229a
4
+ data.tar.gz: 437ffa486b1a4bb37c6c3e89dc33ab9dbb927b831496435948b47039b0d91384
5
5
  SHA512:
6
- metadata.gz: 8f41965d7a08d776b63b91b03cef5275183de8a4f58eb76077633ebbe790b19c042f94ed2a42c664b92b162d07c55d3e0bd75985c359f656e6f25d30848c5382
7
- data.tar.gz: e88fa863ced788b552d5430d68ee351e5c7ed7b28514a59314937dda1ce3a7250cf75c26cf8ce4346780d24b78ed742c1523d50a206e6d7062664cd6e6014ea1
6
+ metadata.gz: b3551c335feda2be9dfd807c1de65fe1f6f7e46698f193cb3112323c02c3b332e66aa9563caebdc3d24f730d5b8d49484099dfd7c0fd1e3f1370c9860350c79b
7
+ data.tar.gz: 4f162c429ea63559cac8749ffcdace2f80014317c30d2d06e6d8954a44a7c8cdd308222e9133bc292a16db9bddcd1283f25b5f762922b46a68eb130737f23432
data/README.md CHANGED
@@ -63,18 +63,31 @@ The client requires two configuration parameters:
63
63
 
64
64
  Main client class for interacting with the Hookd server.
65
65
 
66
- ##### `#register`
66
+ ##### `#register(count: nil)`
67
67
 
68
- Register a new hook and get DNS/HTTP endpoints.
68
+ Register one or more hooks and get DNS/HTTP endpoints.
69
69
 
70
+ **Single hook (default):**
70
71
  ```ruby
71
72
  hook = client.register
72
73
  # => #<Hookd::Hook id="abc123" dns="abc123.hookd.example.com" ...>
73
74
  ```
74
75
 
75
- Returns: `Hookd::Hook` object
76
+ **Multiple hooks:**
77
+ ```ruby
78
+ hooks = client.register(count: 5)
79
+ # => [#<Hookd::Hook id="abc123" ...>, #<Hookd::Hook id="def456" ...>, ...]
80
+ ```
81
+
82
+ Parameters:
83
+ - `count` (Integer, optional) - Number of hooks to create (default: 1)
84
+
85
+ Returns:
86
+ - `Hookd::Hook` object when `count` is 1 or not specified
87
+ - Array of `Hookd::Hook` objects when `count` > 1
76
88
 
77
89
  Raises:
90
+ - `ArgumentError` - Invalid count parameter
78
91
  - `Hookd::AuthenticationError` - Authentication failed
79
92
  - `Hookd::ServerError` - Server error (5xx)
80
93
  - `Hookd::ConnectionError` - Connection failed
data/lib/hookd/client.rb CHANGED
@@ -1,8 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'net/http'
3
+ require 'httpx'
4
4
  require 'json'
5
- require 'uri'
6
5
 
7
6
  module Hookd
8
7
  # HTTP client for interacting with Hookd server
@@ -12,17 +11,36 @@ module Hookd
12
11
  def initialize(server:, token:)
13
12
  @server = server
14
13
  @token = token
15
- @uri = URI.parse(server)
14
+ @http = HTTPX.with(
15
+ headers: { 'X-API-Key' => token },
16
+ timeout: {
17
+ connect_timeout: 10,
18
+ read_timeout: 30
19
+ }
20
+ )
16
21
  end
17
22
 
18
- # Register a new hook
19
- # @return [Hookd::Hook] the newly registered hook
23
+ # Register one or more hooks
24
+ # @param count [Integer, nil] number of hooks to register (default: 1)
25
+ # @return [Hookd::Hook, Array<Hookd::Hook>] single hook or array of hooks
20
26
  # @raise [Hookd::AuthenticationError] if authentication fails
21
27
  # @raise [Hookd::ServerError] if server returns 5xx
22
28
  # @raise [Hookd::ConnectionError] if connection fails
23
- def register
24
- response = post('/register')
25
- Hook.from_hash(response)
29
+ # @raise [ArgumentError] if count is invalid
30
+ def register(count: nil)
31
+ body = count.nil? ? nil : { count: count }
32
+
33
+ raise ArgumentError, 'count must be a positive integer' if count && (!count.is_a?(Integer) || count < 1)
34
+
35
+ response = post('/register', body)
36
+
37
+ # Single hook response (backward compatible)
38
+ return Hook.from_hash(response) if response.key?('id')
39
+
40
+ # Multiple hooks response
41
+ return [] if response['hooks'].nil? || response['hooks'].empty?
42
+
43
+ response['hooks'].map { |h| Hook.from_hash(h) }
26
44
  end
27
45
 
28
46
  # Poll for interactions on a hook
@@ -56,43 +74,43 @@ module Hookd
56
74
  private
57
75
 
58
76
  def get(path)
59
- request = Net::HTTP::Get.new(path)
60
- request['Authorization'] = "Bearer #{token}"
61
- execute_request(request)
77
+ url = "#{@server}#{path}"
78
+ response = @http.get(url)
79
+ handle_response(response)
62
80
  end
63
81
 
64
82
  def post(path, body = nil)
65
- request = Net::HTTP::Post.new(path)
66
- request['Authorization'] = "Bearer #{token}"
67
- request['Content-Type'] = 'application/json'
68
- request.body = body.to_json if body
69
- execute_request(request)
83
+ url = "#{@server}#{path}"
84
+ options = { headers: { 'Content-Type' => 'application/json' } }
85
+ options[:json] = body if body
86
+
87
+ response = @http.post(url, **options)
88
+ handle_response(response)
70
89
  end
71
90
 
72
- def execute_request(request)
73
- http = Net::HTTP.new(@uri.host, @uri.port)
74
- http.use_ssl = @uri.scheme == 'https'
75
- http.open_timeout = 10
76
- http.read_timeout = 30
91
+ def handle_response(response)
92
+ # HTTPX returns HTTPX::ErrorResponse for connection/timeout errors
93
+ if response.is_a?(HTTPX::ErrorResponse)
94
+ error = response.error
95
+ raise ConnectionError, "Connection failed: #{error.message}"
96
+ end
77
97
 
78
- response = http.request(request)
98
+ body = response.body.to_s
79
99
 
80
- case response.code.to_i
100
+ case response.status
81
101
  when 200, 201
82
- raise Error, 'Empty response body from server' if response.body.nil? || response.body.empty?
102
+ raise Error, 'Empty response body from server' if body.nil? || body.empty?
83
103
 
84
- JSON.parse(response.body)
104
+ JSON.parse(body)
85
105
  when 401
86
- raise AuthenticationError, "Authentication failed: #{response.body}"
106
+ raise AuthenticationError, "Authentication failed: #{body}"
87
107
  when 404
88
- raise NotFoundError, "Resource not found: #{response.body}"
108
+ raise NotFoundError, "Resource not found: #{body}"
89
109
  when 500..599
90
- raise ServerError, "Server error (#{response.code}): #{response.body}"
110
+ raise ServerError, "Server error (#{response.status}): #{body}"
91
111
  else
92
- raise Error, "Unexpected response (#{response.code}): #{response.body}"
112
+ raise Error, "Unexpected response (#{response.status}): #{body}"
93
113
  end
94
- rescue SocketError, Errno::ECONNREFUSED, Net::OpenTimeout, Net::ReadTimeout => e
95
- raise ConnectionError, "Connection failed: #{e.message}"
96
114
  rescue JSON::ParserError => e
97
115
  raise Error, "Invalid JSON response: #{e.message}"
98
116
  end
data/lib/hookd/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Hookd
4
- VERSION = '0.1.1'
4
+ VERSION = '1.1.0'
5
5
  end
metadata CHANGED
@@ -1,14 +1,28 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: hookd-client
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 1.1.0
5
5
  platform: ruby
6
6
  authors:
7
- - Jomar
7
+ - Joshua MARTINELLE
8
8
  bindir: bin
9
9
  cert_chain: []
10
10
  date: 1980-01-02 00:00:00.000000000 Z
11
- dependencies: []
11
+ dependencies:
12
+ - !ruby/object:Gem::Dependency
13
+ name: httpx
14
+ requirement: !ruby/object:Gem::Requirement
15
+ requirements:
16
+ - - "~>"
17
+ - !ruby/object:Gem::Version
18
+ version: '1.0'
19
+ type: :runtime
20
+ prerelease: false
21
+ version_requirements: !ruby/object:Gem::Requirement
22
+ requirements:
23
+ - - "~>"
24
+ - !ruby/object:Gem::Version
25
+ version: '1.0'
12
26
  description: Ruby client library for Hookd, a DNS/HTTP interaction server for security
13
27
  testing and debugging
14
28
  email:
@@ -24,12 +38,12 @@ files:
24
38
  - lib/hookd/hook.rb
25
39
  - lib/hookd/interaction.rb
26
40
  - lib/hookd/version.rb
27
- homepage: https://github.com/JoshuaMart/hookd
41
+ homepage: https://github.com/JoshuaMart/Hookd
28
42
  licenses:
29
43
  - MIT
30
44
  metadata:
31
- homepage_uri: https://github.com/JoshuaMart/hookd
32
- source_code_uri: https://github.com/jomar/hookd
45
+ homepage_uri: https://github.com/JoshuaMart/Hookd
46
+ source_code_uri: https://github.com/JoshuaMart/Hookd
33
47
  rubygems_mfa_required: 'true'
34
48
  rdoc_options: []
35
49
  require_paths: