serpnode 0.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 +7 -0
- data/README.md +25 -0
- data/lib/serpnode/client.rb +134 -0
- data/lib/serpnode/version.rb +7 -0
- data/lib/serpnode.rb +7 -0
- metadata +47 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: 12698d52fe2af2a41c4edf43988f3c413a34ec355991c9f4a8f722db2b45704b
|
|
4
|
+
data.tar.gz: 2a010a75db1d835afb5ff07a34af26a9759bcac8341a26f9cf2c4f5d81f7b35a
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: cd9e45e517ba969a0e385c4b61079f9a2ffedb8abb94a0417e27155073aa5b54c860cb596df099e55141909c102f9c0922e5207b4b9dba5e5429f91d22b88c90
|
|
7
|
+
data.tar.gz: 725350e13ef8512287f62d724f1a40a384d4ac63c44fff404b94e3030e9ac5d59c9d71a84f27eb700157f62a63e9cc33510325de8477c252c459e75980c8b6eb
|
data/README.md
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# Serpnode Ruby SDK
|
|
2
|
+
|
|
3
|
+
Ruby client for the Serpnode API. Supports header or query auth and implements `status`, `search`, `options`, and `locations`.
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
## Install
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
gem build serpnode.gemspec
|
|
11
|
+
gem install serpnode-0.1.0.gem
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
## Usage
|
|
15
|
+
|
|
16
|
+
```ruby
|
|
17
|
+
require "serpnode"
|
|
18
|
+
|
|
19
|
+
client = Serpnode::Client.new(api_key: ENV["SERPNODE_API_KEY"]) # or use_header_auth: false
|
|
20
|
+
|
|
21
|
+
puts client.status
|
|
22
|
+
puts client.search(q: "site:example.com", engine: "google")
|
|
23
|
+
puts client.options
|
|
24
|
+
puts client.locations(q: "United States")
|
|
25
|
+
```
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
require "net/http"
|
|
2
|
+
require "json"
|
|
3
|
+
require "uri"
|
|
4
|
+
|
|
5
|
+
module Serpnode
|
|
6
|
+
class Error < StandardError; end
|
|
7
|
+
|
|
8
|
+
class HTTPError < Error
|
|
9
|
+
attr_reader :status, :body
|
|
10
|
+
|
|
11
|
+
def initialize(message, status:, body: nil)
|
|
12
|
+
super(message)
|
|
13
|
+
@status = status
|
|
14
|
+
@body = body
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
class Client
|
|
19
|
+
DEFAULT_OPEN_TIMEOUT = 5
|
|
20
|
+
DEFAULT_READ_TIMEOUT = 30
|
|
21
|
+
DEFAULT_BASE = "https://api.serpnode.com/v1"
|
|
22
|
+
|
|
23
|
+
attr_reader :api_key, :api_base, :use_header_auth, :open_timeout, :read_timeout, :user_agent
|
|
24
|
+
|
|
25
|
+
def initialize(api_key:, api_base: DEFAULT_BASE, use_header_auth: true, open_timeout: DEFAULT_OPEN_TIMEOUT, read_timeout: DEFAULT_READ_TIMEOUT, user_agent: nil)
|
|
26
|
+
@api_key = api_key
|
|
27
|
+
@api_base = api_base.sub(/\/$/, "")
|
|
28
|
+
@use_header_auth = use_header_auth
|
|
29
|
+
@open_timeout = open_timeout
|
|
30
|
+
@read_timeout = read_timeout
|
|
31
|
+
@user_agent = user_agent || default_user_agent
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def status
|
|
35
|
+
get("/status")
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def search(params = {})
|
|
39
|
+
get("/search", params)
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def options(params = {})
|
|
43
|
+
get("/options", params)
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def locations(params = {})
|
|
47
|
+
get("/locations", params)
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
private
|
|
51
|
+
|
|
52
|
+
def get(path, params = {})
|
|
53
|
+
request(:get, path, params: params)
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def request(method, path, params: {})
|
|
57
|
+
uri = build_uri(path, params)
|
|
58
|
+
http = Net::HTTP.new(uri.host, uri.port)
|
|
59
|
+
http.use_ssl = uri.scheme == "https"
|
|
60
|
+
http.open_timeout = open_timeout
|
|
61
|
+
http.read_timeout = read_timeout
|
|
62
|
+
|
|
63
|
+
request = build_http_request(method, uri)
|
|
64
|
+
attach_authentication(request)
|
|
65
|
+
attach_headers(request)
|
|
66
|
+
|
|
67
|
+
response = http.request(request)
|
|
68
|
+
handle_response(response)
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
def build_uri(path, params)
|
|
72
|
+
path = "/#{path}" unless path.start_with?("/")
|
|
73
|
+
uri = URI.parse("#{api_base}#{path}")
|
|
74
|
+
|
|
75
|
+
normalized_params = params.dup
|
|
76
|
+
unless use_header_auth
|
|
77
|
+
normalized_params = { api_key: api_key }.merge(normalized_params || {})
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
if normalized_params && !normalized_params.empty?
|
|
81
|
+
query = URI.encode_www_form(normalized_params)
|
|
82
|
+
uri.query = [uri.query, query].compact.join("&")
|
|
83
|
+
end
|
|
84
|
+
uri
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
def build_http_request(method, uri)
|
|
88
|
+
case method
|
|
89
|
+
when :get
|
|
90
|
+
Net::HTTP::Get.new(uri)
|
|
91
|
+
else
|
|
92
|
+
raise ArgumentError, "Unsupported method: #{method}"
|
|
93
|
+
end
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
def attach_authentication(request)
|
|
97
|
+
if use_header_auth
|
|
98
|
+
request["apikey"] = api_key
|
|
99
|
+
end
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
def attach_headers(request)
|
|
103
|
+
request["Accept"] = "application/json"
|
|
104
|
+
request["User-Agent"] = user_agent
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
def handle_response(response)
|
|
108
|
+
status = response.code.to_i
|
|
109
|
+
body = response.body
|
|
110
|
+
if status >= 200 && status < 300
|
|
111
|
+
parse_json(body)
|
|
112
|
+
else
|
|
113
|
+
message = begin
|
|
114
|
+
parsed = parse_json(body)
|
|
115
|
+
parsed.is_a?(Hash) && (parsed["message"] || parsed["error"]) || body
|
|
116
|
+
rescue JSON::ParserError
|
|
117
|
+
body
|
|
118
|
+
end
|
|
119
|
+
raise HTTPError.new("HTTP #{status}: #{message}", status: status, body: body)
|
|
120
|
+
end
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
def parse_json(string)
|
|
124
|
+
return nil if string.nil? || string.strip.empty?
|
|
125
|
+
JSON.parse(string)
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
def default_user_agent
|
|
129
|
+
"serpnode-ruby/#{Version::STRING} (Ruby #{RUBY_VERSION}; #{RUBY_PLATFORM})"
|
|
130
|
+
end
|
|
131
|
+
end
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
|
data/lib/serpnode.rb
ADDED
metadata
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: serpnode
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.1.0
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- Your Name
|
|
8
|
+
bindir: bin
|
|
9
|
+
cert_chain: []
|
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
|
11
|
+
dependencies: []
|
|
12
|
+
description: 'Ruby client for the Serpnode API: status, search, options, locations.'
|
|
13
|
+
email:
|
|
14
|
+
- you@example.com
|
|
15
|
+
executables: []
|
|
16
|
+
extensions: []
|
|
17
|
+
extra_rdoc_files: []
|
|
18
|
+
files:
|
|
19
|
+
- README.md
|
|
20
|
+
- lib/serpnode.rb
|
|
21
|
+
- lib/serpnode/client.rb
|
|
22
|
+
- lib/serpnode/version.rb
|
|
23
|
+
homepage: https://serpnode.com/
|
|
24
|
+
licenses:
|
|
25
|
+
- MIT
|
|
26
|
+
metadata:
|
|
27
|
+
homepage_uri: https://serpnode.com/
|
|
28
|
+
source_code_uri: https://github.com/everapihq/serpnode-ruby
|
|
29
|
+
changelog_uri: https://github.com/everapihq/serpnode-ruby/releases
|
|
30
|
+
rdoc_options: []
|
|
31
|
+
require_paths:
|
|
32
|
+
- lib
|
|
33
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
34
|
+
requirements:
|
|
35
|
+
- - ">="
|
|
36
|
+
- !ruby/object:Gem::Version
|
|
37
|
+
version: '0'
|
|
38
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
39
|
+
requirements:
|
|
40
|
+
- - ">="
|
|
41
|
+
- !ruby/object:Gem::Version
|
|
42
|
+
version: '0'
|
|
43
|
+
requirements: []
|
|
44
|
+
rubygems_version: 3.7.2
|
|
45
|
+
specification_version: 4
|
|
46
|
+
summary: Serpnode API client
|
|
47
|
+
test_files: []
|