grover 1.1.8 → 1.1.9
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/lib/grover/configuration.rb +2 -1
- data/lib/grover/errors.rb +1 -0
- data/lib/grover/js/processor.cjs +6 -4
- data/lib/grover/middleware.rb +13 -2
- data/lib/grover/options_builder.rb +6 -6
- data/lib/grover/version.rb +1 -1
- data/lib/grover.rb +15 -14
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 82b9a3edaa4f0d20c326f3e79d61b1d2a0190454ac9ffb6867191a9607ec1ea0
|
4
|
+
data.tar.gz: 4e71234c41bf19c88a5b44c0a043a1c2ae5a74f94d0606fb0cd627c02e8511a2
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 737079399ecd8ef4c6a88c535495a2aa52fcb9e2e8fa0ca171d3453b58134d795237e606487a9f3dd06afad73baac8fac834a76a33445a1099e168f929f13835
|
7
|
+
data.tar.gz: 767e6ebf33ce60336d9afd71859e004b54765910136387ed81b44a12489de7728ff88d0b5f33890dea45314a58476972d31a1f3e9e5e7834f6d68979acf0eb19
|
data/lib/grover/configuration.rb
CHANGED
@@ -7,7 +7,7 @@ class Grover
|
|
7
7
|
class Configuration
|
8
8
|
attr_accessor :options, :meta_tag_prefix, :ignore_path, :ignore_request,
|
9
9
|
:root_url, :use_pdf_middleware, :use_png_middleware,
|
10
|
-
:use_jpeg_middleware, :node_env_vars
|
10
|
+
:use_jpeg_middleware, :node_env_vars, :allow_file_uris
|
11
11
|
|
12
12
|
def initialize
|
13
13
|
@options = {}
|
@@ -19,6 +19,7 @@ class Grover
|
|
19
19
|
@use_png_middleware = false
|
20
20
|
@use_jpeg_middleware = false
|
21
21
|
@node_env_vars = {}
|
22
|
+
@allow_file_uris = false
|
22
23
|
end
|
23
24
|
end
|
24
25
|
end
|
data/lib/grover/errors.rb
CHANGED
data/lib/grover/js/processor.cjs
CHANGED
@@ -26,7 +26,7 @@ const fs = require('fs');
|
|
26
26
|
const os = require('os');
|
27
27
|
const path = require('path');
|
28
28
|
|
29
|
-
const _processPage = (async (convertAction,
|
29
|
+
const _processPage = (async (convertAction, uriOrHtml, options) => {
|
30
30
|
let browser, page, errors = [], tmpDir, wsConnection = false;
|
31
31
|
|
32
32
|
try {
|
@@ -173,10 +173,12 @@ const _processPage = (async (convertAction, urlOrHtml, options) => {
|
|
173
173
|
}
|
174
174
|
|
175
175
|
const waitUntil = options.waitUntil; delete options.waitUntil;
|
176
|
-
|
176
|
+
const allowFileUri = options.allowFileUri; delete options.allowFileUri;
|
177
|
+
const uriRegex = allowFileUri ? /^(https?|file):\/\//i : /^https?:\/\//i;
|
178
|
+
if (uriOrHtml.match(uriRegex)) {
|
177
179
|
// Request is for a URL, so request it
|
178
180
|
requestOptions.waitUntil = waitUntil || 'networkidle2';
|
179
|
-
await page.goto(
|
181
|
+
await page.goto(uriOrHtml, requestOptions);
|
180
182
|
} else {
|
181
183
|
// Request is some HTML content. Use request interception to assign the body
|
182
184
|
requestOptions.waitUntil = waitUntil || 'networkidle0';
|
@@ -188,7 +190,7 @@ const _processPage = (async (convertAction, urlOrHtml, options) => {
|
|
188
190
|
request.continue();
|
189
191
|
else {
|
190
192
|
htmlIntercepted = true
|
191
|
-
request.respond({ body:
|
193
|
+
request.respond({ body: uriOrHtml === '' ? ' ' : uriOrHtml });
|
192
194
|
}
|
193
195
|
});
|
194
196
|
const displayUrl = options.displayUrl; delete options.displayUrl;
|
data/lib/grover/middleware.rb
CHANGED
@@ -24,11 +24,14 @@ class Grover
|
|
24
24
|
dup._call(env)
|
25
25
|
end
|
26
26
|
|
27
|
-
def _call(env)
|
27
|
+
def _call(env) # rubocop:disable Metrics/MethodLength
|
28
28
|
@request = Rack::Request.new(env)
|
29
29
|
identify_request_type
|
30
30
|
|
31
|
-
|
31
|
+
if grover_request?
|
32
|
+
check_file_uri_configuration
|
33
|
+
configure_env_for_grover_request(env)
|
34
|
+
end
|
32
35
|
status, headers, response = @app.call(env)
|
33
36
|
response = update_response response, headers if grover_request? && html_content?(headers)
|
34
37
|
|
@@ -45,6 +48,14 @@ class Grover
|
|
45
48
|
|
46
49
|
attr_reader :pdf_request, :png_request, :jpeg_request
|
47
50
|
|
51
|
+
def check_file_uri_configuration
|
52
|
+
return unless Grover.configuration.allow_file_uris
|
53
|
+
|
54
|
+
# The combination of middleware and allowing file URLs is exceptionally
|
55
|
+
# unsafe as it can lead to data exfiltration from the host system.
|
56
|
+
raise UnsafeConfigurationError, 'using `allow_file_uris` configuration with middleware is exceptionally unsafe'
|
57
|
+
end
|
58
|
+
|
48
59
|
def identify_request_type
|
49
60
|
@pdf_request = Grover.configuration.use_pdf_middleware && path_matches?(PDF_REGEX)
|
50
61
|
@png_request = Grover.configuration.use_png_middleware && path_matches?(PNG_REGEX)
|
@@ -8,12 +8,12 @@ class Grover
|
|
8
8
|
# Build options from Grover.configuration, meta_options, and passed-in options
|
9
9
|
#
|
10
10
|
class OptionsBuilder < Hash
|
11
|
-
def initialize(options,
|
11
|
+
def initialize(options, uri)
|
12
12
|
super()
|
13
|
-
@
|
13
|
+
@uri = uri
|
14
14
|
combined = grover_configuration
|
15
15
|
Utils.deep_merge! combined, Utils.deep_stringify_keys(options)
|
16
|
-
Utils.deep_merge! combined, meta_options unless
|
16
|
+
Utils.deep_merge! combined, meta_options unless uri_source?
|
17
17
|
|
18
18
|
update OptionsFixer.new(combined).run
|
19
19
|
end
|
@@ -41,11 +41,11 @@ class Grover
|
|
41
41
|
end
|
42
42
|
|
43
43
|
def meta_tags
|
44
|
-
Nokogiri::HTML(@
|
44
|
+
Nokogiri::HTML(@uri).xpath('//meta')
|
45
45
|
end
|
46
46
|
|
47
|
-
def
|
48
|
-
@
|
47
|
+
def uri_source?
|
48
|
+
@uri.match?(%r{\A(https?|file)://}i)
|
49
49
|
end
|
50
50
|
end
|
51
51
|
end
|
data/lib/grover/version.rb
CHANGED
data/lib/grover.rb
CHANGED
@@ -28,40 +28,40 @@ class Grover
|
|
28
28
|
attr_reader :front_cover_path, :back_cover_path
|
29
29
|
|
30
30
|
#
|
31
|
-
# @param [String]
|
31
|
+
# @param [String] uri URI of the page to convert
|
32
32
|
# @param [Hash] options Optional parameters to pass to PDF processor
|
33
33
|
# see https://github.com/puppeteer/puppeteer/blob/main/docs/api/puppeteer.pdfoptions.md
|
34
34
|
# and https://github.com/puppeteer/puppeteer/blob/main/docs/api/puppeteer.screenshotoptions.md
|
35
35
|
#
|
36
|
-
def initialize(
|
37
|
-
@
|
38
|
-
@options = OptionsBuilder.new(options, @
|
36
|
+
def initialize(uri, **options)
|
37
|
+
@uri = uri.to_s
|
38
|
+
@options = OptionsBuilder.new(options, @uri)
|
39
39
|
@root_path = @options.delete 'root_path'
|
40
40
|
@front_cover_path = @options.delete 'front_cover_path'
|
41
41
|
@back_cover_path = @options.delete 'back_cover_path'
|
42
42
|
end
|
43
43
|
|
44
44
|
#
|
45
|
-
# Request
|
45
|
+
# Request URI with provided options and create PDF
|
46
46
|
#
|
47
47
|
# @param [String] path Optional path to write the PDF to
|
48
48
|
# @return [String] The resulting PDF data
|
49
49
|
#
|
50
50
|
def to_pdf(path = nil)
|
51
|
-
processor.convert :pdf, @
|
51
|
+
processor.convert :pdf, @uri, normalized_options(path: path)
|
52
52
|
end
|
53
53
|
|
54
54
|
#
|
55
|
-
# Request
|
55
|
+
# Request URI with provided options and render HTML
|
56
56
|
#
|
57
57
|
# @return [String] The resulting HTML string
|
58
58
|
#
|
59
59
|
def to_html
|
60
|
-
processor.convert :content, @
|
60
|
+
processor.convert :content, @uri, normalized_options(path: nil)
|
61
61
|
end
|
62
62
|
|
63
63
|
#
|
64
|
-
# Request
|
64
|
+
# Request URI with provided options and create screenshot
|
65
65
|
#
|
66
66
|
# @param [String] path Optional path to write the screenshot to
|
67
67
|
# @param [String] format Optional format of the screenshot
|
@@ -70,11 +70,11 @@ class Grover
|
|
70
70
|
def screenshot(path: nil, format: nil)
|
71
71
|
options = normalized_options(path: path)
|
72
72
|
options['type'] = format if %w[png jpeg].include? format
|
73
|
-
processor.convert :screenshot, @
|
73
|
+
processor.convert :screenshot, @uri, options
|
74
74
|
end
|
75
75
|
|
76
76
|
#
|
77
|
-
# Request
|
77
|
+
# Request URI with provided options and create PNG
|
78
78
|
#
|
79
79
|
# @param [String] path Optional path to write the screenshot to
|
80
80
|
# @return [String] The resulting PNG data
|
@@ -84,7 +84,7 @@ class Grover
|
|
84
84
|
end
|
85
85
|
|
86
86
|
#
|
87
|
-
# Request
|
87
|
+
# Request URI with provided options and create JPEG
|
88
88
|
#
|
89
89
|
# @param [String] path Optional path to write the screenshot to
|
90
90
|
# @return [String] The resulting JPEG data
|
@@ -116,10 +116,10 @@ class Grover
|
|
116
116
|
#
|
117
117
|
def inspect
|
118
118
|
format(
|
119
|
-
'#<%<class_name>s:0x%<object_id>p @
|
119
|
+
'#<%<class_name>s:0x%<object_id>p @uri="%<uri>s">',
|
120
120
|
class_name: self.class.name,
|
121
121
|
object_id: object_id,
|
122
|
-
|
122
|
+
uri: @uri
|
123
123
|
)
|
124
124
|
end
|
125
125
|
|
@@ -147,6 +147,7 @@ class Grover
|
|
147
147
|
def normalized_options(path:)
|
148
148
|
normalized_options = Utils.normalize_object @options, excluding: ['extraHTTPHeaders']
|
149
149
|
normalized_options['path'] = path if path.is_a? ::String
|
150
|
+
normalized_options['allowFileUri'] = Grover.configuration.allow_file_uris == true
|
150
151
|
normalized_options
|
151
152
|
end
|
152
153
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: grover
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.1.
|
4
|
+
version: 1.1.9
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Andrew Bromwich
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-
|
11
|
+
date: 2024-07-02 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: combine_pdf
|