crawlberg 1.1.4 → 1.2.1
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/ext/crawlberg_rb/native/Cargo.lock +55 -54
- data/ext/crawlberg_rb/native/Cargo.toml +2 -2
- data/ext/crawlberg_rb/src/lib.rs +311 -52
- data/lib/crawlberg/native.rb +110 -1
- data/lib/crawlberg/version.rb +2 -2
- data/lib/crawlberg.rb +1 -1
- data/lib/crawlberg_rb.so +0 -0
- data/sig/types.rbs +23 -6
- metadata +2 -2
data/lib/crawlberg/native.rb
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
# This file is auto-generated by alef — DO NOT EDIT.
|
|
2
|
-
# alef:hash:
|
|
2
|
+
# alef:hash:0ce4d753fdb4854e44358639dcbaebee3449a4afa142dbc4f0a72aa72c214648
|
|
3
3
|
# To regenerate: alef generate
|
|
4
4
|
# To verify freshness: alef verify --exit-code
|
|
5
5
|
# frozen_string_literal: true
|
|
@@ -561,3 +561,112 @@ module Crawlberg
|
|
|
561
561
|
end
|
|
562
562
|
end
|
|
563
563
|
end
|
|
564
|
+
|
|
565
|
+
module Crawlberg
|
|
566
|
+
# Hostname/IP allowlist matcher for SSRF policy.
|
|
567
|
+
#
|
|
568
|
+
# Serializes as an internally-tagged object so each variant is distinguishable on the
|
|
569
|
+
# wire and round-trips losslessly:
|
|
570
|
+
#
|
|
571
|
+
# ```json
|
|
572
|
+
# {"type": "exact", "value": "api.example.com"}
|
|
573
|
+
# {"type": "suffix", "value": ".example.com"}
|
|
574
|
+
# {"type": "cidr", "value": "10.0.0.0/8"}
|
|
575
|
+
# ```
|
|
576
|
+
#
|
|
577
|
+
# A bare JSON string is still accepted on deserialization and resolves to [`Exact`],
|
|
578
|
+
# preserving configs written against the previous untagged representation.
|
|
579
|
+
#
|
|
580
|
+
# [`Exact`]: HostMatcher::Exact
|
|
581
|
+
module HostMatcher
|
|
582
|
+
extend T::Helpers
|
|
583
|
+
extend T::Sig
|
|
584
|
+
|
|
585
|
+
interface!
|
|
586
|
+
|
|
587
|
+
# Dispatch from a Hash to the appropriate variant constructor.
|
|
588
|
+
# @param hash [Hash] with discriminator field and variant-specific fields
|
|
589
|
+
# @return [variant_class] an instance of the appropriate variant
|
|
590
|
+
sig { params(hash: T::Hash[T.untyped, T.untyped]).returns(T.untyped) }
|
|
591
|
+
def self.from_hash(hash)
|
|
592
|
+
discriminator = hash[:type] || hash["type"]
|
|
593
|
+
case discriminator
|
|
594
|
+
when "exact"
|
|
595
|
+
HostMatcherExact.from_hash(hash)
|
|
596
|
+
when "suffix"
|
|
597
|
+
HostMatcherSuffix.from_hash(hash)
|
|
598
|
+
when "cidr"
|
|
599
|
+
HostMatcherCidr.from_hash(hash)
|
|
600
|
+
else
|
|
601
|
+
raise "Unknown discriminator: #{discriminator}"
|
|
602
|
+
end
|
|
603
|
+
end
|
|
604
|
+
end
|
|
605
|
+
## Exact hostname match (case-insensitive).
|
|
606
|
+
HostMatcherExact = Data.define(:value) do
|
|
607
|
+
include HostMatcher
|
|
608
|
+
extend T::Sig
|
|
609
|
+
|
|
610
|
+
# The hostname to match.
|
|
611
|
+
sig { returns(String) }
|
|
612
|
+
# rubocop:disable Lint/UselessMethodDefinition
|
|
613
|
+
def value = super
|
|
614
|
+
sig { returns(T::Boolean) }
|
|
615
|
+
def exact? = true
|
|
616
|
+
sig { returns(T::Boolean) }
|
|
617
|
+
def suffix? = false
|
|
618
|
+
sig { returns(T::Boolean) }
|
|
619
|
+
def cidr? = false
|
|
620
|
+
# @param hash [Hash] deserialized from the native extension
|
|
621
|
+
# @return [self]
|
|
622
|
+
sig { params(hash: T::Hash[T.untyped, T.untyped]).returns(T.attached_class) }
|
|
623
|
+
def self.from_hash(hash)
|
|
624
|
+
new(value: hash[:value] || hash["value"])
|
|
625
|
+
end
|
|
626
|
+
end
|
|
627
|
+
## Suffix match: ".xberg.io" matches "api.xberg.io" and "xberg.io".
|
|
628
|
+
HostMatcherSuffix = Data.define(:value) do
|
|
629
|
+
include HostMatcher
|
|
630
|
+
extend T::Sig
|
|
631
|
+
|
|
632
|
+
# The dot-prefixed suffix to match. A leading dot is optional.
|
|
633
|
+
sig { returns(String) }
|
|
634
|
+
# rubocop:disable Lint/UselessMethodDefinition
|
|
635
|
+
def value = super
|
|
636
|
+
sig { returns(T::Boolean) }
|
|
637
|
+
def exact? = false
|
|
638
|
+
sig { returns(T::Boolean) }
|
|
639
|
+
def suffix? = true
|
|
640
|
+
sig { returns(T::Boolean) }
|
|
641
|
+
def cidr? = false
|
|
642
|
+
# @param hash [Hash] deserialized from the native extension
|
|
643
|
+
# @return [self]
|
|
644
|
+
sig { params(hash: T::Hash[T.untyped, T.untyped]).returns(T.attached_class) }
|
|
645
|
+
def self.from_hash(hash)
|
|
646
|
+
new(value: hash[:value] || hash["value"])
|
|
647
|
+
end
|
|
648
|
+
end
|
|
649
|
+
## CIDR match: "10.0.0.0/8" matches IP addresses in that range.
|
|
650
|
+
HostMatcherCidr = Data.define(:value) do
|
|
651
|
+
include HostMatcher
|
|
652
|
+
extend T::Sig
|
|
653
|
+
|
|
654
|
+
# The CIDR block. Validated when built through [`HostMatcher::cidr`] or
|
|
655
|
+
# deserialization.
|
|
656
|
+
sig { returns(String) }
|
|
657
|
+
# rubocop:disable Lint/UselessMethodDefinition
|
|
658
|
+
def value = super
|
|
659
|
+
sig { returns(T::Boolean) }
|
|
660
|
+
def exact? = false
|
|
661
|
+
sig { returns(T::Boolean) }
|
|
662
|
+
def suffix? = false
|
|
663
|
+
sig { returns(T::Boolean) }
|
|
664
|
+
def cidr? = true
|
|
665
|
+
# @param hash [Hash] deserialized from the native extension
|
|
666
|
+
# @return [self]
|
|
667
|
+
sig { params(hash: T::Hash[T.untyped, T.untyped]).returns(T.attached_class) }
|
|
668
|
+
def self.from_hash(hash)
|
|
669
|
+
new(value: hash[:value] || hash["value"])
|
|
670
|
+
end
|
|
671
|
+
end
|
|
672
|
+
end
|
data/lib/crawlberg/version.rb
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
# This file is auto-generated by alef — DO NOT EDIT.
|
|
2
|
-
# alef:hash:
|
|
2
|
+
# alef:hash:0ce4d753fdb4854e44358639dcbaebee3449a4afa142dbc4f0a72aa72c214648
|
|
3
3
|
# To regenerate: alef generate
|
|
4
4
|
# To verify freshness: alef verify --exit-code
|
|
5
5
|
# frozen_string_literal: true
|
|
6
6
|
|
|
7
7
|
module Crawlberg
|
|
8
8
|
## The version string for this package.
|
|
9
|
-
VERSION = "1.1
|
|
9
|
+
VERSION = "1.2.1"
|
|
10
10
|
end
|
data/lib/crawlberg.rb
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
# This file is auto-generated by alef — DO NOT EDIT.
|
|
2
|
-
# alef:hash:
|
|
2
|
+
# alef:hash:0ce4d753fdb4854e44358639dcbaebee3449a4afa142dbc4f0a72aa72c214648
|
|
3
3
|
# To regenerate: alef generate
|
|
4
4
|
# To verify freshness: alef verify --exit-code
|
|
5
5
|
# frozen_string_literal: true
|
data/lib/crawlberg_rb.so
CHANGED
|
Binary file
|
data/sig/types.rbs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
# This file is auto-generated by alef — DO NOT EDIT.
|
|
2
|
-
# alef:hash:
|
|
2
|
+
# alef:hash:0ce4d753fdb4854e44358639dcbaebee3449a4afa142dbc4f0a72aa72c214648
|
|
3
3
|
# To regenerate: alef generate
|
|
4
4
|
# To verify freshness: alef verify --exit-code
|
|
5
5
|
|
|
@@ -67,6 +67,7 @@ def initialize: (?mode: BrowserMode, ?backend: BrowserBackend, ?endpoint: String
|
|
|
67
67
|
class CrawlConfig
|
|
68
68
|
attr_accessor max_depth: Integer?
|
|
69
69
|
attr_accessor max_pages: Integer?
|
|
70
|
+
attr_accessor max_links_per_page: Integer?
|
|
70
71
|
attr_accessor max_concurrent: Integer?
|
|
71
72
|
attr_accessor respect_robots_txt: bool?
|
|
72
73
|
attr_accessor soft_http_errors: bool?
|
|
@@ -100,12 +101,15 @@ def initialize: (?mode: BrowserMode, ?backend: BrowserBackend, ?endpoint: String
|
|
|
100
101
|
attr_accessor download_documents: bool?
|
|
101
102
|
attr_accessor document_max_size: Integer?
|
|
102
103
|
attr_accessor document_mime_types: Array[String]?
|
|
104
|
+
attr_accessor document_output_dir: String?
|
|
105
|
+
attr_accessor document_content_encoding: DocumentContentEncoding?
|
|
103
106
|
attr_accessor warc_output: String?
|
|
104
107
|
attr_accessor browser_profile: String?
|
|
105
108
|
attr_accessor save_browser_profile: bool?
|
|
106
109
|
attr_accessor ssrf: SsrfPolicy?
|
|
110
|
+
attr_accessor ssrf_deny_private_explicit: bool?
|
|
107
111
|
|
|
108
|
-
def initialize: (?max_depth: Integer, ?max_pages: Integer, ?max_concurrent: Integer, ?respect_robots_txt: bool, ?soft_http_errors: bool, ?user_agent: String, ?stay_on_domain: bool, ?allow_subdomains: bool, ?include_paths: Array[String], ?exclude_paths: Array[String], ?custom_headers: Hash[String, String], ?request_timeout: Integer, ?rate_limit_ms: Integer, ?max_redirects: Integer, ?retry_count: Integer, ?retry_codes: Array[Integer], ?cookies_enabled: bool, ?auth: AuthConfig, ?max_body_size: Integer, ?remove_tags: Array[String], ?content: ContentConfig, ?map_limit: Integer, ?map_search: String, ?download_assets: bool, ?asset_types: Array[AssetCategory], ?max_asset_size: Integer, ?browser: BrowserConfig, ?proxy: ProxyConfig, ?user_agents: Array[String], ?capture_screenshot: bool, ?follow_document_urls: bool, ?document_url_depth: Integer, ?download_documents: bool, ?document_max_size: Integer, ?document_mime_types: Array[String], ?warc_output: String, ?browser_profile: String, ?save_browser_profile: bool, ?ssrf: SsrfPolicy) -> void
|
|
112
|
+
def initialize: (?max_depth: Integer, ?max_pages: Integer, ?max_links_per_page: Integer, ?max_concurrent: Integer, ?respect_robots_txt: bool, ?soft_http_errors: bool, ?user_agent: String, ?stay_on_domain: bool, ?allow_subdomains: bool, ?include_paths: Array[String], ?exclude_paths: Array[String], ?custom_headers: Hash[String, String], ?request_timeout: Integer, ?rate_limit_ms: Integer, ?max_redirects: Integer, ?retry_count: Integer, ?retry_codes: Array[Integer], ?cookies_enabled: bool, ?auth: AuthConfig, ?max_body_size: Integer, ?remove_tags: Array[String], ?content: ContentConfig, ?map_limit: Integer, ?map_search: String, ?download_assets: bool, ?asset_types: Array[AssetCategory], ?max_asset_size: Integer, ?browser: BrowserConfig, ?proxy: ProxyConfig, ?user_agents: Array[String], ?capture_screenshot: bool, ?follow_document_urls: bool, ?document_url_depth: Integer, ?download_documents: bool, ?document_max_size: Integer, ?document_mime_types: Array[String], ?document_output_dir: String, ?document_content_encoding: DocumentContentEncoding, ?warc_output: String, ?browser_profile: String, ?save_browser_profile: bool, ?ssrf: SsrfPolicy, ?ssrf_deny_private_explicit: bool) -> void
|
|
109
113
|
def validate: () -> void
|
|
110
114
|
def self.default: () -> CrawlConfig
|
|
111
115
|
end
|
|
@@ -125,16 +129,20 @@ def initialize: (?eval_result: json_value, ?network_events: Array[ResponseMeta],
|
|
|
125
129
|
attr_accessor filename: String?
|
|
126
130
|
attr_accessor content_hash: String?
|
|
127
131
|
attr_accessor headers: Hash[String, String]?
|
|
132
|
+
attr_accessor truncated: bool?
|
|
133
|
+
attr_accessor content_path: String?
|
|
134
|
+
attr_accessor content_base64: String?
|
|
128
135
|
|
|
129
|
-
def initialize: (?url: String, ?mime_type: String, ?size: Integer, ?filename: String, ?content_hash: String, ?headers: Hash[String, String]) -> void
|
|
136
|
+
def initialize: (?url: String, ?mime_type: String, ?size: Integer, ?filename: String, ?content_hash: String, ?headers: Hash[String, String], ?truncated: bool, ?content_path: String, ?content_base64: String) -> void
|
|
130
137
|
end
|
|
131
138
|
|
|
132
139
|
class InteractionResult
|
|
133
140
|
attr_accessor action_results: Array[ActionResult]?
|
|
134
141
|
attr_accessor final_html: String?
|
|
135
142
|
attr_accessor final_url: String?
|
|
143
|
+
attr_accessor screenshot_base64: String?
|
|
136
144
|
|
|
137
|
-
def initialize: (?action_results: Array[ActionResult], ?final_html: String, ?final_url: String) -> void
|
|
145
|
+
def initialize: (?action_results: Array[ActionResult], ?final_html: String, ?final_url: String, ?screenshot_base64: String) -> void
|
|
138
146
|
end
|
|
139
147
|
|
|
140
148
|
class ActionResult
|
|
@@ -174,10 +182,11 @@ def initialize: (?action_results: Array[ActionResult], ?final_html: String, ?fin
|
|
|
174
182
|
attr_accessor markdown: MarkdownResult?
|
|
175
183
|
attr_accessor extracted_data: json_value?
|
|
176
184
|
attr_accessor extraction_meta: ExtractionMeta?
|
|
185
|
+
attr_accessor screenshot_base64: String?
|
|
177
186
|
attr_accessor downloaded_document: DownloadedDocument?
|
|
178
187
|
attr_accessor browser: BrowserExtras?
|
|
179
188
|
|
|
180
|
-
def initialize: (?status_code: Integer, ?final_url: String, ?content_type: String, ?html: String, ?body_size: Integer, ?metadata: PageMetadata, ?links: Array[LinkInfo], ?images: Array[ImageInfo], ?feeds: Array[FeedInfo], ?json_ld: Array[JsonLdEntry], ?is_allowed: bool, ?crawl_delay: Integer, ?noindex_detected: bool, ?nofollow_detected: bool, ?x_robots_tag: String, ?is_pdf: bool, ?was_skipped: bool, ?detected_charset: String, ?auth_header_sent: bool, ?response_meta: ResponseMeta, ?assets: Array[DownloadedAsset], ?js_render_hint: bool, ?browser_used: bool, ?markdown: MarkdownResult, ?extracted_data: json_value, ?extraction_meta: ExtractionMeta, ?downloaded_document: DownloadedDocument, ?browser: BrowserExtras) -> void
|
|
189
|
+
def initialize: (?status_code: Integer, ?final_url: String, ?content_type: String, ?html: String, ?body_size: Integer, ?metadata: PageMetadata, ?links: Array[LinkInfo], ?images: Array[ImageInfo], ?feeds: Array[FeedInfo], ?json_ld: Array[JsonLdEntry], ?is_allowed: bool, ?crawl_delay: Integer, ?noindex_detected: bool, ?nofollow_detected: bool, ?x_robots_tag: String, ?is_pdf: bool, ?was_skipped: bool, ?detected_charset: String, ?auth_header_sent: bool, ?response_meta: ResponseMeta, ?assets: Array[DownloadedAsset], ?js_render_hint: bool, ?browser_used: bool, ?markdown: MarkdownResult, ?extracted_data: json_value, ?extraction_meta: ExtractionMeta, ?screenshot_base64: String, ?downloaded_document: DownloadedDocument, ?browser: BrowserExtras) -> void
|
|
181
190
|
end
|
|
182
191
|
|
|
183
192
|
class CrawlPageResult
|
|
@@ -463,9 +472,10 @@ def initialize: (?results: Array[BatchCrawlResult], ?total_count: Integer, ?comp
|
|
|
463
472
|
|
|
464
473
|
class SsrfPolicy
|
|
465
474
|
attr_accessor deny_private: bool?
|
|
475
|
+
attr_accessor allowlist: Array[HostMatcher]?
|
|
466
476
|
attr_accessor max_redirects: Integer?
|
|
467
477
|
|
|
468
|
-
|
|
478
|
+
def initialize: (?deny_private: bool, ?allowlist: Array[HostMatcher], ?max_redirects: Integer) -> void
|
|
469
479
|
def self.default: () -> SsrfPolicy
|
|
470
480
|
def self.from_env: () -> SsrfPolicy
|
|
471
481
|
end
|
|
@@ -482,6 +492,10 @@ def initialize: (?results: Array[BatchCrawlResult], ?total_count: Integer, ?comp
|
|
|
482
492
|
type value = :chromiumoxide | :native
|
|
483
493
|
end
|
|
484
494
|
|
|
495
|
+
class DocumentContentEncoding
|
|
496
|
+
type value = :base64
|
|
497
|
+
end
|
|
498
|
+
|
|
485
499
|
class AuthConfig
|
|
486
500
|
end
|
|
487
501
|
|
|
@@ -511,6 +525,9 @@ def initialize: (?results: Array[BatchCrawlResult], ?total_count: Integer, ?comp
|
|
|
511
525
|
type value = :up | :down
|
|
512
526
|
end
|
|
513
527
|
|
|
528
|
+
class HostMatcher
|
|
529
|
+
end
|
|
530
|
+
|
|
514
531
|
def self.generate_citations: (String markdown) -> CitationResult
|
|
515
532
|
|
|
516
533
|
def self.create_engine: (?CrawlConfig config) -> CrawlEngineHandle
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: crawlberg
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.1
|
|
4
|
+
version: 1.2.1
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Xberg Team
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2026-08-
|
|
11
|
+
date: 2026-08-11 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: rb_sys
|