censu 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (52) hide show
  1. checksums.yaml +7 -0
  2. data/.codeclimate.yml +13 -0
  3. data/.document +3 -0
  4. data/.gitignore +8 -0
  5. data/.rspec +1 -0
  6. data/.rubocop.yml +166 -0
  7. data/.travis.yml +12 -0
  8. data/.yardopts +1 -0
  9. data/ChangeLog.md +4 -0
  10. data/Gemfile +3 -0
  11. data/LICENSE.txt +7 -0
  12. data/README.md +76 -0
  13. data/Rakefile +21 -0
  14. data/censys.gemspec +28 -0
  15. data/lib/censys.rb +2 -0
  16. data/lib/censys/api.rb +254 -0
  17. data/lib/censys/autonomous_system.rb +43 -0
  18. data/lib/censys/certificate.rb +31 -0
  19. data/lib/censys/document.rb +48 -0
  20. data/lib/censys/document/has_asn.rb +16 -0
  21. data/lib/censys/document/has_location.rb +16 -0
  22. data/lib/censys/document/has_services.rb +21 -0
  23. data/lib/censys/exceptions.rb +16 -0
  24. data/lib/censys/ipv4.rb +26 -0
  25. data/lib/censys/location.rb +54 -0
  26. data/lib/censys/report.rb +1 -0
  27. data/lib/censys/report/metadata.rb +41 -0
  28. data/lib/censys/report/response.rb +54 -0
  29. data/lib/censys/search.rb +1 -0
  30. data/lib/censys/search/certificate.rb +19 -0
  31. data/lib/censys/search/ipv4.rb +18 -0
  32. data/lib/censys/search/metadata.rb +33 -0
  33. data/lib/censys/search/response.rb +124 -0
  34. data/lib/censys/search/result.rb +49 -0
  35. data/lib/censys/search/website.rb +18 -0
  36. data/lib/censys/version.rb +4 -0
  37. data/lib/censys/website.rb +30 -0
  38. data/spec/censys_spec.rb +8 -0
  39. data/spec/fixtures/vcr_cassettes/Censys_API/_report/certificates/should_return_certificate_response.yml +49 -0
  40. data/spec/fixtures/vcr_cassettes/Censys_API/_report/ipv4/should_return_ipv4_response.yml +52 -0
  41. data/spec/fixtures/vcr_cassettes/Censys_API/_report/websites/should_return_website_response.yml +49 -0
  42. data/spec/fixtures/vcr_cassettes/Censys_API/_search/certificates/should_return_Certificate_response.yml +397 -0
  43. data/spec/fixtures/vcr_cassettes/Censys_API/_search/ipv4/should_return_IPv4_response.yml +606 -0
  44. data/spec/fixtures/vcr_cassettes/Censys_API/_search/websites/should_return_Website_response.yml +112 -0
  45. data/spec/fixtures/vcr_cassettes/Censys_API/_view/certificates/should_return_Certificate_response.yml +143 -0
  46. data/spec/fixtures/vcr_cassettes/Censys_API/_view/ipv4/should_return_IPv4_response.yml +176 -0
  47. data/spec/fixtures/vcr_cassettes/Censys_API/_view/websites/should_return_Website_response.yml +1020 -0
  48. data/spec/report_spec.rb +60 -0
  49. data/spec/search_spec.rb +49 -0
  50. data/spec/spec_helper.rb +19 -0
  51. data/spec/view_spec.rb +48 -0
  52. metadata +219 -0
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: dc032c148fcfd0d25166894346ef57abb771edba
4
+ data.tar.gz: 7bc3d93c58883260e0eb274f9104b505ea99156a
5
+ SHA512:
6
+ metadata.gz: a7283ce3bb2407fd4e85874432139a2742d4d052b2d2db8674cbd23ad208cd43f67ff883d3c4339caccba23787aa721c59e2cb007622707db568916fc84879f7
7
+ data.tar.gz: 5c8011da8618be9bd7cc7e5f7ababd13f811c00fe896de01b2ba34924431ea42e07a3f80c4827e3e8becb0a930b35a853ce931ac7f164f66b7250eab4b66f3f4
@@ -0,0 +1,13 @@
1
+ version: "2"
2
+ prepare:
3
+ fetch:
4
+ - url: "https://raw.githubusercontent.com/janlelis/relaxed.ruby.style/master/.rubocop.yml"
5
+ path: "alternate-rubocop-path.yml"
6
+ plugins:
7
+ rubocop:
8
+ enabled: true
9
+ config:
10
+ file: "alternate-rubocop-path.yml"
11
+ exclude_patterns:
12
+ - "spec/"
13
+ - "!spec/support/helpers"
@@ -0,0 +1,3 @@
1
+ -
2
+ ChangeLog.md
3
+ LICENSE.txt
@@ -0,0 +1,8 @@
1
+ /.bundle
2
+ /.env
3
+ /.yardoc/
4
+ /Gemfile.lock
5
+ /doc/
6
+ /pkg/
7
+ /vendor/cache/*.gem
8
+ /vendor/bundle
data/.rspec ADDED
@@ -0,0 +1 @@
1
+ --colour --format documentation
@@ -0,0 +1,166 @@
1
+ # Relaxed.Ruby.Style
2
+ ## Version 2.1
3
+
4
+ Style/Alias:
5
+ Enabled: false
6
+ StyleGuide: http://relaxed.ruby.style/#stylealias
7
+
8
+ Style/AsciiComments:
9
+ Enabled: false
10
+ StyleGuide: http://relaxed.ruby.style/#styleasciicomments
11
+
12
+ Style/BeginBlock:
13
+ Enabled: false
14
+ StyleGuide: http://relaxed.ruby.style/#stylebeginblock
15
+
16
+ Style/BlockDelimiters:
17
+ Enabled: false
18
+ StyleGuide: http://relaxed.ruby.style/#styleblockdelimiters
19
+
20
+ Style/CommentAnnotation:
21
+ Enabled: false
22
+ StyleGuide: http://relaxed.ruby.style/#stylecommentannotation
23
+
24
+ Style/Documentation:
25
+ Enabled: false
26
+ StyleGuide: http://relaxed.ruby.style/#styledocumentation
27
+
28
+ Layout/DotPosition:
29
+ Enabled: false
30
+ StyleGuide: http://relaxed.ruby.style/#layoutdotposition
31
+
32
+ Style/DoubleNegation:
33
+ Enabled: false
34
+ StyleGuide: http://relaxed.ruby.style/#styledoublenegation
35
+
36
+ Style/EndBlock:
37
+ Enabled: false
38
+ StyleGuide: http://relaxed.ruby.style/#styleendblock
39
+
40
+ Style/FormatString:
41
+ Enabled: false
42
+ StyleGuide: http://relaxed.ruby.style/#styleformatstring
43
+
44
+ Style/IfUnlessModifier:
45
+ Enabled: false
46
+ StyleGuide: http://relaxed.ruby.style/#styleifunlessmodifier
47
+
48
+ Style/Lambda:
49
+ Enabled: false
50
+ StyleGuide: http://relaxed.ruby.style/#stylelambda
51
+
52
+ Style/ModuleFunction:
53
+ Enabled: false
54
+ StyleGuide: http://relaxed.ruby.style/#stylemodulefunction
55
+
56
+ Style/MultilineBlockChain:
57
+ Enabled: false
58
+ StyleGuide: http://relaxed.ruby.style/#stylemultilineblockchain
59
+
60
+ Style/NegatedIf:
61
+ Enabled: false
62
+ StyleGuide: http://relaxed.ruby.style/#stylenegatedif
63
+
64
+ Style/NegatedWhile:
65
+ Enabled: false
66
+ StyleGuide: http://relaxed.ruby.style/#stylenegatedwhile
67
+
68
+ Style/ParallelAssignment:
69
+ Enabled: false
70
+ StyleGuide: http://relaxed.ruby.style/#styleparallelassignment
71
+
72
+ Style/PercentLiteralDelimiters:
73
+ Enabled: false
74
+ StyleGuide: http://relaxed.ruby.style/#stylepercentliteraldelimiters
75
+
76
+ Style/PerlBackrefs:
77
+ Enabled: false
78
+ StyleGuide: http://relaxed.ruby.style/#styleperlbackrefs
79
+
80
+ Style/Semicolon:
81
+ Enabled: false
82
+ StyleGuide: http://relaxed.ruby.style/#stylesemicolon
83
+
84
+ Style/SignalException:
85
+ Enabled: false
86
+ StyleGuide: http://relaxed.ruby.style/#stylesignalexception
87
+
88
+ Style/SingleLineBlockParams:
89
+ Enabled: false
90
+ StyleGuide: http://relaxed.ruby.style/#stylesinglelineblockparams
91
+
92
+ Style/SingleLineMethods:
93
+ Enabled: false
94
+ StyleGuide: http://relaxed.ruby.style/#stylesinglelinemethods
95
+
96
+ Layout/SpaceBeforeBlockBraces:
97
+ Enabled: false
98
+ StyleGuide: http://relaxed.ruby.style/#layoutspacebeforeblockbraces
99
+
100
+ Layout/SpaceInsideParens:
101
+ Enabled: false
102
+ StyleGuide: http://relaxed.ruby.style/#layoutspaceinsideparens
103
+
104
+ Style/SpecialGlobalVars:
105
+ Enabled: false
106
+ StyleGuide: http://relaxed.ruby.style/#stylespecialglobalvars
107
+
108
+ Style/StringLiterals:
109
+ Enabled: false
110
+ StyleGuide: http://relaxed.ruby.style/#stylestringliterals
111
+
112
+ Style/TrailingCommaInArguments:
113
+ Enabled: false
114
+ StyleGuide: http://relaxed.ruby.style/#styletrailingcommainarguments
115
+
116
+ Style/TrailingCommaInLiteral:
117
+ Enabled: false
118
+ StyleGuide: http://relaxed.ruby.style/#styletrailingcommainliteral
119
+
120
+ Style/WhileUntilModifier:
121
+ Enabled: false
122
+ StyleGuide: http://relaxed.ruby.style/#stylewhileuntilmodifier
123
+
124
+ Style/WordArray:
125
+ Enabled: false
126
+ StyleGuide: http://relaxed.ruby.style/#stylewordarray
127
+
128
+ Lint/AmbiguousRegexpLiteral:
129
+ Enabled: false
130
+ StyleGuide: http://relaxed.ruby.style/#lintambiguousregexpliteral
131
+
132
+ Lint/AssignmentInCondition:
133
+ Enabled: false
134
+ StyleGuide: http://relaxed.ruby.style/#lintassignmentincondition
135
+
136
+ Metrics/AbcSize:
137
+ Enabled: false
138
+
139
+ Metrics/BlockNesting:
140
+ Enabled: false
141
+
142
+ Metrics/BlockLength:
143
+ Exclude:
144
+ - 'spec/**/*'
145
+
146
+ Metrics/ClassLength:
147
+ Enabled: false
148
+
149
+ Metrics/ModuleLength:
150
+ Enabled: false
151
+
152
+ Metrics/CyclomaticComplexity:
153
+ Enabled: false
154
+
155
+ Metrics/LineLength:
156
+ Enabled: false
157
+
158
+ Metrics/MethodLength:
159
+ Enabled: false
160
+
161
+ Metrics/ParameterLists:
162
+ Enabled: false
163
+
164
+ Metrics/PerceivedComplexity:
165
+ Enabled: false
166
+
@@ -0,0 +1,12 @@
1
+ language: ruby
2
+
3
+ cache:
4
+ bundler: true
5
+
6
+ rvm:
7
+ - 2.4
8
+
9
+ script: bundle exec rake test
10
+
11
+ gemfile:
12
+ - Gemfile
@@ -0,0 +1 @@
1
+ --markup markdown --title "CenSys Documentation" --protected
@@ -0,0 +1,4 @@
1
+ ### 0.1.0 / 2016-02-18
2
+
3
+ * Initial release:
4
+
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
@@ -0,0 +1,7 @@
1
+ Copyright 2017 ninoseki(Manabu Niseki)
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
4
+
5
+ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
6
+
7
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,76 @@
1
+ # Censu
2
+
3
+ [![Build Status](https://travis-ci.org/ninoseki/censu.svg?branch=master)](https://travis-ci.org/ninoseki/censu)
4
+ [![Maintainability](https://api.codeclimate.com/v1/badges/39e77d63ce6a7d89b4dc/maintainability)](https://codeclimate.com/github/ninoseki/censu/maintainability)
5
+
6
+ * [Homepage](https://github.com/ninoseki/censu)
7
+ * [Issues](https://github.com/ninoseki/censu/issues)
8
+
9
+ ## Description
10
+
11
+ Ruby API client to the [Censys] internet search engine.
12
+
13
+ ## Features
14
+
15
+ ## Examples
16
+
17
+ Initialize the API:
18
+
19
+ require 'censys'
20
+ api = Censys::API.new(uid,secret)
21
+
22
+ Initialize the API using `$CENSYS_ID` and `$CENSYS_SECRET` environment
23
+ variables:
24
+
25
+ api = Censys::API.new
26
+
27
+ Search for IPv4 addresses:
28
+
29
+ response = api.ipv4.search(query: 'dropbox.com')
30
+
31
+ Search for Websites:
32
+
33
+ response = api.websites.search(query: 'dropbox.com')
34
+
35
+ Search for Certificates:
36
+
37
+ response = api.certificates.search(query: 'dropbox.com')
38
+
39
+ Enumerate through search results:
40
+
41
+ response.each_page do |page|
42
+ puts ">>> Page ##{page.metadata.page} / #{page.metadata.pages} ..."
43
+
44
+ page.each do |result|
45
+ puts result
46
+ end
47
+ end
48
+
49
+ Generate aggregate reports:
50
+
51
+ response = api.websites.report(
52
+ query: '80.http.get.headers.server: Apache',
53
+ field: 'location.country_code',
54
+ buckets: 100
55
+ )
56
+
57
+ response.each do |country,count|
58
+ puts "#{country}: #{count}"
59
+ end
60
+
61
+ ## Requirements
62
+
63
+ * [ruby] >= 2.0
64
+
65
+ ## Install
66
+
67
+ $ gem install censu
68
+
69
+ ## License
70
+
71
+ See {file:LICENSE.txt} for details.
72
+
73
+ Note:: This gem is forked from [trailofbits/censys-ruby](https://github.com/trailofbits/censys-ruby).
74
+
75
+ [ruby]: http://www.ruby-lang.org/
76
+ [Cens:qys]: https://censys.io/
@@ -0,0 +1,21 @@
1
+ require 'rubygems'
2
+
3
+ begin
4
+ require 'bundler/setup'
5
+ rescue LoadError => e
6
+ abort e.message
7
+ end
8
+
9
+ require 'rake'
10
+ require 'rubygems/tasks'
11
+ Gem::Tasks.new
12
+
13
+ require 'rspec/core/rake_task'
14
+ RSpec::Core::RakeTask.new
15
+
16
+ task test: :spec
17
+ task default: :spec
18
+
19
+ require 'yard'
20
+ YARD::Rake::YardocTask.new
21
+ task doc: :yard
@@ -0,0 +1,28 @@
1
+ lib = File.expand_path('../lib', __FILE__)
2
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
3
+ require 'censys/version'
4
+
5
+ Gem::Specification.new do |gem|
6
+ gem.name = "censu"
7
+ gem.version = Censys::VERSION
8
+ gem.summary = "API client for censys.io"
9
+ gem.description = "Ruby API client for the Censys Internet search engine."
10
+ gem.license = "MIT"
11
+ gem.authors = ["Manabu Niseki"]
12
+ gem.email = "manabu.niseki@gmail.com"
13
+ gem.homepage = "https://github.com/ninoseki/censu"
14
+
15
+ gem.files = `git ls-files`.split($/)
16
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
17
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
18
+ gem.require_paths = ['lib']
19
+
20
+ gem.add_development_dependency 'bundler', '~> 1.16'
21
+ gem.add_development_dependency 'dotenv', '~> 2.2'
22
+ gem.add_development_dependency 'rake', '~> 12.3'
23
+ gem.add_development_dependency 'rspec', '~> 3.7'
24
+ gem.add_development_dependency 'rubygems-tasks', '~> 0.2'
25
+ gem.add_development_dependency 'vcr', '~> 4.0'
26
+ gem.add_development_dependency 'webmock', '~> 3.1'
27
+ gem.add_development_dependency 'yard', '~> 0.9'
28
+ end
@@ -0,0 +1,2 @@
1
+ require 'censys/api'
2
+ require 'censys/version'
@@ -0,0 +1,254 @@
1
+ require 'censys/exceptions'
2
+ require 'censys/search'
3
+ require 'censys/report'
4
+ require 'censys/ipv4'
5
+ require 'censys/website'
6
+ require 'censys/certificate'
7
+
8
+ require 'net/https'
9
+ require 'json'
10
+
11
+ module Censys
12
+ class API
13
+ VERSION = 1
14
+ HOST = 'www.censys.io'.freeze
15
+ URL = "https://#{HOST}/api/v#{VERSION}".freeze
16
+
17
+ class Resource
18
+ def initialize(type, api)
19
+ @type = type
20
+ @api = api
21
+ end
22
+
23
+ #
24
+ # @see API#search
25
+ #
26
+ def search(params = {})
27
+ @api.search(@type, params)
28
+ end
29
+
30
+ #
31
+ # @see API#view
32
+ #
33
+ def [](id)
34
+ @api.view(@type, id)
35
+ end
36
+
37
+ #
38
+ # @see API#report
39
+ #
40
+ def report(params)
41
+ @api.report(@type, params)
42
+ end
43
+ end
44
+
45
+ # API UID.
46
+ #
47
+ # @return [String]
48
+ attr_reader :id
49
+
50
+ # API Secret.
51
+ #
52
+ # @return [String]
53
+ attr_reader :secret
54
+
55
+ # IPv4 resource.
56
+ #
57
+ # @return [Resource]
58
+ attr_reader :ipv4
59
+
60
+ # Websites resource.
61
+ #
62
+ # @return [Resource]
63
+ attr_reader :websites
64
+
65
+ # Certificates resource.
66
+ #
67
+ # @return [Resource]
68
+ attr_reader :certificates
69
+
70
+ #
71
+ # Initializes the API.
72
+ #
73
+ # @param [String] id
74
+ # The API UID used for authentication.
75
+ #
76
+ # @param [String] secret
77
+ # The API secret used for authentication.
78
+ #
79
+ # @raise [ArgumentError]
80
+ # Either `id` or `secret` was `nil` or empty.
81
+ #
82
+ # @see https://censys.io/account
83
+ # Censys - My Account
84
+ #
85
+ def initialize(id = ENV['CENSYS_ID'], secret = ENV['CENSYS_SECRET'])
86
+ raise(ArgumentError, "'id' argument required") if id.nil? || id.empty?
87
+ raise(ArgumentError, "'secret' argument required") if secret.nil? || secret.empty?
88
+
89
+ @id, @secret = id, secret
90
+
91
+ @ipv4 = Resource.new(:ipv4, self)
92
+ @websites = Resource.new(:websites, self)
93
+ @certificates = Resource.new(:certificates, self)
94
+ end
95
+
96
+ #
97
+ # Performs a search.
98
+ #
99
+ # @param [:ipv4, :websites, :certificates] resource
100
+ #
101
+ # @param [Hash] params
102
+ # Optional search params.
103
+ #
104
+ # @option params [String] :query
105
+ # The query to perform.
106
+ #
107
+ # @option params [Fixnum] :page
108
+ # Optional page number to request.
109
+ #
110
+ # @option params [Array<String>] :fields
111
+ # Optional list of fields to include in the results.
112
+ #
113
+ # @api private
114
+ #
115
+ def search(resource, params = {})
116
+ post("/search/#{resource}", params) do |json|
117
+ Search::Response.new(self, resource, params, json)
118
+ end
119
+ end
120
+
121
+ DOCUMENTS = {
122
+ ipv4: IPv4,
123
+ websites: Website,
124
+ certificates: Certificate
125
+ }.freeze
126
+
127
+ #
128
+ # Requests the document of the given type.
129
+ #
130
+ # @param [:ipv4, :websites, :certificates] resource
131
+ #
132
+ # @param [String] id
133
+ #
134
+ # @api private
135
+ #
136
+ def view(resource, id)
137
+ document_class = DOCUMENTS.fetch(resource)
138
+
139
+ get("/view/#{resource}/#{id}") do |attributes|
140
+ document_class.new(attributes)
141
+ end
142
+ end
143
+
144
+ #
145
+ # Builds a report of aggregate data.
146
+ #
147
+ # @param [:ipv4, :websites, :certificates] resource
148
+ #
149
+ # @param [Hash] params
150
+ #
151
+ # @option params [String] :query
152
+ # (**Required**) The query to perform.
153
+ #
154
+ # @option params [String] :field
155
+ # (**Required**) The field to aggregate.
156
+ #
157
+ # @option params [Fixnum] :buckets
158
+ # Optional maximum number of values to be returned.
159
+ #
160
+ # @option params
161
+ #
162
+ def report(resource, params)
163
+ raise(ArgumentError, "must specify the :query param") unless params[:query]
164
+ raise(ArgumentError, "must specify the :field param") unless params[:field]
165
+
166
+ post("/report/#{resource}", params) do |response|
167
+ Report::Response.new(response)
168
+ end
169
+ end
170
+
171
+ private
172
+
173
+ #
174
+ # Returns a URL for the API sub-path.
175
+ #
176
+ # @param [String] path
177
+ # Path relative to `/api/v1`.
178
+ #
179
+ # @return [URI::HTTPS]
180
+ # Fully qualified URI.
181
+ #
182
+ def url_for(path)
183
+ URI(URL + path)
184
+ end
185
+
186
+ #
187
+ # Sends the HTTP request and handles the response.
188
+ #
189
+ # @param [Net::HTTP::Get, Net::HTTP::Post] req
190
+ # The prepared request to send.
191
+ #
192
+ # @yield [json]
193
+ # The given block will be passed the parsed JSON.
194
+ #
195
+ # @yieldparam [Hash{String => Object}] json
196
+ # The parsed JSON.
197
+ #
198
+ # @raise [NotFound, RateLimited, InternalServerError, ResponseError]
199
+ # If an error response is returned, the appropriate exception will be
200
+ # raised.
201
+ #
202
+ def request(req)
203
+ Net::HTTP.start(HOST, 443, use_ssl: true) do |http|
204
+ response = http.request(req)
205
+
206
+ case response.code
207
+ when '200' then yield JSON.parse(response.body)
208
+ when '302' then raise(AuthenticationError, response.body)
209
+ when '404' then raise(NotFound, "#{req.uri} not found")
210
+ when '429' then raise(RateLimited, "rate limit exceeded")
211
+ when '500' then raise(InternalServerError, response.body)
212
+ else
213
+ raise(ResponseError, "unsupported response code returned: #{response.code}")
214
+ end
215
+ end
216
+ end
217
+
218
+ #
219
+ # Creates a new HTTP GET request.
220
+ #
221
+ # @param [String] path
222
+ #
223
+ # @see #request
224
+ #
225
+ def get(path, &block)
226
+ get = Net::HTTP::Get.new(url_for(path))
227
+ get.basic_auth @id, @secret
228
+
229
+ request(get, &block)
230
+ end
231
+
232
+ #
233
+ # Creates a new HTTP POST request.
234
+ #
235
+ # @param [String] path
236
+ #
237
+ # @param [#to_json] json
238
+ #
239
+ # @see #request
240
+ #
241
+ def post(path, json, &block)
242
+ post = Net::HTTP::Post.new(url_for(path))
243
+ post.basic_auth @id, @secret
244
+ post.content_type = 'application/json'
245
+ post.body = json.to_json
246
+
247
+ request(post, &block)
248
+ end
249
+
250
+ def validate_index!(index)
251
+ raise(ArgumentError, "unsupported index type: #{index}") unless INDEXES.include?(index)
252
+ end
253
+ end
254
+ end