screenshotscout 0.3.0 → 0.4.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 +4 -4
- data/README.md +12 -21
- data/examples/README.md +4 -5
- data/examples/binary.rb +1 -2
- data/examples/json.rb +1 -2
- data/lib/screenshotscout/client.rb +12 -4
- data/lib/screenshotscout/internal/serializer.rb +10 -7
- data/lib/screenshotscout/version.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 8a670447d2ee6dc8b14865d9161623661cdcd7f8ca0139a5741d61872821d05a
|
|
4
|
+
data.tar.gz: 9c514cbb7f1f5e0eabc76669c7a83faffbcff07501689749238c6f527dbaa6cb
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: d3606891244c9ec6eb473af8eda9ff48d07b4990ff7263e577920ddf8db12abc787a177bccf8448d3e64f9396640378a2a2e16e0c57f3e78e330d06dbaac5066
|
|
7
|
+
data.tar.gz: 4e07a85d4ed239504f3629f4d897f93585cbc32c5279898e4819f3b3346c1a6cc4eadecabe5b652504b26d775af5aeb9990dc690f8bbb470a13c51927c159378
|
data/README.md
CHANGED
|
@@ -29,7 +29,7 @@ gem install screenshotscout
|
|
|
29
29
|
store them securely. The access key is required. The secret key is optional and enables
|
|
30
30
|
[signed requests](#signed-requests).
|
|
31
31
|
|
|
32
|
-
The examples below read `SCREENSHOTSCOUT_ACCESS_KEY` and,
|
|
32
|
+
The examples below read `SCREENSHOTSCOUT_ACCESS_KEY` and, where they sign,
|
|
33
33
|
`SCREENSHOTSCOUT_SECRET_KEY` from environment variables.
|
|
34
34
|
|
|
35
35
|
## Capture a screenshot
|
|
@@ -40,10 +40,7 @@ the full page and saves the returned image:
|
|
|
40
40
|
```ruby
|
|
41
41
|
require "screenshotscout"
|
|
42
42
|
|
|
43
|
-
client = ScreenshotScout::Client.new(
|
|
44
|
-
access_key: ENV.fetch("SCREENSHOTSCOUT_ACCESS_KEY"),
|
|
45
|
-
secret_key: ENV.fetch("SCREENSHOTSCOUT_SECRET_KEY", nil)
|
|
46
|
-
)
|
|
43
|
+
client = ScreenshotScout::Client.new(access_key: ENV.fetch("SCREENSHOTSCOUT_ACCESS_KEY"))
|
|
47
44
|
response = client.capture(
|
|
48
45
|
"https://example.com",
|
|
49
46
|
ScreenshotScout::CaptureOptions.new(full_page: true)
|
|
@@ -64,10 +61,7 @@ image or PDF output:
|
|
|
64
61
|
```ruby
|
|
65
62
|
require "screenshotscout"
|
|
66
63
|
|
|
67
|
-
client = ScreenshotScout::Client.new(
|
|
68
|
-
access_key: ENV.fetch("SCREENSHOTSCOUT_ACCESS_KEY"),
|
|
69
|
-
secret_key: ENV.fetch("SCREENSHOTSCOUT_SECRET_KEY", nil)
|
|
70
|
-
)
|
|
64
|
+
client = ScreenshotScout::Client.new(access_key: ENV.fetch("SCREENSHOTSCOUT_ACCESS_KEY"))
|
|
71
65
|
options = ScreenshotScout::CaptureOptions.new(
|
|
72
66
|
response_type: ScreenshotScout::CaptureResponseType::JSON
|
|
73
67
|
)
|
|
@@ -122,8 +116,9 @@ on the [API Keys page](https://screenshotscout.com/app/api-keys).
|
|
|
122
116
|
|
|
123
117
|
## Signed requests
|
|
124
118
|
|
|
125
|
-
Pass the API key's secret key to sign
|
|
126
|
-
|
|
119
|
+
Pass the API key's secret key to sign generated capture URLs and GET requests automatically. The
|
|
120
|
+
secret is used locally and is never transmitted. POST requests can't be signed, so capture with
|
|
121
|
+
`method: CaptureHttpMethod::GET`:
|
|
127
122
|
|
|
128
123
|
```ruby
|
|
129
124
|
require "screenshotscout"
|
|
@@ -133,7 +128,10 @@ client = ScreenshotScout::Client.new(
|
|
|
133
128
|
secret_key: ENV.fetch("SCREENSHOTSCOUT_SECRET_KEY")
|
|
134
129
|
)
|
|
135
130
|
|
|
136
|
-
response = client.capture(
|
|
131
|
+
response = client.capture(
|
|
132
|
+
"https://example.com",
|
|
133
|
+
method: ScreenshotScout::CaptureHttpMethod::GET
|
|
134
|
+
)
|
|
137
135
|
File.binwrite("signed-screenshot.png", response.bytes)
|
|
138
136
|
```
|
|
139
137
|
|
|
@@ -164,10 +162,7 @@ Use the provided constants for documented values, or pass a string:
|
|
|
164
162
|
```ruby
|
|
165
163
|
require "screenshotscout"
|
|
166
164
|
|
|
167
|
-
client = ScreenshotScout::Client.new(
|
|
168
|
-
access_key: ENV.fetch("SCREENSHOTSCOUT_ACCESS_KEY"),
|
|
169
|
-
secret_key: ENV.fetch("SCREENSHOTSCOUT_SECRET_KEY", nil)
|
|
170
|
-
)
|
|
165
|
+
client = ScreenshotScout::Client.new(access_key: ENV.fetch("SCREENSHOTSCOUT_ACCESS_KEY"))
|
|
171
166
|
options = ScreenshotScout::CaptureOptions.new(
|
|
172
167
|
format: ScreenshotScout::CaptureFormat::WEBP,
|
|
173
168
|
wait_until: ScreenshotScout::CaptureWaitUntil::LOAD
|
|
@@ -240,7 +235,6 @@ end
|
|
|
240
235
|
|
|
241
236
|
client = ScreenshotScout::Client.new(
|
|
242
237
|
access_key: ENV.fetch("SCREENSHOTSCOUT_ACCESS_KEY"),
|
|
243
|
-
secret_key: ENV.fetch("SCREENSHOTSCOUT_SECRET_KEY", nil),
|
|
244
238
|
transport: ApplicationTransport.new(open_timeout: 10, read_timeout: 300)
|
|
245
239
|
)
|
|
246
240
|
|
|
@@ -256,10 +250,7 @@ headers, content type, and body. `APIError` provides the same response details.
|
|
|
256
250
|
```ruby
|
|
257
251
|
require "screenshotscout"
|
|
258
252
|
|
|
259
|
-
client = ScreenshotScout::Client.new(
|
|
260
|
-
access_key: ENV.fetch("SCREENSHOTSCOUT_ACCESS_KEY"),
|
|
261
|
-
secret_key: ENV.fetch("SCREENSHOTSCOUT_SECRET_KEY", nil)
|
|
262
|
-
)
|
|
253
|
+
client = ScreenshotScout::Client.new(access_key: ENV.fetch("SCREENSHOTSCOUT_ACCESS_KEY"))
|
|
263
254
|
|
|
264
255
|
begin
|
|
265
256
|
client.capture("https://example.com")
|
data/examples/README.md
CHANGED
|
@@ -14,22 +14,21 @@ From the repository root, install the dependencies:
|
|
|
14
14
|
bundle install
|
|
15
15
|
```
|
|
16
16
|
|
|
17
|
-
Set your access key.
|
|
18
|
-
|
|
19
|
-
when **Require signed requests** is enabled for the API key.
|
|
17
|
+
Set your access key. To sign the URL that `capture_url.rb` prints, also set the optional secret
|
|
18
|
+
key.
|
|
20
19
|
|
|
21
20
|
PowerShell:
|
|
22
21
|
|
|
23
22
|
```powershell
|
|
24
23
|
$env:SCREENSHOTSCOUT_ACCESS_KEY = "YOUR_ACCESS_KEY"
|
|
25
|
-
$env:SCREENSHOTSCOUT_SECRET_KEY = "YOUR_SECRET_KEY"
|
|
24
|
+
$env:SCREENSHOTSCOUT_SECRET_KEY = "YOUR_SECRET_KEY" # Optional, used by capture_url.rb
|
|
26
25
|
```
|
|
27
26
|
|
|
28
27
|
macOS or Linux:
|
|
29
28
|
|
|
30
29
|
```shell
|
|
31
30
|
export SCREENSHOTSCOUT_ACCESS_KEY="YOUR_ACCESS_KEY"
|
|
32
|
-
export SCREENSHOTSCOUT_SECRET_KEY="YOUR_SECRET_KEY"
|
|
31
|
+
export SCREENSHOTSCOUT_SECRET_KEY="YOUR_SECRET_KEY" # Optional, used by capture_url.rb
|
|
33
32
|
```
|
|
34
33
|
|
|
35
34
|
Run any example:
|
data/examples/binary.rb
CHANGED
|
@@ -3,8 +3,7 @@
|
|
|
3
3
|
require "screenshotscout"
|
|
4
4
|
|
|
5
5
|
access_key = ENV.fetch("SCREENSHOTSCOUT_ACCESS_KEY")
|
|
6
|
-
|
|
7
|
-
client = ScreenshotScout::Client.new(access_key: access_key, secret_key: secret_key)
|
|
6
|
+
client = ScreenshotScout::Client.new(access_key: access_key)
|
|
8
7
|
options = ScreenshotScout::CaptureOptions.new(full_page: true)
|
|
9
8
|
response = client.capture("https://example.com", options)
|
|
10
9
|
|
data/examples/json.rb
CHANGED
|
@@ -3,8 +3,7 @@
|
|
|
3
3
|
require "screenshotscout"
|
|
4
4
|
|
|
5
5
|
access_key = ENV.fetch("SCREENSHOTSCOUT_ACCESS_KEY")
|
|
6
|
-
|
|
7
|
-
client = ScreenshotScout::Client.new(access_key: access_key, secret_key: secret_key)
|
|
6
|
+
client = ScreenshotScout::Client.new(access_key: access_key)
|
|
8
7
|
options = ScreenshotScout::CaptureOptions.new(
|
|
9
8
|
response_type: ScreenshotScout::CaptureResponseType::JSON
|
|
10
9
|
)
|
|
@@ -19,11 +19,13 @@ module ScreenshotScout
|
|
|
19
19
|
@transport = transport || NetHttpTransport.new
|
|
20
20
|
end
|
|
21
21
|
|
|
22
|
-
# Sends one GET or POST request and waits for the final inline response.
|
|
22
|
+
# Sends one GET or POST request and waits for the final inline response. A client with a secret key
|
|
23
|
+
# signs GET requests and raises ConfigurationError for POST, because POST requests can't be signed.
|
|
23
24
|
def capture(url, options = nil, method: CaptureHttpMethod::POST)
|
|
24
25
|
serialized = Internal::Serializer.serialize(url, options)
|
|
25
26
|
method = CaptureHttpMethod::POST if method.nil?
|
|
26
27
|
validate_method(method)
|
|
28
|
+
reject_signed_post(method)
|
|
27
29
|
expected_kind = expected_response_kind(options)
|
|
28
30
|
signature = create_signature(serialized.pairs)
|
|
29
31
|
request = create_request(serialized, method, signature)
|
|
@@ -76,6 +78,14 @@ module ScreenshotScout
|
|
|
76
78
|
)
|
|
77
79
|
end
|
|
78
80
|
|
|
81
|
+
def reject_signed_post(method)
|
|
82
|
+
return if @secret_key.nil? || method != CaptureHttpMethod::POST
|
|
83
|
+
|
|
84
|
+
raise ConfigurationError,
|
|
85
|
+
"POST requests can't be signed. This client has a secret key: send this capture with method GET, " \
|
|
86
|
+
"or use a client without a secret key and an API key that doesn't require signed requests."
|
|
87
|
+
end
|
|
88
|
+
|
|
79
89
|
def create_signature(pairs)
|
|
80
90
|
return nil if @secret_key.nil?
|
|
81
91
|
|
|
@@ -95,14 +105,12 @@ module ScreenshotScout
|
|
|
95
105
|
url = "#{CAPTURE_ENDPOINT}?#{Internal::Serializer.encode_query(pairs)}"
|
|
96
106
|
TransportRequest.new(method: method, url: url, headers: headers)
|
|
97
107
|
else
|
|
98
|
-
body = serialized.body.dup
|
|
99
|
-
body["signature"] = signature unless signature.nil?
|
|
100
108
|
headers["Content-Type"] = "application/json"
|
|
101
109
|
TransportRequest.new(
|
|
102
110
|
method: method,
|
|
103
111
|
url: CAPTURE_ENDPOINT,
|
|
104
112
|
headers: headers,
|
|
105
|
-
body: Internal::JsonCodec.encode_wire_object(body)
|
|
113
|
+
body: Internal::JsonCodec.encode_wire_object(serialized.body)
|
|
106
114
|
)
|
|
107
115
|
end
|
|
108
116
|
rescue Error
|
|
@@ -122,7 +122,7 @@ module ScreenshotScout
|
|
|
122
122
|
end
|
|
123
123
|
|
|
124
124
|
def encode_query(pairs)
|
|
125
|
-
pairs.map { |pair| "#{
|
|
125
|
+
pairs.map { |pair| "#{rfc3986_encode(pair.name)}=#{rfc3986_encode(pair.value)}" }.join("&")
|
|
126
126
|
end
|
|
127
127
|
|
|
128
128
|
def append_repeated(pairs, body, property, wire_name, value)
|
|
@@ -199,7 +199,11 @@ module ScreenshotScout
|
|
|
199
199
|
raise SerializationError.new(message, option: property)
|
|
200
200
|
end
|
|
201
201
|
|
|
202
|
-
value.encode(Encoding::UTF_8)
|
|
202
|
+
string = value.encode(Encoding::UTF_8)
|
|
203
|
+
# encode doesn't check the bytes of a string that is already tagged as UTF-8.
|
|
204
|
+
raise Encoding::InvalidByteSequenceError, "invalid byte sequence in UTF-8" unless string.valid_encoding?
|
|
205
|
+
|
|
206
|
+
string
|
|
203
207
|
rescue EncodingError => e
|
|
204
208
|
message = if target
|
|
205
209
|
"The capture target URL must contain valid UTF-8."
|
|
@@ -210,19 +214,18 @@ module ScreenshotScout
|
|
|
210
214
|
end
|
|
211
215
|
private_class_method :string_value
|
|
212
216
|
|
|
213
|
-
|
|
217
|
+
# Percent-encodes UTF-8 bytes, leaving only the RFC 3986 unreserved characters as they are.
|
|
218
|
+
def rfc3986_encode(value)
|
|
214
219
|
value.bytes.map do |byte|
|
|
215
220
|
if byte.between?(65, 90) || byte.between?(97, 122) ||
|
|
216
|
-
byte.between?(48, 57) || [
|
|
221
|
+
byte.between?(48, 57) || [45, 46, 95, 126].include?(byte)
|
|
217
222
|
byte.chr
|
|
218
|
-
elsif byte == 32
|
|
219
|
-
"+"
|
|
220
223
|
else
|
|
221
224
|
format("%%%02X", byte)
|
|
222
225
|
end
|
|
223
226
|
end.join
|
|
224
227
|
end
|
|
225
|
-
private_class_method :
|
|
228
|
+
private_class_method :rfc3986_encode
|
|
226
229
|
end
|
|
227
230
|
end
|
|
228
231
|
end
|