renderscreenshot 1.0.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/.pre-commit-config.yaml +40 -0
- data/.rubocop.yml +86 -0
- data/.secrets.baseline +116 -0
- data/CHANGELOG.md +59 -0
- data/Gemfile +17 -0
- data/LICENSE +21 -0
- data/README.md +356 -0
- data/REVIEW.md +125 -0
- data/Rakefile +30 -0
- data/lib/renderscreenshot/cache_manager.rb +63 -0
- data/lib/renderscreenshot/client.rb +201 -0
- data/lib/renderscreenshot/configuration.rb +32 -0
- data/lib/renderscreenshot/error.rb +146 -0
- data/lib/renderscreenshot/http_client.rb +166 -0
- data/lib/renderscreenshot/take_options.rb +442 -0
- data/lib/renderscreenshot/version.rb +5 -0
- data/lib/renderscreenshot/webhook.rb +95 -0
- data/lib/renderscreenshot.rb +25 -0
- metadata +84 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: 866ece0d8812f0d70751db71d9746530c4e4b0f95a39624f569672b93688137b
|
|
4
|
+
data.tar.gz: a6d705614f59526337dc55e852075ed21030f66e2a71c17a94895db00386993a
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: f8a11440d6feb0739526fe945732ed2c12e0e0130476c48b6c96d544d98fa70b41c1a9d982e621a42046f42cf0d2bd4b8ffe2d1ef2c618163318a8a4e3b3355d
|
|
7
|
+
data.tar.gz: 11cc424b00ae6727181f580118644a01aa2bb29ddf7554d8a8768e7ebf6bdf410cf862b8728abee757d6d484f30d76fd7f0973ff8e4b31a349249579f1885d48
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
repos:
|
|
2
|
+
# Secret detection - Gitleaks
|
|
3
|
+
- repo: https://github.com/gitleaks/gitleaks
|
|
4
|
+
rev: v8.30.0
|
|
5
|
+
hooks:
|
|
6
|
+
- id: gitleaks
|
|
7
|
+
|
|
8
|
+
# Secret detection - detect-secrets (additional layer)
|
|
9
|
+
- repo: https://github.com/Yelp/detect-secrets
|
|
10
|
+
rev: v1.4.0
|
|
11
|
+
hooks:
|
|
12
|
+
- id: detect-secrets
|
|
13
|
+
args: ['--baseline', '.secrets.baseline']
|
|
14
|
+
exclude: vendor/
|
|
15
|
+
|
|
16
|
+
# General checks
|
|
17
|
+
- repo: https://github.com/pre-commit/pre-commit-hooks
|
|
18
|
+
rev: v6.0.0
|
|
19
|
+
hooks:
|
|
20
|
+
- id: check-added-large-files
|
|
21
|
+
args: ['--maxkb=500']
|
|
22
|
+
- id: check-case-conflict
|
|
23
|
+
- id: check-merge-conflict
|
|
24
|
+
- id: check-yaml
|
|
25
|
+
- id: check-json
|
|
26
|
+
- id: detect-private-key
|
|
27
|
+
- id: end-of-file-fixer
|
|
28
|
+
- id: trailing-whitespace
|
|
29
|
+
- id: no-commit-to-branch
|
|
30
|
+
args: ['--branch', 'main']
|
|
31
|
+
|
|
32
|
+
# Ruby linting
|
|
33
|
+
- repo: local
|
|
34
|
+
hooks:
|
|
35
|
+
- id: rubocop
|
|
36
|
+
name: RuboCop
|
|
37
|
+
entry: bundle exec rubocop --force-exclusion
|
|
38
|
+
language: system
|
|
39
|
+
types: [ruby]
|
|
40
|
+
pass_filenames: true
|
data/.rubocop.yml
ADDED
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
AllCops:
|
|
2
|
+
TargetRubyVersion: 3.0
|
|
3
|
+
NewCops: enable
|
|
4
|
+
SuggestExtensions: false
|
|
5
|
+
Exclude:
|
|
6
|
+
- 'vendor/**/*'
|
|
7
|
+
- 'tmp/**/*'
|
|
8
|
+
- '*.gemspec'
|
|
9
|
+
|
|
10
|
+
Style/Documentation:
|
|
11
|
+
Enabled: false
|
|
12
|
+
|
|
13
|
+
Style/StringLiterals:
|
|
14
|
+
EnforcedStyle: single_quotes
|
|
15
|
+
|
|
16
|
+
Style/FrozenStringLiteralComment:
|
|
17
|
+
Enabled: true
|
|
18
|
+
|
|
19
|
+
# SDK pattern: boolean defaults are common for fluent builders
|
|
20
|
+
Style/OptionalBooleanParameter:
|
|
21
|
+
Enabled: false
|
|
22
|
+
|
|
23
|
+
# SDK pattern: memoization with descriptive names
|
|
24
|
+
Naming/MemoizedInstanceVariableName:
|
|
25
|
+
Enabled: false
|
|
26
|
+
|
|
27
|
+
# Private methods can have short parameter names
|
|
28
|
+
Naming/MethodParameterName:
|
|
29
|
+
Enabled: false
|
|
30
|
+
|
|
31
|
+
# Predicate methods in private scope
|
|
32
|
+
Naming/PredicateMethod:
|
|
33
|
+
Enabled: false
|
|
34
|
+
|
|
35
|
+
# Allow HTTP status codes in test method names
|
|
36
|
+
Naming/VariableNumber:
|
|
37
|
+
CheckMethodNames: false
|
|
38
|
+
|
|
39
|
+
# Allow mutable constants for dynamic values
|
|
40
|
+
Style/MutableConstant:
|
|
41
|
+
Enabled: false
|
|
42
|
+
|
|
43
|
+
# Duplicate branches are intentional for error mapping
|
|
44
|
+
Lint/DuplicateBranch:
|
|
45
|
+
Enabled: false
|
|
46
|
+
|
|
47
|
+
Metrics/BlockLength:
|
|
48
|
+
Exclude:
|
|
49
|
+
- 'test/**/*'
|
|
50
|
+
- 'Rakefile'
|
|
51
|
+
|
|
52
|
+
Metrics/MethodLength:
|
|
53
|
+
Max: 30
|
|
54
|
+
Exclude:
|
|
55
|
+
- 'lib/renderscreenshot/take_options.rb'
|
|
56
|
+
- 'test/**/*'
|
|
57
|
+
|
|
58
|
+
Metrics/AbcSize:
|
|
59
|
+
Max: 50
|
|
60
|
+
Exclude:
|
|
61
|
+
- 'lib/renderscreenshot/take_options.rb'
|
|
62
|
+
- 'test/**/*'
|
|
63
|
+
|
|
64
|
+
Metrics/ClassLength:
|
|
65
|
+
Max: 300
|
|
66
|
+
Exclude:
|
|
67
|
+
- 'lib/renderscreenshot/take_options.rb'
|
|
68
|
+
- 'test/**/*'
|
|
69
|
+
|
|
70
|
+
Metrics/CyclomaticComplexity:
|
|
71
|
+
Max: 15
|
|
72
|
+
Exclude:
|
|
73
|
+
- 'lib/renderscreenshot/take_options.rb'
|
|
74
|
+
|
|
75
|
+
Metrics/PerceivedComplexity:
|
|
76
|
+
Max: 15
|
|
77
|
+
Exclude:
|
|
78
|
+
- 'lib/renderscreenshot/take_options.rb'
|
|
79
|
+
|
|
80
|
+
Metrics/ParameterLists:
|
|
81
|
+
Max: 7
|
|
82
|
+
|
|
83
|
+
Layout/LineLength:
|
|
84
|
+
Max: 120
|
|
85
|
+
Exclude:
|
|
86
|
+
- 'test/**/*'
|
data/.secrets.baseline
ADDED
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": "1.4.0",
|
|
3
|
+
"plugins_used": [
|
|
4
|
+
{
|
|
5
|
+
"name": "ArtifactoryDetector"
|
|
6
|
+
},
|
|
7
|
+
{
|
|
8
|
+
"name": "AWSKeyDetector"
|
|
9
|
+
},
|
|
10
|
+
{
|
|
11
|
+
"name": "AzureStorageKeyDetector"
|
|
12
|
+
},
|
|
13
|
+
{
|
|
14
|
+
"name": "Base64HighEntropyString",
|
|
15
|
+
"limit": 4.5
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
"name": "BasicAuthDetector"
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
"name": "CloudantDetector"
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
"name": "DiscordBotTokenDetector"
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
"name": "GitHubTokenDetector"
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
"name": "HexHighEntropyString",
|
|
31
|
+
"limit": 3.0
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
"name": "IbmCloudIamDetector"
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
"name": "IbmCosHmacDetector"
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
"name": "JwtTokenDetector"
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
"name": "KeywordDetector",
|
|
44
|
+
"keyword_exclude": ""
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
"name": "MailchimpDetector"
|
|
48
|
+
},
|
|
49
|
+
{
|
|
50
|
+
"name": "NpmDetector"
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
"name": "PrivateKeyDetector"
|
|
54
|
+
},
|
|
55
|
+
{
|
|
56
|
+
"name": "SendGridDetector"
|
|
57
|
+
},
|
|
58
|
+
{
|
|
59
|
+
"name": "SlackDetector"
|
|
60
|
+
},
|
|
61
|
+
{
|
|
62
|
+
"name": "SoftlayerDetector"
|
|
63
|
+
},
|
|
64
|
+
{
|
|
65
|
+
"name": "SquareOAuthDetector"
|
|
66
|
+
},
|
|
67
|
+
{
|
|
68
|
+
"name": "StripeDetector"
|
|
69
|
+
},
|
|
70
|
+
{
|
|
71
|
+
"name": "TwilioKeyDetector"
|
|
72
|
+
}
|
|
73
|
+
],
|
|
74
|
+
"filters_used": [
|
|
75
|
+
{
|
|
76
|
+
"path": "detect_secrets.filters.allowlist.is_line_allowlisted"
|
|
77
|
+
},
|
|
78
|
+
{
|
|
79
|
+
"path": "detect_secrets.filters.common.is_baseline_file",
|
|
80
|
+
"filename": ".secrets.baseline"
|
|
81
|
+
},
|
|
82
|
+
{
|
|
83
|
+
"path": "detect_secrets.filters.common.is_ignored_due_to_verification_policies",
|
|
84
|
+
"min_level": 2
|
|
85
|
+
},
|
|
86
|
+
{
|
|
87
|
+
"path": "detect_secrets.filters.heuristic.is_indirect_reference"
|
|
88
|
+
},
|
|
89
|
+
{
|
|
90
|
+
"path": "detect_secrets.filters.heuristic.is_likely_id_string"
|
|
91
|
+
},
|
|
92
|
+
{
|
|
93
|
+
"path": "detect_secrets.filters.heuristic.is_lock_file"
|
|
94
|
+
},
|
|
95
|
+
{
|
|
96
|
+
"path": "detect_secrets.filters.heuristic.is_not_alphanumeric_string"
|
|
97
|
+
},
|
|
98
|
+
{
|
|
99
|
+
"path": "detect_secrets.filters.heuristic.is_potential_uuid"
|
|
100
|
+
},
|
|
101
|
+
{
|
|
102
|
+
"path": "detect_secrets.filters.heuristic.is_prefixed_with_dollar_sign"
|
|
103
|
+
},
|
|
104
|
+
{
|
|
105
|
+
"path": "detect_secrets.filters.heuristic.is_sequential_string"
|
|
106
|
+
},
|
|
107
|
+
{
|
|
108
|
+
"path": "detect_secrets.filters.heuristic.is_swagger_file"
|
|
109
|
+
},
|
|
110
|
+
{
|
|
111
|
+
"path": "detect_secrets.filters.heuristic.is_templated_secret"
|
|
112
|
+
}
|
|
113
|
+
],
|
|
114
|
+
"results": {},
|
|
115
|
+
"generated_at": "2025-01-31T00:00:00Z"
|
|
116
|
+
}
|
data/CHANGELOG.md
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project will be documented in this file.
|
|
4
|
+
|
|
5
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
6
|
+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
|
+
|
|
8
|
+
## [1.0.0] - 2026-02-24
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
|
|
12
|
+
- Initial release of the RenderScreenshot Ruby SDK
|
|
13
|
+
- `Client` class for API interactions
|
|
14
|
+
- `take` - Get screenshot as binary data
|
|
15
|
+
- `take_json` - Get screenshot with JSON metadata
|
|
16
|
+
- `generate_url` - Create signed URLs
|
|
17
|
+
- `batch` - Batch process multiple URLs
|
|
18
|
+
- `batch_advanced` - Batch with per-URL options
|
|
19
|
+
- `get_batch` - Check batch status
|
|
20
|
+
- `presets` - List available presets
|
|
21
|
+
- `preset` - Get specific preset
|
|
22
|
+
- `devices` - List device presets
|
|
23
|
+
- `cache` - Access cache manager
|
|
24
|
+
- `TakeOptions` fluent builder with 58+ methods
|
|
25
|
+
- Viewport: `width`, `height`, `scale`, `mobile`
|
|
26
|
+
- Capture: `full_page`, `element`, `format`, `quality`
|
|
27
|
+
- Wait: `wait_for`, `delay`, `wait_for_selector`, `wait_for_timeout`
|
|
28
|
+
- Presets: `preset`, `device`
|
|
29
|
+
- Blocking: `block_ads`, `block_trackers`, `block_cookie_banners`, `block_chat_widgets`, `block_urls`, `block_resources`
|
|
30
|
+
- Page: `inject_script`, `inject_style`, `click`, `hide`, `remove`
|
|
31
|
+
- Browser: `dark_mode`, `reduced_motion`, `media_type`, `user_agent`, `timezone`, `locale`, `geolocation`
|
|
32
|
+
- Network: `headers`, `cookies`, `auth_basic`, `auth_bearer`, `bypass_csp`
|
|
33
|
+
- Cache: `cache_ttl`, `cache_refresh`
|
|
34
|
+
- PDF: All PDF-specific options
|
|
35
|
+
- Storage: `storage_enabled`, `storage_path`, `storage_acl`
|
|
36
|
+
- `CacheManager` for cache operations
|
|
37
|
+
- `get`, `delete`, `purge`, `purge_url`, `purge_before`, `purge_pattern`
|
|
38
|
+
- `Webhook` module for webhook verification
|
|
39
|
+
- `verify` - HMAC-SHA256 signature verification
|
|
40
|
+
- `parse` - Parse webhook payload
|
|
41
|
+
- `extract_headers` - Extract signature/timestamp from headers
|
|
42
|
+
- Error hierarchy with `retryable?` support
|
|
43
|
+
- `ValidationError`, `AuthenticationError`, `AuthorizationError`
|
|
44
|
+
- `NotFoundError`, `RateLimitError`, `TimeoutError`
|
|
45
|
+
- `ServerError`, `ConnectionError`
|
|
46
|
+
- Global configuration via `RenderScreenshot.configure`
|
|
47
|
+
- Dependabot for automated dependency updates
|
|
48
|
+
- Full test coverage with Minitest (142 tests, 97% coverage)
|
|
49
|
+
|
|
50
|
+
### Security
|
|
51
|
+
|
|
52
|
+
- Faraday minimum version set to >= 2.12.3 (AIKIDO-2025-10223 vulnerability in earlier versions)
|
|
53
|
+
|
|
54
|
+
### Requirements
|
|
55
|
+
|
|
56
|
+
- Ruby >= 3.2.0
|
|
57
|
+
- Faraday >= 2.12.3, < 3.0
|
|
58
|
+
|
|
59
|
+
[1.0.0]: https://github.com/Render-Screenshot/rs-ruby/releases/tag/v1.0.0
|
data/Gemfile
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
source 'https://rubygems.org'
|
|
4
|
+
|
|
5
|
+
gemspec
|
|
6
|
+
|
|
7
|
+
group :development, :test do
|
|
8
|
+
gem 'bundler-audit', '~> 0.9'
|
|
9
|
+
gem 'minitest', '~> 5.20'
|
|
10
|
+
gem 'minitest-reporters', '~> 1.6'
|
|
11
|
+
gem 'rake', '~> 13.0'
|
|
12
|
+
gem 'rubocop', '~> 1.70'
|
|
13
|
+
gem 'simplecov', '~> 0.22', require: false
|
|
14
|
+
gem 'timecop', '~> 0.9'
|
|
15
|
+
gem 'webmock', '~> 3.18'
|
|
16
|
+
gem 'yard', '~> 0.9'
|
|
17
|
+
end
|
data/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 RenderScreenshot
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
data/README.md
ADDED
|
@@ -0,0 +1,356 @@
|
|
|
1
|
+
# RenderScreenshot Ruby SDK
|
|
2
|
+
|
|
3
|
+
The official Ruby SDK for [RenderScreenshot](https://renderscreenshot.com) - a developer-friendly screenshot API for capturing web pages programmatically.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
Add this line to your application's Gemfile:
|
|
8
|
+
|
|
9
|
+
```ruby
|
|
10
|
+
gem 'renderscreenshot'
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
And then execute:
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
bundle install
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
Or install it yourself as:
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
gem install renderscreenshot
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
## Requirements
|
|
26
|
+
|
|
27
|
+
- Ruby 3.0 or higher
|
|
28
|
+
|
|
29
|
+
## Quick Start
|
|
30
|
+
|
|
31
|
+
```ruby
|
|
32
|
+
require 'renderscreenshot'
|
|
33
|
+
|
|
34
|
+
# Create a client
|
|
35
|
+
client = RenderScreenshot.client('rs_live_your_api_key')
|
|
36
|
+
|
|
37
|
+
# Take a screenshot
|
|
38
|
+
image_data = client.take(
|
|
39
|
+
RenderScreenshot::TakeOptions
|
|
40
|
+
.url('https://example.com')
|
|
41
|
+
.width(1200)
|
|
42
|
+
.height(630)
|
|
43
|
+
.format('png')
|
|
44
|
+
)
|
|
45
|
+
|
|
46
|
+
# Save to file
|
|
47
|
+
File.binwrite('screenshot.png', image_data)
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
## Configuration
|
|
51
|
+
|
|
52
|
+
### Global Configuration
|
|
53
|
+
|
|
54
|
+
```ruby
|
|
55
|
+
RenderScreenshot.configure do |config|
|
|
56
|
+
config.base_url = 'https://api.renderscreenshot.com' # Default
|
|
57
|
+
config.timeout = 30 # Default timeout in seconds
|
|
58
|
+
end
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
### Per-Client Configuration
|
|
62
|
+
|
|
63
|
+
```ruby
|
|
64
|
+
client = RenderScreenshot.client(
|
|
65
|
+
'rs_live_your_api_key',
|
|
66
|
+
base_url: 'https://custom.api.com',
|
|
67
|
+
timeout: 60
|
|
68
|
+
)
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
## Usage
|
|
72
|
+
|
|
73
|
+
### Taking Screenshots
|
|
74
|
+
|
|
75
|
+
#### Binary Response
|
|
76
|
+
|
|
77
|
+
```ruby
|
|
78
|
+
# Get screenshot as binary data
|
|
79
|
+
image_data = client.take(
|
|
80
|
+
RenderScreenshot::TakeOptions
|
|
81
|
+
.url('https://example.com')
|
|
82
|
+
.preset('og_card')
|
|
83
|
+
)
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
#### JSON Response (with metadata)
|
|
87
|
+
|
|
88
|
+
```ruby
|
|
89
|
+
# Get screenshot URL and metadata
|
|
90
|
+
response = client.take_json(
|
|
91
|
+
RenderScreenshot::TakeOptions
|
|
92
|
+
.url('https://example.com')
|
|
93
|
+
.preset('og_card')
|
|
94
|
+
)
|
|
95
|
+
|
|
96
|
+
puts response['image']['url'] # CDN URL
|
|
97
|
+
puts response['image']['width'] # 1200
|
|
98
|
+
puts response['image']['height'] # 630
|
|
99
|
+
puts response['cache']['key'] # Cache key for later reference
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
### Screenshot Options
|
|
103
|
+
|
|
104
|
+
The `TakeOptions` class provides a fluent interface for configuring screenshots:
|
|
105
|
+
|
|
106
|
+
```ruby
|
|
107
|
+
options = RenderScreenshot::TakeOptions
|
|
108
|
+
.url('https://example.com')
|
|
109
|
+
# Viewport
|
|
110
|
+
.width(1920)
|
|
111
|
+
.height(1080)
|
|
112
|
+
.scale(2)
|
|
113
|
+
.mobile(true)
|
|
114
|
+
# Capture
|
|
115
|
+
.full_page
|
|
116
|
+
.element('#main-content')
|
|
117
|
+
.format('webp')
|
|
118
|
+
.quality(90)
|
|
119
|
+
# Wait conditions
|
|
120
|
+
.wait_for('networkidle')
|
|
121
|
+
.delay(500)
|
|
122
|
+
.wait_for_selector('.loaded')
|
|
123
|
+
# Blocking
|
|
124
|
+
.block_ads
|
|
125
|
+
.block_trackers
|
|
126
|
+
.block_cookie_banners
|
|
127
|
+
# Browser emulation
|
|
128
|
+
.dark_mode
|
|
129
|
+
.timezone('America/New_York')
|
|
130
|
+
.locale('en-US')
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
### Using Presets
|
|
134
|
+
|
|
135
|
+
```ruby
|
|
136
|
+
# Social card presets
|
|
137
|
+
options = RenderScreenshot::TakeOptions
|
|
138
|
+
.url('https://example.com')
|
|
139
|
+
.preset('og_card') # 1200x630 for Open Graph
|
|
140
|
+
|
|
141
|
+
# Device presets
|
|
142
|
+
options = RenderScreenshot::TakeOptions
|
|
143
|
+
.url('https://example.com')
|
|
144
|
+
.device('iphone_14_pro')
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
### PDF Generation
|
|
148
|
+
|
|
149
|
+
```ruby
|
|
150
|
+
options = RenderScreenshot::TakeOptions
|
|
151
|
+
.url('https://example.com')
|
|
152
|
+
.format('pdf')
|
|
153
|
+
.pdf_paper_size('a4')
|
|
154
|
+
.pdf_landscape
|
|
155
|
+
.pdf_print_background
|
|
156
|
+
.pdf_margin('1cm')
|
|
157
|
+
|
|
158
|
+
pdf_data = client.take(options)
|
|
159
|
+
File.binwrite('document.pdf', pdf_data)
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
### Batch Processing
|
|
163
|
+
|
|
164
|
+
```ruby
|
|
165
|
+
# Simple batch (same options for all URLs)
|
|
166
|
+
response = client.batch(
|
|
167
|
+
['https://example1.com', 'https://example2.com', 'https://example3.com'],
|
|
168
|
+
options: RenderScreenshot::TakeOptions.url('').preset('og_card')
|
|
169
|
+
)
|
|
170
|
+
|
|
171
|
+
response['results'].each do |result|
|
|
172
|
+
puts "#{result['url']}: #{result['status']}"
|
|
173
|
+
end
|
|
174
|
+
|
|
175
|
+
# Advanced batch (per-URL options)
|
|
176
|
+
response = client.batch_advanced([
|
|
177
|
+
{ url: 'https://example1.com', options: { preset: 'og_card' } },
|
|
178
|
+
{ url: 'https://example2.com', options: { preset: 'twitter_card' } }
|
|
179
|
+
])
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
### Signed URLs
|
|
183
|
+
|
|
184
|
+
Generate signed URLs for client-side use without exposing your API key:
|
|
185
|
+
|
|
186
|
+
```ruby
|
|
187
|
+
options = RenderScreenshot::TakeOptions
|
|
188
|
+
.url('https://example.com')
|
|
189
|
+
.preset('og_card')
|
|
190
|
+
|
|
191
|
+
# URL expires in 24 hours
|
|
192
|
+
signed_url = client.generate_url(options, expires_at: Time.now + 86400)
|
|
193
|
+
|
|
194
|
+
# Use in HTML
|
|
195
|
+
# <img src="#{signed_url}" />
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
### Cache Management
|
|
199
|
+
|
|
200
|
+
```ruby
|
|
201
|
+
cache = client.cache
|
|
202
|
+
|
|
203
|
+
# Get cached screenshot
|
|
204
|
+
data = cache.get('cache_key_123')
|
|
205
|
+
|
|
206
|
+
# Delete cached entry
|
|
207
|
+
cache.delete('cache_key_123')
|
|
208
|
+
|
|
209
|
+
# Bulk purge
|
|
210
|
+
cache.purge(['key1', 'key2', 'key3'])
|
|
211
|
+
|
|
212
|
+
# Purge by URL pattern
|
|
213
|
+
cache.purge_url('https://example.com/*')
|
|
214
|
+
|
|
215
|
+
# Purge by date
|
|
216
|
+
cache.purge_before(Time.now - 86400 * 7) # Older than 7 days
|
|
217
|
+
|
|
218
|
+
# Purge by storage path pattern
|
|
219
|
+
cache.purge_pattern('screenshots/2024/01/*')
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
### Presets and Devices
|
|
223
|
+
|
|
224
|
+
```ruby
|
|
225
|
+
# List all presets
|
|
226
|
+
presets = client.presets
|
|
227
|
+
presets.each { |p| puts "#{p['id']}: #{p['name']}" }
|
|
228
|
+
|
|
229
|
+
# Get specific preset
|
|
230
|
+
preset = client.preset('og_card')
|
|
231
|
+
|
|
232
|
+
# List all devices
|
|
233
|
+
devices = client.devices
|
|
234
|
+
devices.each { |d| puts "#{d['id']}: #{d['name']} (#{d['width']}x#{d['height']})" }
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
### Webhook Verification
|
|
238
|
+
|
|
239
|
+
```ruby
|
|
240
|
+
# In your webhook endpoint
|
|
241
|
+
def webhook_handler(request)
|
|
242
|
+
payload = request.body.read
|
|
243
|
+
signature, timestamp = RenderScreenshot::Webhook.extract_headers(request.headers)
|
|
244
|
+
|
|
245
|
+
unless RenderScreenshot::Webhook.verify(
|
|
246
|
+
payload: payload,
|
|
247
|
+
signature: signature,
|
|
248
|
+
timestamp: timestamp,
|
|
249
|
+
secret: ENV['WEBHOOK_SECRET']
|
|
250
|
+
)
|
|
251
|
+
return [401, 'Invalid signature']
|
|
252
|
+
end
|
|
253
|
+
|
|
254
|
+
event = RenderScreenshot::Webhook.parse(payload)
|
|
255
|
+
|
|
256
|
+
case event[:event]
|
|
257
|
+
when 'screenshot.completed'
|
|
258
|
+
handle_screenshot_completed(event[:data])
|
|
259
|
+
when 'screenshot.failed'
|
|
260
|
+
handle_screenshot_failed(event[:data])
|
|
261
|
+
when 'batch.completed'
|
|
262
|
+
handle_batch_completed(event[:data])
|
|
263
|
+
end
|
|
264
|
+
|
|
265
|
+
[200, 'OK']
|
|
266
|
+
end
|
|
267
|
+
```
|
|
268
|
+
|
|
269
|
+
## Error Handling
|
|
270
|
+
|
|
271
|
+
All API errors inherit from `RenderScreenshot::Error`:
|
|
272
|
+
|
|
273
|
+
```ruby
|
|
274
|
+
begin
|
|
275
|
+
client.take(RenderScreenshot::TakeOptions.url('https://example.com'))
|
|
276
|
+
rescue RenderScreenshot::ValidationError => e
|
|
277
|
+
puts "Invalid request: #{e.message}"
|
|
278
|
+
rescue RenderScreenshot::AuthenticationError => e
|
|
279
|
+
puts "Auth failed: #{e.message}"
|
|
280
|
+
rescue RenderScreenshot::RateLimitError => e
|
|
281
|
+
puts "Rate limited. Retry after #{e.retry_after} seconds"
|
|
282
|
+
sleep(e.retry_after) if e.retry_after
|
|
283
|
+
retry
|
|
284
|
+
rescue RenderScreenshot::TimeoutError => e
|
|
285
|
+
puts "Request timed out" if e.retryable?
|
|
286
|
+
rescue RenderScreenshot::ServerError => e
|
|
287
|
+
puts "Server error: #{e.message}"
|
|
288
|
+
retry if e.retryable?
|
|
289
|
+
rescue RenderScreenshot::ConnectionError => e
|
|
290
|
+
puts "Connection failed: #{e.message}"
|
|
291
|
+
end
|
|
292
|
+
```
|
|
293
|
+
|
|
294
|
+
Error properties:
|
|
295
|
+
- `http_status` - HTTP status code
|
|
296
|
+
- `code` - Error code from API
|
|
297
|
+
- `message` - Human-readable message
|
|
298
|
+
- `request_id` - Request ID for support
|
|
299
|
+
- `retry_after` - Seconds to wait (rate limits)
|
|
300
|
+
- `retryable?` - Whether the error can be retried
|
|
301
|
+
|
|
302
|
+
## Complete Options Reference
|
|
303
|
+
|
|
304
|
+
| Category | Methods |
|
|
305
|
+
|----------|---------|
|
|
306
|
+
| **Viewport** | `width`, `height`, `scale`, `mobile` |
|
|
307
|
+
| **Capture** | `full_page`, `element`, `format`, `quality` |
|
|
308
|
+
| **Wait** | `wait_for`, `delay`, `wait_for_selector`, `wait_for_timeout` |
|
|
309
|
+
| **Preset** | `preset`, `device` |
|
|
310
|
+
| **Blocking** | `block_ads`, `block_trackers`, `block_cookie_banners`, `block_chat_widgets`, `block_urls`, `block_resources` |
|
|
311
|
+
| **Page** | `inject_script`, `inject_style`, `click`, `hide`, `remove` |
|
|
312
|
+
| **Browser** | `dark_mode`, `reduced_motion`, `media_type`, `user_agent`, `timezone`, `locale`, `geolocation` |
|
|
313
|
+
| **Network** | `headers`, `cookies`, `auth_basic`, `auth_bearer`, `bypass_csp` |
|
|
314
|
+
| **Cache** | `cache_ttl`, `cache_refresh` |
|
|
315
|
+
| **PDF** | `pdf_paper_size`, `pdf_width`, `pdf_height`, `pdf_landscape`, `pdf_margin`, `pdf_margin_top`, `pdf_margin_right`, `pdf_margin_bottom`, `pdf_margin_left`, `pdf_scale`, `pdf_print_background`, `pdf_page_ranges`, `pdf_header`, `pdf_footer`, `pdf_fit_one_page`, `pdf_prefer_css_page_size` |
|
|
316
|
+
| **Storage** | `storage_enabled`, `storage_path`, `storage_acl` |
|
|
317
|
+
|
|
318
|
+
## Development
|
|
319
|
+
|
|
320
|
+
After checking out the repo:
|
|
321
|
+
|
|
322
|
+
```bash
|
|
323
|
+
bundle install
|
|
324
|
+
bundle exec rake test # Run tests
|
|
325
|
+
bundle exec rubocop # Run linter
|
|
326
|
+
bundle exec rake # Run both
|
|
327
|
+
```
|
|
328
|
+
|
|
329
|
+
### Pre-commit Hooks
|
|
330
|
+
|
|
331
|
+
This project uses pre-commit hooks to prevent secrets from being committed:
|
|
332
|
+
|
|
333
|
+
```bash
|
|
334
|
+
# Install pre-commit (if not already installed)
|
|
335
|
+
brew install pre-commit # macOS
|
|
336
|
+
pip install pre-commit # or via pip
|
|
337
|
+
|
|
338
|
+
# Install the hooks
|
|
339
|
+
pre-commit install
|
|
340
|
+
|
|
341
|
+
# Run manually on all files
|
|
342
|
+
pre-commit run --all-files
|
|
343
|
+
```
|
|
344
|
+
|
|
345
|
+
The hooks include:
|
|
346
|
+
- **Gitleaks** - Scans for secrets and API keys
|
|
347
|
+
- **detect-private-key** - Prevents committing private keys
|
|
348
|
+
- **check-added-large-files** - Prevents large files (>500KB)
|
|
349
|
+
|
|
350
|
+
## Contributing
|
|
351
|
+
|
|
352
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/renderscreenshot/renderscreenshot-ruby.
|
|
353
|
+
|
|
354
|
+
## License
|
|
355
|
+
|
|
356
|
+
The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
|