optic14n 2.1.0 → 3.0.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/.github/dependabot.yml +10 -0
- data/.github/pull_request_template.md +1 -0
- data/.github/workflows/autorelease.yml +10 -0
- data/.github/workflows/ci.yml +45 -0
- data/.govuk_dependabot_merger.yml +7 -0
- data/.ruby-version +1 -1
- data/CHANGELOG.md +11 -0
- data/README.md +4 -0
- data/Rakefile +6 -9
- data/lib/optic14n/version.rb +1 -1
- data/lib/uri/bluri.rb +5 -9
- data/lib/uri/query_hash.rb +1 -1
- data/optic14n.gemspec +6 -5
- data/spec/c14n_spec.rb +16 -18
- data/spec/canonicalized_urls_spec.rb +2 -2
- metadata +15 -10
- data/Jenkinsfile +0 -9
- /data/{LICENSE.txt → LICENCE} +0 -0
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b539e842a367753aa0532242ca905914bb21803c4b7817ce89459ecf037e783b
|
4
|
+
data.tar.gz: 6afa30fb438610df8e7db8dd667c46cdfe40a564cd4f1b2b6df5c31e88390d22
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9d79b734cb02f8e31a5a72decda4353a5bbd2061709bb74d59857738cd8df3741e5ecd9f1531de866da3501aa2337874c56295122e224759f99300e95dd30cdf
|
7
|
+
data.tar.gz: 12c7bbbcda19a084a3526d07ac4dc3bf1fad4374efede88c668d815cd630bb50c6b816442f99a513d867a2cdf6bd8b730a18c4caf071dbb41b238f3d7957c8dd
|
@@ -0,0 +1 @@
|
|
1
|
+
This repo is owned by the publishing platform team. Please let us know in #govuk-publishing-platform when you raise any PRs.
|
@@ -0,0 +1,10 @@
|
|
1
|
+
on:
|
2
|
+
workflow_dispatch: {}
|
3
|
+
schedule:
|
4
|
+
- cron: '30 10 * * 1-5' # 10:30am UTC, Mon-Fri.
|
5
|
+
|
6
|
+
jobs:
|
7
|
+
autorelease:
|
8
|
+
uses: alphagov/govuk-infrastructure/.github/workflows/autorelease-rubygem.yml@main
|
9
|
+
secrets:
|
10
|
+
GH_TOKEN: ${{ secrets.GOVUK_CI_GITHUB_API_TOKEN }}
|
@@ -0,0 +1,45 @@
|
|
1
|
+
on: [push, pull_request]
|
2
|
+
|
3
|
+
jobs:
|
4
|
+
codeql-sast:
|
5
|
+
name: CodeQL SAST scan
|
6
|
+
uses: alphagov/govuk-infrastructure/.github/workflows/codeql-analysis.yml@main
|
7
|
+
permissions:
|
8
|
+
security-events: write
|
9
|
+
|
10
|
+
dependency-review:
|
11
|
+
name: Dependency Review scan
|
12
|
+
uses: alphagov/govuk-infrastructure/.github/workflows/dependency-review.yml@main
|
13
|
+
|
14
|
+
# This matrix job runs the test suite against multiple Ruby versions
|
15
|
+
test_matrix:
|
16
|
+
strategy:
|
17
|
+
fail-fast: false
|
18
|
+
matrix:
|
19
|
+
ruby: [3.1, 3.2, 3.3]
|
20
|
+
runs-on: ubuntu-latest
|
21
|
+
steps:
|
22
|
+
- uses: actions/checkout@v4
|
23
|
+
- uses: ruby/setup-ruby@v1
|
24
|
+
with:
|
25
|
+
ruby-version: ${{ matrix.ruby }}
|
26
|
+
bundler-cache: true
|
27
|
+
- run: bundle exec rake
|
28
|
+
|
29
|
+
# Branch protection rules cannot directly depend on status checks from matrix jobs.
|
30
|
+
# So instead we define `test` as a dummy job which only runs after the preceding `test_matrix` checks have passed.
|
31
|
+
# Solution inspired by: https://github.community/t/status-check-for-a-matrix-jobs/127354/3
|
32
|
+
test:
|
33
|
+
needs: test_matrix
|
34
|
+
runs-on: ubuntu-latest
|
35
|
+
steps:
|
36
|
+
- run: echo "All matrix tests have passed 🚀"
|
37
|
+
|
38
|
+
publish:
|
39
|
+
needs: test
|
40
|
+
if: ${{ github.ref == 'refs/heads/main' }}
|
41
|
+
permissions:
|
42
|
+
contents: write
|
43
|
+
uses: alphagov/govuk-infrastructure/.github/workflows/publish-rubygem.yml@main
|
44
|
+
secrets:
|
45
|
+
GEM_HOST_API_KEY: ${{ secrets.ALPHAGOV_RUBYGEMS_API_KEY }}
|
data/.ruby-version
CHANGED
@@ -1 +1 @@
|
|
1
|
-
|
1
|
+
3.1.4
|
data/CHANGELOG.md
ADDED
data/README.md
CHANGED
data/Rakefile
CHANGED
@@ -1,15 +1,12 @@
|
|
1
1
|
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), "..", "lib"))
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
RSpec::Core::RakeTask.new(:spec)
|
6
|
-
rescue LoadError
|
7
|
-
puts "Running in production mode"
|
8
|
-
end
|
9
|
-
|
3
|
+
require "rspec/core/rake_task"
|
4
|
+
require "rubocop/rake_task"
|
10
5
|
require "bundler/gem_tasks"
|
11
6
|
require "optic14n"
|
12
7
|
Dir.glob("lib/tasks/*.rake").each { |r| import r }
|
13
8
|
|
14
|
-
|
15
|
-
|
9
|
+
RuboCop::RakeTask.new
|
10
|
+
RSpec::Core::RakeTask.new(:spec)
|
11
|
+
|
12
|
+
task default: %i[rubocop spec]
|
data/lib/optic14n/version.rb
CHANGED
data/lib/uri/bluri.rb
CHANGED
@@ -1,5 +1,3 @@
|
|
1
|
-
# encoding: utf-8
|
2
|
-
|
3
1
|
module URI
|
4
2
|
##
|
5
3
|
# A URI class with a bit extra for canonicalising query strings
|
@@ -21,13 +19,13 @@ module URI
|
|
21
19
|
"%21" => "!",
|
22
20
|
}.freeze
|
23
21
|
|
24
|
-
REQUIRE_REGEX_ESCAPE =
|
22
|
+
REQUIRE_REGEX_ESCAPE = [".", "|", "(", ")", "[", "]", "{", "}", "+", " ^", "$", "*", "?"] & PATH_ESCAPE_MAPPINGS.keys
|
25
23
|
|
26
24
|
extend Forwardable
|
27
25
|
|
28
26
|
def_delegators :@uri, :scheme, :path, :host, :host=, :query, :fragment, :to_s
|
29
27
|
|
30
|
-
def initialize(uri_str)
|
28
|
+
def initialize(uri_str) # rubocop:disable Lint/MissingSuper - This class seems a reimplementation rather than an ancestor
|
31
29
|
@uri = ::Addressable::URI.parse(uri_str)
|
32
30
|
|
33
31
|
raise URI::InvalidURIError, "'#{uri_str}' not a valid URI" unless valid_uri?
|
@@ -40,7 +38,7 @@ module URI
|
|
40
38
|
end
|
41
39
|
|
42
40
|
def query_hash
|
43
|
-
@query_hash ||= CGI
|
41
|
+
@query_hash ||= CGI.parse(query || "").tap do |query_hash|
|
44
42
|
# By default, CGI::parse produces lots of arrays. Usually they have a single element
|
45
43
|
# in them. That's correct but not terribly usable. Fix it here.
|
46
44
|
query_hash.each_pair { |k, v| query_hash[k] = v[0] if v.length == 1 }
|
@@ -68,7 +66,7 @@ module URI
|
|
68
66
|
end
|
69
67
|
|
70
68
|
def has_query?
|
71
|
-
%w
|
69
|
+
%w[http https].include?(@uri.scheme) && query
|
72
70
|
end
|
73
71
|
|
74
72
|
def canonicalize!(options = {})
|
@@ -103,7 +101,7 @@ module URI
|
|
103
101
|
REQUIRE_REGEX_ESCAPE.include?(char) ? "\\#{char}" : char
|
104
102
|
end
|
105
103
|
|
106
|
-
Regexp.new("[
|
104
|
+
Regexp.new("[#{escaped_characters_for_regex.join}]")
|
107
105
|
end
|
108
106
|
end
|
109
107
|
|
@@ -124,7 +122,5 @@ module Kernel
|
|
124
122
|
end
|
125
123
|
# rubocop:enable Naming/MethodName
|
126
124
|
|
127
|
-
# rubocop:disable Style/AccessModifierDeclarations
|
128
125
|
module_function :BLURI
|
129
|
-
# rubocop:enable Style/AccessModifierDeclarations
|
130
126
|
end
|
data/lib/uri/query_hash.rb
CHANGED
data/optic14n.gemspec
CHANGED
@@ -1,5 +1,4 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
require "English"
|
3
2
|
lib = File.expand_path("lib", __dir__)
|
4
3
|
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
5
4
|
require "optic14n/version"
|
@@ -14,14 +13,16 @@ Gem::Specification.new do |spec|
|
|
14
13
|
spec.homepage = "https://github.com/alphagov/optic14n"
|
15
14
|
spec.license = "MIT"
|
16
15
|
|
17
|
-
spec.
|
16
|
+
spec.required_ruby_version = ">= 3.1.4"
|
17
|
+
|
18
|
+
spec.files = `git ls-files`.split($INPUT_RECORD_SEPARATOR)
|
18
19
|
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
19
20
|
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
20
|
-
spec.require_paths = %w
|
21
|
+
spec.require_paths = %w[lib]
|
21
22
|
|
22
23
|
spec.add_dependency "addressable", "~> 2.7"
|
23
24
|
|
24
25
|
spec.add_development_dependency "rake"
|
25
26
|
spec.add_development_dependency "rspec"
|
26
|
-
spec.add_development_dependency "rubocop-govuk", "
|
27
|
+
spec.add_development_dependency "rubocop-govuk", "5.0.3"
|
27
28
|
end
|
data/spec/c14n_spec.rb
CHANGED
@@ -1,5 +1,3 @@
|
|
1
|
-
# encoding: utf-8
|
2
|
-
|
3
1
|
require "spec_helper"
|
4
2
|
|
5
3
|
describe "Paul's tests, translated from Perl" do
|
@@ -67,8 +65,8 @@ describe "Paul's tests, translated from Perl" do
|
|
67
65
|
end
|
68
66
|
it "decodes non-reserved characters (! and ~)" do
|
69
67
|
# My god, it's full of stars
|
70
|
-
expect(BLURI("http://www.example.com/%7eyes%20I%20have%20now%20read%20%5brfc%203986%5d%2C%20%26%20I%27m%20a%20%3Dlot%3D%20more%20reassured%21%21")
|
71
|
-
canonicalize!.to_s).to eq("http://www.example.com/~yes%20i%20have%20now%20read%20%5brfc%203986%5d%2c%20%26%20i%27m%20a%20%3dlot%3d%20more%20reassured!!")
|
68
|
+
expect(BLURI("http://www.example.com/%7eyes%20I%20have%20now%20read%20%5brfc%203986%5d%2C%20%26%20I%27m%20a%20%3Dlot%3D%20more%20reassured%21%21")
|
69
|
+
.canonicalize!.to_s).to eq("http://www.example.com/~yes%20i%20have%20now%20read%20%5brfc%203986%5d%2c%20%26%20i%27m%20a%20%3dlot%3d%20more%20reassured!!")
|
72
70
|
end
|
73
71
|
it "encodes pound signs" do
|
74
72
|
expect(BLURI("https://www.example.com/pound-sign-£").canonicalize!.to_s).to eq("http://www.example.com/pound-sign-%c2%a3")
|
@@ -93,8 +91,8 @@ describe "Paul's tests, translated from Perl" do
|
|
93
91
|
)
|
94
92
|
end
|
95
93
|
it "sorts query string values" do
|
96
|
-
expect(BLURI("http://www.example.com?c=23&d=1&b=909&e=33&a=1")
|
97
|
-
canonicalize!(allow_query: %i[b e c d a]).to_s).to eq("http://www.example.com?a=1&b=909&c=23&d=1&e=33")
|
94
|
+
expect(BLURI("http://www.example.com?c=23&d=1&b=909&e=33&a=1")
|
95
|
+
.canonicalize!(allow_query: %i[b e c d a]).to_s).to eq("http://www.example.com?a=1&b=909&c=23&d=1&e=33")
|
98
96
|
end
|
99
97
|
it "encodes querystring values" do
|
100
98
|
expect(BLURI("http://www.example.com?a=you're_dangerous").canonicalize!(allow_query: :all).to_s).to eq(
|
@@ -107,16 +105,16 @@ describe "Paul's tests, translated from Perl" do
|
|
107
105
|
)
|
108
106
|
end
|
109
107
|
it "converts matrix URI to query_string" do
|
110
|
-
expect(BLURI("http://www.example.com?c=23;d=1;b=909;e=33;a=1")
|
111
|
-
canonicalize!(allow_query: %i[b e c d a]).to_s).to eq("http://www.example.com?a=1&b=909&c=23&d=1&e=33")
|
108
|
+
expect(BLURI("http://www.example.com?c=23;d=1;b=909;e=33;a=1")
|
109
|
+
.canonicalize!(allow_query: %i[b e c d a]).to_s).to eq("http://www.example.com?a=1&b=909&c=23&d=1&e=33")
|
112
110
|
end
|
113
111
|
it "sorts cherry-picked query string arguments" do
|
114
|
-
expect(BLURI("http://www.example.com?a=2322sdfsf&topic=334499&q=909&item=23444")
|
115
|
-
canonicalize!(allow_query: %i[topic item]).to_s).to eq("http://www.example.com?item=23444&topic=334499")
|
112
|
+
expect(BLURI("http://www.example.com?a=2322sdfsf&topic=334499&q=909&item=23444")
|
113
|
+
.canonicalize!(allow_query: %i[topic item]).to_s).to eq("http://www.example.com?item=23444&topic=334499")
|
116
114
|
end
|
117
115
|
it "ignores empty querystring values" do
|
118
|
-
expect(BLURI("http://www.example.com?a=2322sdfsf&topic=334499&q=909&item=23444")
|
119
|
-
canonicalize!(allow_query: %w
|
116
|
+
expect(BLURI("http://www.example.com?a=2322sdfsf&topic=334499&q=909&item=23444")
|
117
|
+
.canonicalize!(allow_query: %w[foo bar baz]).to_s).to eq("http://www.example.com")
|
120
118
|
end
|
121
119
|
|
122
120
|
describe "querystrings that are not an HTML-encoded thing" do
|
@@ -174,15 +172,15 @@ describe "Paul's tests, translated from Perl" do
|
|
174
172
|
describe "the treatment of query strings when there are query string octets that unescape to "\
|
175
173
|
"invalid UTF-8 sequences (we no longer treat these as failures)" do
|
176
174
|
it "no longer raises exceptions when there are bad things in query values" do
|
177
|
-
expect(BLURI("http://example.com/path?view=%ED")
|
178
|
-
canonicalize!(allow_query: :all)
|
179
|
-
to_s).to eql("http://example.com/path?view=%ED")
|
175
|
+
expect(BLURI("http://example.com/path?view=%ED")
|
176
|
+
.canonicalize!(allow_query: :all)
|
177
|
+
.to_s).to eql("http://example.com/path?view=%ED")
|
180
178
|
end
|
181
179
|
|
182
180
|
it "re-encodes correctly when there are bad things in query keys" do
|
183
|
-
expect(BLURI("http://example.com/path?%ED=view")
|
184
|
-
canonicalize!(allow_query: :all)
|
185
|
-
to_s).to eql("http://example.com/path?%ED=view")
|
181
|
+
expect(BLURI("http://example.com/path?%ED=view")
|
182
|
+
.canonicalize!(allow_query: :all)
|
183
|
+
.to_s).to eql("http://example.com/path?%ED=view")
|
186
184
|
end
|
187
185
|
|
188
186
|
it "does not error when there are bad things in query keys when allow_query isn't :all" do
|
@@ -3,14 +3,14 @@ require "spec_helper"
|
|
3
3
|
describe Optic14n::CanonicalizedUrls do
|
4
4
|
describe "c14nize" do
|
5
5
|
let(:test_urls) do
|
6
|
-
%w
|
6
|
+
%w[
|
7
7
|
http://www.qhm.mod.uk/portsmouth/leisure/fuel
|
8
8
|
http://www.qhm.mod.uk/portsmouth/leisure/lntm?
|
9
9
|
http://www.qhm.mod.uk/portsmouth/leisure/lntm?action=view
|
10
10
|
http://www.qhm.mod.uk/portsmouth/leisure/lntm?action=view&id=199
|
11
11
|
http://unistats.direct.gov.uk/searchResults.do?pname=institutesearchresults&level3Subjects=L3.90%AC10007761%ACFIRSTDEGREE%ACFulltime%AC430%ACNo%AC60%ACYes%AC83%ACNo%ACYes
|
12
12
|
1234://123
|
13
|
-
|
13
|
+
]
|
14
14
|
end
|
15
15
|
|
16
16
|
context "options[:allow_query] is false" do
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: optic14n
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 3.0.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- GOV.UK Dev
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2024-11-27 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: addressable
|
@@ -56,16 +56,16 @@ dependencies:
|
|
56
56
|
name: rubocop-govuk
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
58
58
|
requirements:
|
59
|
-
- -
|
59
|
+
- - '='
|
60
60
|
- !ruby/object:Gem::Version
|
61
|
-
version:
|
61
|
+
version: 5.0.3
|
62
62
|
type: :development
|
63
63
|
prerelease: false
|
64
64
|
version_requirements: !ruby/object:Gem::Requirement
|
65
65
|
requirements:
|
66
|
-
- -
|
66
|
+
- - '='
|
67
67
|
- !ruby/object:Gem::Version
|
68
|
-
version:
|
68
|
+
version: 5.0.3
|
69
69
|
description: Canonicalises URLs.
|
70
70
|
email:
|
71
71
|
- govuk-dev@digital.cabinet-office.gov.uk
|
@@ -73,12 +73,17 @@ executables: []
|
|
73
73
|
extensions: []
|
74
74
|
extra_rdoc_files: []
|
75
75
|
files:
|
76
|
+
- ".github/dependabot.yml"
|
77
|
+
- ".github/pull_request_template.md"
|
78
|
+
- ".github/workflows/autorelease.yml"
|
79
|
+
- ".github/workflows/ci.yml"
|
76
80
|
- ".gitignore"
|
81
|
+
- ".govuk_dependabot_merger.yml"
|
77
82
|
- ".rubocop.yml"
|
78
83
|
- ".ruby-version"
|
84
|
+
- CHANGELOG.md
|
79
85
|
- Gemfile
|
80
|
-
-
|
81
|
-
- LICENSE.txt
|
86
|
+
- LICENCE
|
82
87
|
- README.md
|
83
88
|
- Rakefile
|
84
89
|
- lib/optic14n.rb
|
@@ -107,14 +112,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
107
112
|
requirements:
|
108
113
|
- - ">="
|
109
114
|
- !ruby/object:Gem::Version
|
110
|
-
version:
|
115
|
+
version: 3.1.4
|
111
116
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
112
117
|
requirements:
|
113
118
|
- - ">="
|
114
119
|
- !ruby/object:Gem::Version
|
115
120
|
version: '0'
|
116
121
|
requirements: []
|
117
|
-
rubygems_version: 3.
|
122
|
+
rubygems_version: 3.5.23
|
118
123
|
signing_key:
|
119
124
|
specification_version: 4
|
120
125
|
summary: Specifically, HTTP URLs, for a limited purpose
|
data/Jenkinsfile
DELETED
/data/{LICENSE.txt → LICENCE}
RENAMED
File without changes
|