screenshotscout 0.1.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 +13 -22
- data/examples/README.md +4 -5
- data/examples/binary.rb +1 -2
- data/examples/json.rb +1 -2
- data/lib/screenshotscout/capture_options.rb +3 -3
- data/lib/screenshotscout/capture_values.rb +2 -1
- data/lib/screenshotscout/client.rb +12 -4
- data/lib/screenshotscout/internal/serializer.rb +11 -7
- data/lib/screenshotscout/version.rb +1 -1
- data/sig/screenshotscout.rbs +4 -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
|
|
|
@@ -155,7 +153,7 @@ capture:
|
|
|
155
153
|
- DOM changes: `hide_selectors`, `click_selectors`, `click_all_selectors`, `inject_css`, `inject_js`, `bypass_csp`
|
|
156
154
|
- Framing: `selector`, `clip_x`, `clip_y`, `clip_width`, `clip_height`
|
|
157
155
|
- Image output: `image_width`, `image_height`, `image_mode`, `image_anchor`, `image_allow_upscale`, `image_background`, `image_quality`
|
|
158
|
-
- PDF: `pdf_paper_format`, `pdf_landscape`, `pdf_print_background`, `pdf_margin`, `pdf_margin_top`, `pdf_margin_right`, `pdf_margin_bottom`, `pdf_margin_left`, `pdf_scale`
|
|
156
|
+
- PDF: `pdf_paper_format`, `pdf_landscape`, `pdf_print_background`, `pdf_margin`, `pdf_margin_top`, `pdf_margin_right`, `pdf_margin_bottom`, `pdf_margin_left`, `pdf_scale`, `pdf_page_ranges`
|
|
159
157
|
- Caching: `cache`, `cache_ttl`, `cache_key`
|
|
160
158
|
- Storage: `storage_mode`, `storage_endpoint`, `storage_bucket`, `storage_region`, `storage_object_key`
|
|
161
159
|
|
|
@@ -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
|
)
|
|
@@ -13,9 +13,9 @@ module ScreenshotScout
|
|
|
13
13
|
click_selectors click_all_selectors inject_css inject_js bypass_csp selector clip_x clip_y
|
|
14
14
|
clip_width clip_height image_width image_height image_mode image_anchor image_allow_upscale
|
|
15
15
|
image_background image_quality pdf_paper_format pdf_landscape pdf_print_background
|
|
16
|
-
pdf_margin pdf_margin_top pdf_margin_right pdf_margin_bottom pdf_margin_left pdf_scale
|
|
17
|
-
cache_ttl cache_key storage_mode storage_endpoint storage_bucket
|
|
18
|
-
storage_object_key
|
|
16
|
+
pdf_margin pdf_margin_top pdf_margin_right pdf_margin_bottom pdf_margin_left pdf_scale
|
|
17
|
+
pdf_page_ranges cache cache_ttl cache_key storage_mode storage_endpoint storage_bucket
|
|
18
|
+
storage_region storage_object_key
|
|
19
19
|
].freeze
|
|
20
20
|
|
|
21
21
|
attr_reader(*ATTRIBUTE_NAMES)
|
|
@@ -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
|
|
@@ -67,6 +67,7 @@ module ScreenshotScout
|
|
|
67
67
|
pdf_margin_bottom: "pdf_margin_bottom",
|
|
68
68
|
pdf_margin_left: "pdf_margin_left",
|
|
69
69
|
pdf_scale: "pdf_scale",
|
|
70
|
+
pdf_page_ranges: "pdf_page_ranges",
|
|
70
71
|
cache: "cache",
|
|
71
72
|
cache_ttl: "cache_ttl",
|
|
72
73
|
cache_key: "cache_key",
|
|
@@ -121,7 +122,7 @@ module ScreenshotScout
|
|
|
121
122
|
end
|
|
122
123
|
|
|
123
124
|
def encode_query(pairs)
|
|
124
|
-
pairs.map { |pair| "#{
|
|
125
|
+
pairs.map { |pair| "#{rfc3986_encode(pair.name)}=#{rfc3986_encode(pair.value)}" }.join("&")
|
|
125
126
|
end
|
|
126
127
|
|
|
127
128
|
def append_repeated(pairs, body, property, wire_name, value)
|
|
@@ -198,7 +199,11 @@ module ScreenshotScout
|
|
|
198
199
|
raise SerializationError.new(message, option: property)
|
|
199
200
|
end
|
|
200
201
|
|
|
201
|
-
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
|
|
202
207
|
rescue EncodingError => e
|
|
203
208
|
message = if target
|
|
204
209
|
"The capture target URL must contain valid UTF-8."
|
|
@@ -209,19 +214,18 @@ module ScreenshotScout
|
|
|
209
214
|
end
|
|
210
215
|
private_class_method :string_value
|
|
211
216
|
|
|
212
|
-
|
|
217
|
+
# Percent-encodes UTF-8 bytes, leaving only the RFC 3986 unreserved characters as they are.
|
|
218
|
+
def rfc3986_encode(value)
|
|
213
219
|
value.bytes.map do |byte|
|
|
214
220
|
if byte.between?(65, 90) || byte.between?(97, 122) ||
|
|
215
|
-
byte.between?(48, 57) || [
|
|
221
|
+
byte.between?(48, 57) || [45, 46, 95, 126].include?(byte)
|
|
216
222
|
byte.chr
|
|
217
|
-
elsif byte == 32
|
|
218
|
-
"+"
|
|
219
223
|
else
|
|
220
224
|
format("%%%02X", byte)
|
|
221
225
|
end
|
|
222
226
|
end.join
|
|
223
227
|
end
|
|
224
|
-
private_class_method :
|
|
228
|
+
private_class_method :rfc3986_encode
|
|
225
229
|
end
|
|
226
230
|
end
|
|
227
231
|
end
|
data/sig/screenshotscout.rbs
CHANGED
|
@@ -64,7 +64,8 @@ module ScreenshotScout
|
|
|
64
64
|
module CapturePdfPaperFormat
|
|
65
65
|
A3: String
|
|
66
66
|
A4: String
|
|
67
|
-
|
|
67
|
+
A5: String
|
|
68
|
+
A6: String
|
|
68
69
|
LEGAL: String
|
|
69
70
|
LETTER: String
|
|
70
71
|
TABLOID: String
|
|
@@ -135,6 +136,7 @@ module ScreenshotScout
|
|
|
135
136
|
attr_reader pdf_margin_bottom: String?
|
|
136
137
|
attr_reader pdf_margin_left: String?
|
|
137
138
|
attr_reader pdf_scale: number?
|
|
139
|
+
attr_reader pdf_page_ranges: String?
|
|
138
140
|
attr_reader cache: bool?
|
|
139
141
|
attr_reader cache_ttl: Integer?
|
|
140
142
|
attr_reader cache_key: String?
|
|
@@ -204,6 +206,7 @@ module ScreenshotScout
|
|
|
204
206
|
?pdf_margin_bottom: String?,
|
|
205
207
|
?pdf_margin_left: String?,
|
|
206
208
|
?pdf_scale: number?,
|
|
209
|
+
?pdf_page_ranges: String?,
|
|
207
210
|
?cache: bool?,
|
|
208
211
|
?cache_ttl: Integer?,
|
|
209
212
|
?cache_key: String?,
|