jira-ruby 3.1.0 → 3.2.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/jira-ruby.gemspec +1 -1
- data/lib/jira/atlassian/jwt.rb +76 -0
- data/lib/jira/client.rb +10 -2
- data/lib/jira/jwt_client.rb +2 -2
- data/lib/jira/resource/attachment.rb +17 -2
- data/lib/jira/resource/comment.rb +12 -0
- data/lib/jira/resource/createmeta.rb +4 -4
- data/lib/jira/resource/issue.rb +1 -0
- data/lib/jira/resource/properties.rb +56 -0
- data/lib/jira/resource/worklog.rb +12 -0
- data/lib/jira/version.rb +1 -1
- data/lib/jira-ruby.rb +1 -0
- data/spec/data/files/jwt-signed-urls.json +317 -0
- data/spec/integration/properties_spec.rb +45 -0
- data/spec/integration/transition_spec.rb +3 -2
- data/spec/integration/webhook_spec.rb +4 -2
- data/spec/jira/atlassian/jwt_spec.rb +60 -0
- data/spec/jira/resource/issue_spec.rb +5 -1
- data/spec/mock_responses/issue/10002/properties/foo.json +4 -0
- data/spec/mock_responses/issue/10002/properties/xyz.json +4 -0
- data/spec/mock_responses/issue/10002/properties/xyz.put.json +4 -0
- data/spec/mock_responses/issue/10002/properties.json +12 -0
- data/spec/support/clients_helper.rb +3 -3
- data/spec/support/shared_examples/integration.rb +34 -38
- metadata +16 -9
- data/spec/mock_responses/jira/rest/webhooks/1.0/webhook.json +0 -11
- data/spec/mock_responses/webhook/webhook.json +0 -11
- /data/spec/mock_responses/{jira/rest/webhooks/1.0/webhook → webhook}/2.json +0 -0
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 4a043cafa57aad32acfda37495a8419b4511581786620049cb6264a05265aefb
|
|
4
|
+
data.tar.gz: 2c3b66dd69faaef351e043b10c62f3cfd7662e003905363db6bdbf458bfb10b1
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 677a496c74235ea213ac92416b9dfb303e56bc04ea94b617134925ce744c25bd81583b2516a342c347a935959795c35813245499efcf2c058b075d308ef51454
|
|
7
|
+
data.tar.gz: ef42dd385a24ff73526e8e2d21fedb0af60832444f9d1e43c0c23a1cca58da61751a24901430abf0650cffacdd7b41ff28fa7620deb195ede7081af504eb4295
|
data/jira-ruby.gemspec
CHANGED
|
@@ -23,8 +23,8 @@ Gem::Specification.new do |s|
|
|
|
23
23
|
s.require_paths = ['lib']
|
|
24
24
|
|
|
25
25
|
s.add_dependency 'activesupport'
|
|
26
|
-
s.add_dependency 'atlassian-jwt'
|
|
27
26
|
s.add_dependency 'cgi'
|
|
27
|
+
s.add_dependency 'jwt', '>= 2.1'
|
|
28
28
|
s.add_dependency 'multipart-post'
|
|
29
29
|
s.add_dependency 'oauth', '~> 1.0'
|
|
30
30
|
end
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Copyright 2013 Atlassian Pty Ltd.
|
|
4
|
+
#
|
|
5
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
6
|
+
# you may not use this file except in compliance with the License.
|
|
7
|
+
# You may obtain a copy of the License at
|
|
8
|
+
#
|
|
9
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
#
|
|
11
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
12
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
13
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
+
# See the License for the specific language governing permissions and
|
|
15
|
+
# limitations under the License.
|
|
16
|
+
|
|
17
|
+
require 'jwt'
|
|
18
|
+
require 'uri'
|
|
19
|
+
require 'cgi'
|
|
20
|
+
|
|
21
|
+
module JIRA
|
|
22
|
+
module Atlassian
|
|
23
|
+
module Jwt
|
|
24
|
+
class << self
|
|
25
|
+
CANONICAL_QUERY_SEPARATOR = '&'
|
|
26
|
+
ESCAPED_CANONICAL_QUERY_SEPARATOR = '%26'
|
|
27
|
+
|
|
28
|
+
def create_canonical_request(uri, http_method, base_uri)
|
|
29
|
+
uri = URI.parse(uri) unless uri.is_a? URI
|
|
30
|
+
base_uri = URI.parse(base_uri) unless base_uri.is_a? URI
|
|
31
|
+
|
|
32
|
+
[
|
|
33
|
+
http_method.upcase,
|
|
34
|
+
canonicalize_uri(uri, base_uri),
|
|
35
|
+
canonicalize_query_string(uri.query)
|
|
36
|
+
].join(CANONICAL_QUERY_SEPARATOR)
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def build_claims(issuer, url, http_method, base_url = '', issued_at = nil, expires = nil, attributes = {}) # rubocop:disable Metrics/ParameterLists
|
|
40
|
+
issued_at ||= Time.now.to_i
|
|
41
|
+
expires ||= issued_at + 60
|
|
42
|
+
qsh = Digest::SHA256.hexdigest(create_canonical_request(url, http_method, base_url))
|
|
43
|
+
|
|
44
|
+
{
|
|
45
|
+
iss: issuer,
|
|
46
|
+
iat: issued_at,
|
|
47
|
+
exp: expires,
|
|
48
|
+
qsh: qsh
|
|
49
|
+
}.merge(attributes)
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def canonicalize_uri(uri, base_uri)
|
|
53
|
+
path = uri.path.sub(/^#{base_uri.path}/, '')
|
|
54
|
+
path = '/' if path.nil? || path.empty?
|
|
55
|
+
path = "/#{path}" unless path.start_with? '/'
|
|
56
|
+
path.chomp!('/') if path.length > 1
|
|
57
|
+
path.gsub(CANONICAL_QUERY_SEPARATOR, ESCAPED_CANONICAL_QUERY_SEPARATOR)
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def canonicalize_query_string(query)
|
|
61
|
+
return '' if query.nil? || query.empty?
|
|
62
|
+
|
|
63
|
+
query = CGI.parse(query)
|
|
64
|
+
query.delete('jwt')
|
|
65
|
+
query.each do |k, v|
|
|
66
|
+
query[k] = v.map { |a| CGI.escape a }.join(',') if v.is_a? Array
|
|
67
|
+
query[k].gsub!('+', '%20') # Use %20, not CGI.escape default of "+"
|
|
68
|
+
query[k].gsub!('%7E', '~') # Unescape "~" per JS tests
|
|
69
|
+
end
|
|
70
|
+
query = query.sort.to_h
|
|
71
|
+
query.map { |k, v| "#{CGI.escape k}=#{v}" }.join(CANONICAL_QUERY_SEPARATOR)
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
end
|
data/lib/jira/client.rb
CHANGED
|
@@ -302,6 +302,10 @@ module JIRA
|
|
|
302
302
|
JIRA::Resource::AgileFactory.new(self)
|
|
303
303
|
end
|
|
304
304
|
|
|
305
|
+
def Properties
|
|
306
|
+
JIRA::Resource::PropertiesFactory.new(self)
|
|
307
|
+
end
|
|
308
|
+
|
|
305
309
|
# HTTP methods without a body
|
|
306
310
|
|
|
307
311
|
# Make an HTTP DELETE request
|
|
@@ -351,7 +355,9 @@ module JIRA
|
|
|
351
355
|
# @raise [JIRA::HTTPError] If the response is not an HTTP success code
|
|
352
356
|
def post_multipart(path, file, headers = {})
|
|
353
357
|
puts "post multipart: #{path} - [#{file}]" if @http_debug
|
|
354
|
-
@request_client.request_multipart(path, file, merge_default_headers(headers))
|
|
358
|
+
res = @request_client.request_multipart(path, file, merge_default_headers(headers))
|
|
359
|
+
puts "response: #{res}" if @http_debug
|
|
360
|
+
res
|
|
355
361
|
end
|
|
356
362
|
|
|
357
363
|
# Make an HTTP PUT request
|
|
@@ -375,7 +381,9 @@ module JIRA
|
|
|
375
381
|
# @raise [JIRA::HTTPError] If the response is not an HTTP success code
|
|
376
382
|
def request(http_method, path, body = '', headers = {})
|
|
377
383
|
puts "#{http_method}: #{path} - [#{body}]" if @http_debug
|
|
378
|
-
@request_client.request(http_method, path, body, headers)
|
|
384
|
+
res = @request_client.request(http_method, path, body, headers)
|
|
385
|
+
puts "response: #{res}" if @http_debug
|
|
386
|
+
res
|
|
379
387
|
end
|
|
380
388
|
|
|
381
389
|
# @private
|
data/lib/jira/jwt_client.rb
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require 'atlassian/jwt'
|
|
3
|
+
require 'jira/atlassian/jwt'
|
|
4
4
|
|
|
5
5
|
module JIRA
|
|
6
6
|
class JwtClient < HttpClient
|
|
@@ -29,7 +29,7 @@ module JIRA
|
|
|
29
29
|
end
|
|
30
30
|
|
|
31
31
|
def build_jwt(url)
|
|
32
|
-
claim = Atlassian::Jwt.build_claims \
|
|
32
|
+
claim = JIRA::Atlassian::Jwt.build_claims \
|
|
33
33
|
@options[:issuer],
|
|
34
34
|
url,
|
|
35
35
|
http_method.to_s,
|
|
@@ -146,10 +146,14 @@ module JIRA
|
|
|
146
146
|
# @raise [JIRA::HTTPError] if failed
|
|
147
147
|
def save!(attrs, path = url)
|
|
148
148
|
file = attrs['file'] || attrs[:file] # Keep supporting 'file' parameter as a string for backward compatibility
|
|
149
|
-
|
|
149
|
+
# If :filename does not exist or is nil, that is fine as it will force
|
|
150
|
+
# Upload to determine the filename automatically from file.
|
|
151
|
+
# Breaking the filename out allows this to support any IO-based file parameter.
|
|
152
|
+
fname = attrs['filename'] || attrs[:filename]
|
|
153
|
+
mime_type = attrs['mimeType'] || attrs[:mimeType] || 'application/binary'
|
|
150
154
|
|
|
151
155
|
headers = { 'X-Atlassian-Token' => 'nocheck' }
|
|
152
|
-
data = { 'file' => Multipart::Post::UploadIO.new(file, mime_type,
|
|
156
|
+
data = { 'file' => Multipart::Post::UploadIO.new(file, mime_type, fname) }
|
|
153
157
|
|
|
154
158
|
response = client.post_multipart(path, data, headers)
|
|
155
159
|
|
|
@@ -159,6 +163,17 @@ module JIRA
|
|
|
159
163
|
true
|
|
160
164
|
end
|
|
161
165
|
|
|
166
|
+
def http_download
|
|
167
|
+
# Actually fetch the attachment
|
|
168
|
+
# Note: Jira handles attachment's weird!
|
|
169
|
+
# Typically, they respond with a redirect location that should not have the same authentication
|
|
170
|
+
client.get(attrs['content'])
|
|
171
|
+
rescue JIRA::HTTPError => e
|
|
172
|
+
raise e unless e.response.code =~ /\A3\d\d\z/ && e.response['location'].present?
|
|
173
|
+
|
|
174
|
+
Net::HTTP.get_response(URI(e.response['location']))
|
|
175
|
+
end
|
|
176
|
+
|
|
162
177
|
private
|
|
163
178
|
|
|
164
179
|
def set_attributes(attributes, response)
|
|
@@ -9,6 +9,18 @@ module JIRA
|
|
|
9
9
|
belongs_to :issue
|
|
10
10
|
|
|
11
11
|
nested_collections true
|
|
12
|
+
|
|
13
|
+
def self.all(client, options = {})
|
|
14
|
+
issue = options[:issue]
|
|
15
|
+
raise ArgumentError, 'parent issue is required' unless issue
|
|
16
|
+
|
|
17
|
+
response = client.get("#{issue.url}/#{endpoint_name}")
|
|
18
|
+
json = parse_json(response.body)
|
|
19
|
+
json = json[endpoint_name.pluralize]
|
|
20
|
+
json.map do |attrs|
|
|
21
|
+
new(client, { attrs: }.merge(options))
|
|
22
|
+
end
|
|
23
|
+
end
|
|
12
24
|
end
|
|
13
25
|
end
|
|
14
26
|
end
|
|
@@ -12,22 +12,22 @@ module JIRA
|
|
|
12
12
|
|
|
13
13
|
def self.all(client, params = {})
|
|
14
14
|
if params.key?(:projectKeys)
|
|
15
|
-
values = Array(params[:projectKeys]).map { |i|
|
|
15
|
+
values = Array(params[:projectKeys]).map { |i| i.is_a?(JIRA::Resource::Project) ? i.key : i }
|
|
16
16
|
params[:projectKeys] = values.join(',')
|
|
17
17
|
end
|
|
18
18
|
|
|
19
19
|
if params.key?(:projectIds)
|
|
20
|
-
values = Array(params[:projectIds]).map { |i|
|
|
20
|
+
values = Array(params[:projectIds]).map { |i| i.is_a?(JIRA::Resource::Project) ? i.id : i }
|
|
21
21
|
params[:projectIds] = values.join(',')
|
|
22
22
|
end
|
|
23
23
|
|
|
24
24
|
if params.key?(:issuetypeNames)
|
|
25
|
-
values = Array(params[:issuetypeNames]).map { |i|
|
|
25
|
+
values = Array(params[:issuetypeNames]).map { |i| i.is_a?(JIRA::Resource::Issuetype) ? i.name : i }
|
|
26
26
|
params[:issuetypeNames] = values.join(',')
|
|
27
27
|
end
|
|
28
28
|
|
|
29
29
|
if params.key?(:issuetypeIds)
|
|
30
|
-
values = Array(params[:issuetypeIds]).map { |i|
|
|
30
|
+
values = Array(params[:issuetypeIds]).map { |i| i.is_a?(JIRA::Resource::Issuetype) ? i.id : i }
|
|
31
31
|
params[:issuetypeIds] = values.join(',')
|
|
32
32
|
end
|
|
33
33
|
|
data/lib/jira/resource/issue.rb
CHANGED
|
@@ -57,6 +57,7 @@ module JIRA
|
|
|
57
57
|
has_many :issuelinks, nested_under: 'fields'
|
|
58
58
|
has_many :remotelink, class: JIRA::Resource::Remotelink
|
|
59
59
|
has_many :watchers, attribute_key: 'watches', nested_under: %w[fields watches]
|
|
60
|
+
has_many :properties, class: JIRA::Resource::Properties
|
|
60
61
|
|
|
61
62
|
# Get collection of issues.
|
|
62
63
|
# @param client [JIRA::Client]
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'active_support/inflector'
|
|
4
|
+
|
|
5
|
+
module JIRA
|
|
6
|
+
module Resource
|
|
7
|
+
class PropertiesFactory < JIRA::BaseFactory # :nodoc:
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
class Properties < JIRA::Base
|
|
11
|
+
belongs_to :issue
|
|
12
|
+
|
|
13
|
+
def self.key_attribute
|
|
14
|
+
:key
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def self.all(client, options = {})
|
|
18
|
+
issue = options[:issue]
|
|
19
|
+
raise ArgumentError, 'parent issue is required' unless issue
|
|
20
|
+
|
|
21
|
+
response = client.get("#{issue.url}/#{endpoint_name}")
|
|
22
|
+
json = parse_json(response.body)
|
|
23
|
+
json[key_attribute.to_s.pluralize].map do |attrs|
|
|
24
|
+
## Net get the individual property
|
|
25
|
+
self_response = client.get(attrs['self'])
|
|
26
|
+
property = parse_json(self_response.body)
|
|
27
|
+
## Make sure to build the new resource via the issue.properties in order to support the has_many proxy
|
|
28
|
+
issue.properties.build(property)
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
## Override save so we can handle the required attrs (and default 'value' when appropriate)
|
|
33
|
+
def save!(attrs = {}, path = nil)
|
|
34
|
+
if attrs.is_a?(Hash) && attrs.key?(self.class.key_attribute.to_s)
|
|
35
|
+
raise ArgumentError, "Use of 'value' is required when '#{self.class.key_attribute}' is provided" \
|
|
36
|
+
unless attrs.key?('value')
|
|
37
|
+
|
|
38
|
+
set_attrs(self.class.key_attribute.to_s => attrs[self.class.key_attribute.to_s])
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
raise ArgumentError, "'key' is required on a new record" if new_record?
|
|
42
|
+
|
|
43
|
+
path ||= patched_url
|
|
44
|
+
## We can take either the 'value' element from the hash, OR use the entire attrs as the value
|
|
45
|
+
value = attrs.is_a?(Hash) && attrs.key?('value') ? attrs['value'] : attrs
|
|
46
|
+
value = '' if value.nil?
|
|
47
|
+
## Note: this API endpoint requires a non-empty JSON body for the value of the property
|
|
48
|
+
## Note2: this API endpoint does not return a body, so no need to call set_attrs_from_response
|
|
49
|
+
client.send(:put, path, value.to_json)
|
|
50
|
+
set_attrs({ 'value' => value }, false)
|
|
51
|
+
@expanded = false
|
|
52
|
+
true
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
end
|
|
@@ -10,6 +10,18 @@ module JIRA
|
|
|
10
10
|
has_one :update_author, class: JIRA::Resource::User, attribute_key: 'updateAuthor'
|
|
11
11
|
belongs_to :issue
|
|
12
12
|
nested_collections true
|
|
13
|
+
|
|
14
|
+
def self.all(client, options = {})
|
|
15
|
+
issue = options[:issue]
|
|
16
|
+
raise ArgumentError, 'parent issue is required' unless issue
|
|
17
|
+
|
|
18
|
+
response = client.get("#{issue.url}/#{endpoint_name}")
|
|
19
|
+
json = parse_json(response.body)
|
|
20
|
+
json = json[endpoint_name.pluralize]
|
|
21
|
+
json.map do |attrs|
|
|
22
|
+
new(client, { attrs: }.merge(options))
|
|
23
|
+
end
|
|
24
|
+
end
|
|
13
25
|
end
|
|
14
26
|
end
|
|
15
27
|
end
|
data/lib/jira/version.rb
CHANGED
data/lib/jira-ruby.rb
CHANGED
|
@@ -23,6 +23,7 @@ require 'jira/resource/status'
|
|
|
23
23
|
require 'jira/resource/status_category'
|
|
24
24
|
require 'jira/resource/transition'
|
|
25
25
|
require 'jira/resource/project'
|
|
26
|
+
require 'jira/resource/properties'
|
|
26
27
|
require 'jira/resource/priority'
|
|
27
28
|
require 'jira/resource/comment'
|
|
28
29
|
require 'jira/resource/worklog'
|
|
@@ -0,0 +1,317 @@
|
|
|
1
|
+
{
|
|
2
|
+
"secret": "7512836e-9137-48ac-baaf-a1935b96e17a",
|
|
3
|
+
"tests": [{
|
|
4
|
+
"name": "Simple",
|
|
5
|
+
"canonicalUrl": "GET\u0026/test\u0026param\u003dvalue",
|
|
6
|
+
"signedUrl": "https://example.com/test?param\u003dvalue\u0026jwt\u003deyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJxc2giOiJiZTE2OTEwODU4YTQxZmQxOWVhNWMxYjRlOWRlY2NhOWE3ODRkMTAyNGNiMDBiMjE1OGRlZmUyZjI5ZGM4NmRkIiwiY29udGV4dCI6e30sImlzcyI6ImppcmE6MTIzNC01Njc4LTkwMDAiLCJleHAiOjE0NjY3MzEyNTUsImlhdCI6MTQ2NjczMTA3NX0.ssbmLUBemh6nQW3MH5o2fSdnOFTIKf2w0KASnnH8aXo"
|
|
7
|
+
}, {
|
|
8
|
+
"name": "Simple (uri)",
|
|
9
|
+
"canonicalUrl": "GET\u0026/test\u0026param\u003dvalue",
|
|
10
|
+
"signedUrl": "https://example.com/test?param\u003dvalue\u0026jwt\u003deyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJxc2giOiJiZTE2OTEwODU4YTQxZmQxOWVhNWMxYjRlOWRlY2NhOWE3ODRkMTAyNGNiMDBiMjE1OGRlZmUyZjI5ZGM4NmRkIiwiY29udGV4dCI6e30sImlzcyI6ImppcmE6MTIzNC01Njc4LTkwMDAiLCJleHAiOjE0NjY3MzEyNTUsImlhdCI6MTQ2NjczMTA3NX0.ssbmLUBemh6nQW3MH5o2fSdnOFTIKf2w0KASnnH8aXo"
|
|
11
|
+
}, {
|
|
12
|
+
"name": "Spaces",
|
|
13
|
+
"canonicalUrl": "GET\u0026/test\u0026param\u003dsome%20spaces%20in%20this%20parameter",
|
|
14
|
+
"signedUrl": "https://example.com/test?param\u003dsome+spaces+in+this+parameter\u0026jwt\u003deyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJxc2giOiJlZjQwOTdkMDUzOTVlYWYxYTEzMzk1NmYxNDAxMTZhOWM0MTFhZmFkNzY4ZDRmMDZkYWFjOWUzMDU3NjQyNjVkIiwiY29udGV4dCI6e30sImlzcyI6ImppcmE6MTIzNC01Njc4LTkwMDAiLCJleHAiOjE0NjY3MzEyNTUsImlhdCI6MTQ2NjczMTA3NX0.JGTIXMHEtxAmLlTjIUFR21IEs9b8-3QIt3VwyRB816M"
|
|
15
|
+
}, {
|
|
16
|
+
"name": "Spaces (uri)",
|
|
17
|
+
"canonicalUrl": "GET\u0026/test\u0026param\u003dsome%20spaces%20in%20this%20parameter",
|
|
18
|
+
"signedUrl": "https://example.com/test?param\u003dsome+spaces+in+this+parameter\u0026jwt\u003deyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJxc2giOiJlZjQwOTdkMDUzOTVlYWYxYTEzMzk1NmYxNDAxMTZhOWM0MTFhZmFkNzY4ZDRmMDZkYWFjOWUzMDU3NjQyNjVkIiwiY29udGV4dCI6e30sImlzcyI6ImppcmE6MTIzNC01Njc4LTkwMDAiLCJleHAiOjE0NjY3MzEyNTUsImlhdCI6MTQ2NjczMTA3NX0.JGTIXMHEtxAmLlTjIUFR21IEs9b8-3QIt3VwyRB816M"
|
|
19
|
+
}, {
|
|
20
|
+
"name": "Asterisk",
|
|
21
|
+
"canonicalUrl": "GET\u0026/test\u0026query\u003dconnect%2A",
|
|
22
|
+
"signedUrl": "https://example.com/test?query\u003dconnect*\u0026jwt\u003deyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJxc2giOiIwZDI4YmMxMGQxOTcyZDljYWI1OWUxMjNjZTE3OTc2ZWIzMmFhZDY5NTdhMTNjZmI4Yjk3Y2VkNmQzZmM4YTI5IiwiY29udGV4dCI6e30sImlzcyI6ImppcmE6MTIzNC01Njc4LTkwMDAiLCJleHAiOjE0NjY3MzEyNTUsImlhdCI6MTQ2NjczMTA3NX0.Lj8eCYfC3mYcnkdGtvGPXT763nPI2XYyxlIJjSgIF5k"
|
|
23
|
+
}, {
|
|
24
|
+
"name": "Asterisk (uri)",
|
|
25
|
+
"canonicalUrl": "GET\u0026/test\u0026query\u003dconnect%2A",
|
|
26
|
+
"signedUrl": "https://example.com/test?query\u003dconnect*\u0026jwt\u003deyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJxc2giOiIwZDI4YmMxMGQxOTcyZDljYWI1OWUxMjNjZTE3OTc2ZWIzMmFhZDY5NTdhMTNjZmI4Yjk3Y2VkNmQzZmM4YTI5IiwiY29udGV4dCI6e30sImlzcyI6ImppcmE6MTIzNC01Njc4LTkwMDAiLCJleHAiOjE0NjY3MzEyNTUsImlhdCI6MTQ2NjczMTA3NX0.Lj8eCYfC3mYcnkdGtvGPXT763nPI2XYyxlIJjSgIF5k"
|
|
27
|
+
}, {
|
|
28
|
+
"name": "Unicode",
|
|
29
|
+
"canonicalUrl": "GET\u0026/test\u0026director\u003d%E5%AE%AE%E5%B4%8E%20%E9%A7%BF",
|
|
30
|
+
"signedUrl": "https://example.com/test?director\u003d%E5%AE%AE%E5%B4%8E+%E9%A7%BF\u0026jwt\u003deyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJxc2giOiI0NGQ2MzU0ZmZlOGY5NjM5NzJhN2ZjNTllOThiMmMzZGZlNGI0OTMyOTVjNWI4OWVkZDk3NGEzMzllNjFhYzg5IiwiY29udGV4dCI6e30sImlzcyI6ImppcmE6MTIzNC01Njc4LTkwMDAiLCJleHAiOjE0NjY3MzEyNTUsImlhdCI6MTQ2NjczMTA3NX0.oc618kGGWy6ZP6ZqDsy2Hj61OS1kqFghcaQdvCBMLhc"
|
|
31
|
+
}, {
|
|
32
|
+
"name": "Unicode (uri)",
|
|
33
|
+
"canonicalUrl": "GET\u0026/test\u0026director\u003d%E5%AE%AE%E5%B4%8E%20%E9%A7%BF",
|
|
34
|
+
"signedUrl": "https://example.com/test?director\u003d%E5%AE%AE%E5%B4%8E+%E9%A7%BF\u0026jwt\u003deyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJxc2giOiI0NGQ2MzU0ZmZlOGY5NjM5NzJhN2ZjNTllOThiMmMzZGZlNGI0OTMyOTVjNWI4OWVkZDk3NGEzMzllNjFhYzg5IiwiY29udGV4dCI6e30sImlzcyI6ImppcmE6MTIzNC01Njc4LTkwMDAiLCJleHAiOjE0NjY3MzEyNTUsImlhdCI6MTQ2NjczMTA3NX0.oc618kGGWy6ZP6ZqDsy2Hj61OS1kqFghcaQdvCBMLhc"
|
|
35
|
+
}, {
|
|
36
|
+
"name": "Comma-delimited",
|
|
37
|
+
"canonicalUrl": "GET\u0026/test\u0026ids\u003d10%2C2%2C20%2C1",
|
|
38
|
+
"signedUrl": "https://example.com/test?ids\u003d10%2C2%2C20%2C1\u0026jwt\u003deyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJxc2giOiIyZTYxN2I2NWY5NjY2NTA3ODk5OTBlNWNhYzhmZjI5NWVlNWI0NTM4MzRkMDQ3OThmNDY2ZmY2MDM1YmQ4ODI5IiwiY29udGV4dCI6e30sImlzcyI6ImppcmE6MTIzNC01Njc4LTkwMDAiLCJleHAiOjE0NjY3MzEyNTUsImlhdCI6MTQ2NjczMTA3NX0.fdIooLlQ22kaE0FA15_cS_LvOtwBj2r5y586US4WJiw"
|
|
39
|
+
}, {
|
|
40
|
+
"name": "Comma-delimited (uri)",
|
|
41
|
+
"canonicalUrl": "GET\u0026/test\u0026ids\u003d10%2C2%2C20%2C1",
|
|
42
|
+
"signedUrl": "https://example.com/test?ids\u003d10%2C2%2C20%2C1\u0026jwt\u003deyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJxc2giOiIyZTYxN2I2NWY5NjY2NTA3ODk5OTBlNWNhYzhmZjI5NWVlNWI0NTM4MzRkMDQ3OThmNDY2ZmY2MDM1YmQ4ODI5IiwiY29udGV4dCI6e30sImlzcyI6ImppcmE6MTIzNC01Njc4LTkwMDAiLCJleHAiOjE0NjY3MzEyNTUsImlhdCI6MTQ2NjczMTA3NX0.fdIooLlQ22kaE0FA15_cS_LvOtwBj2r5y586US4WJiw"
|
|
43
|
+
}, {
|
|
44
|
+
"name": "Multi-value Comma-delimited",
|
|
45
|
+
"canonicalUrl": "GET\u0026/test\u0026tuples\u003d1%2C2%2C3,6%2C5%2C4,7%2C9%2C8",
|
|
46
|
+
"signedUrl": "https://example.com/test?tuples\u003d1%2C2%2C3\u0026tuples\u003d6%2C5%2C4\u0026tuples\u003d7%2C9%2C8\u0026jwt\u003deyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJxc2giOiJmOWY2MmJiNjExOTFkZmYxYjIxOWU5YWRlOGFjMzhmY2ZhNDYyNzJlYTc2ZDk1NDU0MTBkYjY1NTlmZDhlN2JkIiwiY29udGV4dCI6e30sImlzcyI6ImppcmE6MTIzNC01Njc4LTkwMDAiLCJleHAiOjE0NjY3MzEyNTUsImlhdCI6MTQ2NjczMTA3NX0.PXOWzUEk0Be2zCEzO5W_yTvYWDOhuEQbm7t8XXctXrE"
|
|
47
|
+
}, {
|
|
48
|
+
"name": "Multi-value Comma-delimited (uri)",
|
|
49
|
+
"canonicalUrl": "GET\u0026/test\u0026tuples\u003d1%2C2%2C3,6%2C5%2C4,7%2C9%2C8",
|
|
50
|
+
"signedUrl": "https://example.com/test?tuples\u003d1%2C2%2C3\u0026tuples\u003d6%2C5%2C4\u0026tuples\u003d7%2C9%2C8\u0026jwt\u003deyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJxc2giOiJmOWY2MmJiNjExOTFkZmYxYjIxOWU5YWRlOGFjMzhmY2ZhNDYyNzJlYTc2ZDk1NDU0MTBkYjY1NTlmZDhlN2JkIiwiY29udGV4dCI6e30sImlzcyI6ImppcmE6MTIzNC01Njc4LTkwMDAiLCJleHAiOjE0NjY3MzEyNTUsImlhdCI6MTQ2NjczMTA3NX0.PXOWzUEk0Be2zCEzO5W_yTvYWDOhuEQbm7t8XXctXrE"
|
|
51
|
+
}, {
|
|
52
|
+
"name": "Plus",
|
|
53
|
+
"canonicalUrl": "GET\u0026/test\u0026title\u003d1%20%2B%201%20equals%203",
|
|
54
|
+
"signedUrl": "https://example.com/test?title\u003d1+%2B+1+equals+3\u0026jwt\u003deyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJxc2giOiJjZTBhODY2Y2UwYzM0Y2JkZTcwZGViNjNmNjkxNTE5MmY1ODUwMGQyYjQ5YjEyZTFmZmM4Y2RmOTFlZGFiYzkxIiwiY29udGV4dCI6e30sImlzcyI6ImppcmE6MTIzNC01Njc4LTkwMDAiLCJleHAiOjE0NjY3MzEyNTUsImlhdCI6MTQ2NjczMTA3NX0.NKD1M6kVQ3YFsQb-W2AUzYyntKSNvE15r4_hL9OO6A4"
|
|
55
|
+
}, {
|
|
56
|
+
"name": "Plus (uri)",
|
|
57
|
+
"canonicalUrl": "GET\u0026/test\u0026title\u003d1%20%2B%201%20equals%203",
|
|
58
|
+
"signedUrl": "https://example.com/test?title\u003d1+%2B+1+equals+3\u0026jwt\u003deyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJxc2giOiJjZTBhODY2Y2UwYzM0Y2JkZTcwZGViNjNmNjkxNTE5MmY1ODUwMGQyYjQ5YjEyZTFmZmM4Y2RmOTFlZGFiYzkxIiwiY29udGV4dCI6e30sImlzcyI6ImppcmE6MTIzNC01Njc4LTkwMDAiLCJleHAiOjE0NjY3MzEyNTUsImlhdCI6MTQ2NjczMTA3NX0.NKD1M6kVQ3YFsQb-W2AUzYyntKSNvE15r4_hL9OO6A4"
|
|
59
|
+
}, {
|
|
60
|
+
"name": "JSON Object",
|
|
61
|
+
"canonicalUrl": "GET\u0026/test\u0026json\u003d%7B%22key%22%3A%22value%22%7D",
|
|
62
|
+
"signedUrl": "https://example.com/test?json\u003d%7B%22key%22%3A%22value%22%7D\u0026jwt\u003deyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJxc2giOiIxZDc0YzVhMWYwYTZjNzJhM2NlMjg1NTcwY2JmZDhmZTczNjkxMDEyM2U2YWRhMjAzZDRjN2JhOWE2MTI4YTZmIiwiY29udGV4dCI6e30sImlzcyI6ImppcmE6MTIzNC01Njc4LTkwMDAiLCJleHAiOjE0NjY3MzEyNTUsImlhdCI6MTQ2NjczMTA3NX0.AFKN_CHERMJa-VYAEVfRFw-Hi53VbJ_Y3clKB3RDAfE"
|
|
63
|
+
}, {
|
|
64
|
+
"name": "JSON Object (uri)",
|
|
65
|
+
"canonicalUrl": "GET\u0026/test\u0026json\u003d%7B%22key%22%3A%22value%22%7D",
|
|
66
|
+
"signedUrl": "https://example.com/test?json\u003d%7B%22key%22%3A%22value%22%7D\u0026jwt\u003deyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJxc2giOiIxZDc0YzVhMWYwYTZjNzJhM2NlMjg1NTcwY2JmZDhmZTczNjkxMDEyM2U2YWRhMjAzZDRjN2JhOWE2MTI4YTZmIiwiY29udGV4dCI6e30sImlzcyI6ImppcmE6MTIzNC01Njc4LTkwMDAiLCJleHAiOjE0NjY3MzEyNTUsImlhdCI6MTQ2NjczMTA3NX0.AFKN_CHERMJa-VYAEVfRFw-Hi53VbJ_Y3clKB3RDAfE"
|
|
67
|
+
}, {
|
|
68
|
+
"name": "JSON Array",
|
|
69
|
+
"canonicalUrl": "GET\u0026/test\u0026json\u003d%5B%22val1%22%2C%22val2%22%5D",
|
|
70
|
+
"signedUrl": "https://example.com/test?json\u003d%5B%22val1%22%2C%22val2%22%5D\u0026jwt\u003deyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJxc2giOiI1YTY5ZDM1ZjE2NTM0MjkwYTRlZDJmOWU1M2E0NWU2ODcyY2YwYzNhMTE2MzI5NWM0Mjk0N2Q0MjkzMWExZjczIiwiY29udGV4dCI6e30sImlzcyI6ImppcmE6MTIzNC01Njc4LTkwMDAiLCJleHAiOjE0NjY3MzEyNTUsImlhdCI6MTQ2NjczMTA3NX0.xO5VqtU8GL8CTr_wn0tHJAJ-r63PU-bJBTeuKF759dA"
|
|
71
|
+
}, {
|
|
72
|
+
"name": "JSON Array (uri)",
|
|
73
|
+
"canonicalUrl": "GET\u0026/test\u0026json\u003d%5B%22val1%22%2C%22val2%22%5D",
|
|
74
|
+
"signedUrl": "https://example.com/test?json\u003d%5B%22val1%22%2C%22val2%22%5D\u0026jwt\u003deyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJxc2giOiI1YTY5ZDM1ZjE2NTM0MjkwYTRlZDJmOWU1M2E0NWU2ODcyY2YwYzNhMTE2MzI5NWM0Mjk0N2Q0MjkzMWExZjczIiwiY29udGV4dCI6e30sImlzcyI6ImppcmE6MTIzNC01Njc4LTkwMDAiLCJleHAiOjE0NjY3MzEyNTUsImlhdCI6MTQ2NjczMTA3NX0.xO5VqtU8GL8CTr_wn0tHJAJ-r63PU-bJBTeuKF759dA"
|
|
75
|
+
}, {
|
|
76
|
+
"name": "Single Quotes",
|
|
77
|
+
"canonicalUrl": "GET\u0026/test\u0026quote\u003d%27quoted%27",
|
|
78
|
+
"signedUrl": "https://example.com/test?quote\u003d%27quoted%27\u0026jwt\u003deyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJxc2giOiIyMDdhMzAzNzZjNTk0ZDVjZGU3YjZlODczYjk0M2Y4NDc5ODM3MWQzMjkzYjdlYWMyN2UyYzJhMmE1ZDExMWQ1IiwiY29udGV4dCI6e30sImlzcyI6ImppcmE6MTIzNC01Njc4LTkwMDAiLCJleHAiOjE0NjY3MzEyNTUsImlhdCI6MTQ2NjczMTA3NX0.XsfJjmLIyIuX7_xfuj1JlNBiNQ_oSoh8KQVfEJHNJ0A"
|
|
79
|
+
}, {
|
|
80
|
+
"name": "Single Quotes (uri)",
|
|
81
|
+
"canonicalUrl": "GET\u0026/test\u0026quote\u003d%27quoted%27",
|
|
82
|
+
"signedUrl": "https://example.com/test?quote\u003d%27quoted%27\u0026jwt\u003deyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJxc2giOiIyMDdhMzAzNzZjNTk0ZDVjZGU3YjZlODczYjk0M2Y4NDc5ODM3MWQzMjkzYjdlYWMyN2UyYzJhMmE1ZDExMWQ1IiwiY29udGV4dCI6e30sImlzcyI6ImppcmE6MTIzNC01Njc4LTkwMDAiLCJleHAiOjE0NjY3MzEyNTUsImlhdCI6MTQ2NjczMTA3NX0.XsfJjmLIyIuX7_xfuj1JlNBiNQ_oSoh8KQVfEJHNJ0A"
|
|
83
|
+
}, {
|
|
84
|
+
"name": "Brackets",
|
|
85
|
+
"canonicalUrl": "GET\u0026/test\u0026param\u003d%28%29",
|
|
86
|
+
"signedUrl": "https://example.com/test?param\u003d%28%29\u0026jwt\u003deyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJxc2giOiI0NmI5Nzg3YTg5ODM1NjBmNDQ2ZjgyZDYxNDMxMjJkOTllMTUzYWZmZDU2ODhmYTQ1MzQzMDc0YTA5MTU3M2ViIiwiY29udGV4dCI6e30sImlzcyI6ImppcmE6MTIzNC01Njc4LTkwMDAiLCJleHAiOjE0NjY3MzEyNTUsImlhdCI6MTQ2NjczMTA3NX0.E7tLaNwK3c9HmDEoptDGWh2p6DZ2pd1R4sNBAPJ0L_A"
|
|
87
|
+
}, {
|
|
88
|
+
"name": "Brackets (uri)",
|
|
89
|
+
"canonicalUrl": "GET\u0026/test\u0026param\u003d%28%29",
|
|
90
|
+
"signedUrl": "https://example.com/test?param\u003d%28%29\u0026jwt\u003deyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJxc2giOiI0NmI5Nzg3YTg5ODM1NjBmNDQ2ZjgyZDYxNDMxMjJkOTllMTUzYWZmZDU2ODhmYTQ1MzQzMDc0YTA5MTU3M2ViIiwiY29udGV4dCI6e30sImlzcyI6ImppcmE6MTIzNC01Njc4LTkwMDAiLCJleHAiOjE0NjY3MzEyNTUsImlhdCI6MTQ2NjczMTA3NX0.E7tLaNwK3c9HmDEoptDGWh2p6DZ2pd1R4sNBAPJ0L_A"
|
|
91
|
+
}, {
|
|
92
|
+
"name": "Tilde",
|
|
93
|
+
"canonicalUrl": "GET\u0026/test\u0026eta\u003din%20~3%20days",
|
|
94
|
+
"signedUrl": "https://example.com/test?eta\u003din+%7E3+days\u0026jwt\u003deyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJxc2giOiI1YzVmOTdjZGZlM2FiZDhmZWI0OGY2ZjAyNDBhNzFlZjVjMTExMjg5YTViZjc3ZGRmNjQ1MjUwYjM5NTFlYzYzIiwiY29udGV4dCI6e30sImlzcyI6ImppcmE6MTIzNC01Njc4LTkwMDAiLCJleHAiOjE0NjY3MzEyNTUsImlhdCI6MTQ2NjczMTA3NX0.kc_ugGzgCHSyCk4DgUFNVb5dhC2TdTlFVKyQx1oBcDQ"
|
|
95
|
+
}, {
|
|
96
|
+
"name": "Tilde (uri)",
|
|
97
|
+
"canonicalUrl": "GET\u0026/test\u0026eta\u003din%20~3%20days",
|
|
98
|
+
"signedUrl": "https://example.com/test?eta\u003din+%7E3+days\u0026jwt\u003deyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJxc2giOiI1YzVmOTdjZGZlM2FiZDhmZWI0OGY2ZjAyNDBhNzFlZjVjMTExMjg5YTViZjc3ZGRmNjQ1MjUwYjM5NTFlYzYzIiwiY29udGV4dCI6e30sImlzcyI6ImppcmE6MTIzNC01Njc4LTkwMDAiLCJleHAiOjE0NjY3MzEyNTUsImlhdCI6MTQ2NjczMTA3NX0.kc_ugGzgCHSyCk4DgUFNVb5dhC2TdTlFVKyQx1oBcDQ"
|
|
99
|
+
}, {
|
|
100
|
+
"name": "RFC-1738 Unsafe",
|
|
101
|
+
"canonicalUrl": "GET\u0026/test\u0026rfc\u003d%20%3C%3E%22%23%25%7B%7D%7C%5C%5E~%5B%5D%60",
|
|
102
|
+
"signedUrl": "https://example.com/test?rfc\u003d+%3C%3E%22%23%25%7B%7D%7C%5C%5E%7E%5B%5D%60\u0026jwt\u003deyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJxc2giOiIzNmJhMzljNTM3OWQ3NTJiYmVmMTM0OWJhNThkZjk4ZWNhYTQ1NmI3OGM3YzJlMzI0NWUyZjMzZWFjNzEyYTQ5IiwiY29udGV4dCI6e30sImlzcyI6ImppcmE6MTIzNC01Njc4LTkwMDAiLCJleHAiOjE0NjY3MzEyNTUsImlhdCI6MTQ2NjczMTA3NX0.AHIN8GC3aWL6o8ZOxZZBW_fxTI-6CY78ucWh_kaXBAs"
|
|
103
|
+
}, {
|
|
104
|
+
"name": "RFC-1738 Unsafe (uri)",
|
|
105
|
+
"canonicalUrl": "GET\u0026/test\u0026rfc\u003d%20%3C%3E%22%23%25%7B%7D%7C%5C%5E~%5B%5D%60",
|
|
106
|
+
"signedUrl": "https://example.com/test?rfc\u003d+%3C%3E%22%23%25%7B%7D%7C%5C%5E%7E%5B%5D%60\u0026jwt\u003deyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJxc2giOiIzNmJhMzljNTM3OWQ3NTJiYmVmMTM0OWJhNThkZjk4ZWNhYTQ1NmI3OGM3YzJlMzI0NWUyZjMzZWFjNzEyYTQ5IiwiY29udGV4dCI6e30sImlzcyI6ImppcmE6MTIzNC01Njc4LTkwMDAiLCJleHAiOjE0NjY3MzEyNTUsImlhdCI6MTQ2NjczMTA3NX0.AHIN8GC3aWL6o8ZOxZZBW_fxTI-6CY78ucWh_kaXBAs"
|
|
107
|
+
}, {
|
|
108
|
+
"name": "RFC-1738 Reserved",
|
|
109
|
+
"canonicalUrl": "GET\u0026/test\u0026rfc\u003d%3B%2F%3F%3A%40%3D%26",
|
|
110
|
+
"signedUrl": "https://example.com/test?rfc\u003d%3B%2F%3F%3A%40%3D%26\u0026jwt\u003deyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJxc2giOiI2MzkzMzBiYzkyZDc5MzczYjE5OGRhNjk3ODczYjJmMDNmMWEzYTBjNWFmNzhjZjhlZWE1MTdmMTQ5NjBiMTUwIiwiY29udGV4dCI6e30sImlzcyI6ImppcmE6MTIzNC01Njc4LTkwMDAiLCJleHAiOjE0NjY3MzEyNTUsImlhdCI6MTQ2NjczMTA3NX0.a7vQvXIFT-sSJiHFcQKf3o8pTFA__O0X4EJOD_91iK0"
|
|
111
|
+
}, {
|
|
112
|
+
"name": "RFC-1738 Reserved (uri)",
|
|
113
|
+
"canonicalUrl": "GET\u0026/test\u0026rfc\u003d%3B%2F%3F%3A%40%3D%26",
|
|
114
|
+
"signedUrl": "https://example.com/test?rfc\u003d%3B%2F%3F%3A%40%3D%26\u0026jwt\u003deyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJxc2giOiI2MzkzMzBiYzkyZDc5MzczYjE5OGRhNjk3ODczYjJmMDNmMWEzYTBjNWFmNzhjZjhlZWE1MTdmMTQ5NjBiMTUwIiwiY29udGV4dCI6e30sImlzcyI6ImppcmE6MTIzNC01Njc4LTkwMDAiLCJleHAiOjE0NjY3MzEyNTUsImlhdCI6MTQ2NjczMTA3NX0.a7vQvXIFT-sSJiHFcQKf3o8pTFA__O0X4EJOD_91iK0"
|
|
115
|
+
}, {
|
|
116
|
+
"name": "RFC-1738 Special",
|
|
117
|
+
"canonicalUrl": "GET\u0026/test\u0026rfc\u003d%24-_.%2B%21%2A%27%28%29%2C",
|
|
118
|
+
"signedUrl": "https://example.com/test?rfc\u003d%24-_.%2B%21*%27%28%29%2C\u0026jwt\u003deyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJxc2giOiIwZTM2MjI5Y2M0NTlmZjhjY2I0ODQ1YzExNDMzY2ZiYmUyNWJmYTQ1ZThjMWVhMTRkMmExMjQyMzFjYjBhMmU5IiwiY29udGV4dCI6e30sImlzcyI6ImppcmE6MTIzNC01Njc4LTkwMDAiLCJleHAiOjE0NjY3MzEyNTUsImlhdCI6MTQ2NjczMTA3NX0.vUERQg8SGBRFZpB8d0DFOcaFdDfJjsHZBUDujLJ7LhQ"
|
|
119
|
+
}, {
|
|
120
|
+
"name": "RFC-1738 Special (uri)",
|
|
121
|
+
"canonicalUrl": "GET\u0026/test\u0026rfc\u003d%24-_.%2B%21%2A%27%28%29%2C",
|
|
122
|
+
"signedUrl": "https://example.com/test?rfc\u003d%24-_.%2B%21*%27%28%29%2C\u0026jwt\u003deyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJxc2giOiIwZTM2MjI5Y2M0NTlmZjhjY2I0ODQ1YzExNDMzY2ZiYmUyNWJmYTQ1ZThjMWVhMTRkMmExMjQyMzFjYjBhMmU5IiwiY29udGV4dCI6e30sImlzcyI6ImppcmE6MTIzNC01Njc4LTkwMDAiLCJleHAiOjE0NjY3MzEyNTUsImlhdCI6MTQ2NjczMTA3NX0.vUERQg8SGBRFZpB8d0DFOcaFdDfJjsHZBUDujLJ7LhQ"
|
|
123
|
+
}, {
|
|
124
|
+
"name": "RFC-3986 Unreserved",
|
|
125
|
+
"canonicalUrl": "GET\u0026/test\u0026rfc\u003d-._~",
|
|
126
|
+
"signedUrl": "https://example.com/test?rfc\u003d-._%7E\u0026jwt\u003deyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJxc2giOiIwZGRmN2U2MzFjM2IxMWU3OTc1ODE0ZWU4NGZlYzI2ODA0ZGM3MmIwYTBlOTk3ODcxZDg0MTVjZWU2Yjc4YjMxIiwiY29udGV4dCI6e30sImlzcyI6ImppcmE6MTIzNC01Njc4LTkwMDAiLCJleHAiOjE0NjY3MzEyNTUsImlhdCI6MTQ2NjczMTA3NX0.tqAbSA8_iIe-nfjtqBrHpxUe3HI7D9ILxpXIf0EqUfA"
|
|
127
|
+
}, {
|
|
128
|
+
"name": "RFC-3986 Unreserved (uri)",
|
|
129
|
+
"canonicalUrl": "GET\u0026/test\u0026rfc\u003d-._~",
|
|
130
|
+
"signedUrl": "https://example.com/test?rfc\u003d-._%7E\u0026jwt\u003deyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJxc2giOiIwZGRmN2U2MzFjM2IxMWU3OTc1ODE0ZWU4NGZlYzI2ODA0ZGM3MmIwYTBlOTk3ODcxZDg0MTVjZWU2Yjc4YjMxIiwiY29udGV4dCI6e30sImlzcyI6ImppcmE6MTIzNC01Njc4LTkwMDAiLCJleHAiOjE0NjY3MzEyNTUsImlhdCI6MTQ2NjczMTA3NX0.tqAbSA8_iIe-nfjtqBrHpxUe3HI7D9ILxpXIf0EqUfA"
|
|
131
|
+
}, {
|
|
132
|
+
"name": "RFC-3986 gen-delims",
|
|
133
|
+
"canonicalUrl": "GET\u0026/test\u0026rfc\u003d%3A%2F%3F%23%5B%5D%40",
|
|
134
|
+
"signedUrl": "https://example.com/test?rfc\u003d%3A%2F%3F%23%5B%5D%40\u0026jwt\u003deyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJxc2giOiI5NjA0MWVlNDVhZDRiOGVhMjliY2U0MmYzZTI4MzU0OTA1OTFmNTVlODRiZGRiYmFiODIxNTFkNGExYWMxYTExIiwiY29udGV4dCI6e30sImlzcyI6ImppcmE6MTIzNC01Njc4LTkwMDAiLCJleHAiOjE0NjY3MzEyNTUsImlhdCI6MTQ2NjczMTA3NX0.ChCEYkRpoqkZsyZ2ZtGAAntcb0KYHjmqI6to9p1KKJQ"
|
|
135
|
+
}, {
|
|
136
|
+
"name": "RFC-3986 gen-delims (uri)",
|
|
137
|
+
"canonicalUrl": "GET\u0026/test\u0026rfc\u003d%3A%2F%3F%23%5B%5D%40",
|
|
138
|
+
"signedUrl": "https://example.com/test?rfc\u003d%3A%2F%3F%23%5B%5D%40\u0026jwt\u003deyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJxc2giOiI5NjA0MWVlNDVhZDRiOGVhMjliY2U0MmYzZTI4MzU0OTA1OTFmNTVlODRiZGRiYmFiODIxNTFkNGExYWMxYTExIiwiY29udGV4dCI6e30sImlzcyI6ImppcmE6MTIzNC01Njc4LTkwMDAiLCJleHAiOjE0NjY3MzEyNTUsImlhdCI6MTQ2NjczMTA3NX0.ChCEYkRpoqkZsyZ2ZtGAAntcb0KYHjmqI6to9p1KKJQ"
|
|
139
|
+
}, {
|
|
140
|
+
"name": "RFC-3986 sub-delims",
|
|
141
|
+
"canonicalUrl": "GET\u0026/test\u0026rfc\u003d%21%24%26%27%28%29%2A%2B%2C%3B%3D",
|
|
142
|
+
"signedUrl": "https://example.com/test?rfc\u003d%21%24%26%27%28%29*%2B%2C%3B%3D\u0026jwt\u003deyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJxc2giOiJiOGQwNDk4NzRmMWZlNWFiZTI3NGQyMGJkZWNlYmVlOGRhYWRhNDUzMTkxYTgyNzczOGVlYmNkNzU5ZWZkNGUxIiwiY29udGV4dCI6e30sImlzcyI6ImppcmE6MTIzNC01Njc4LTkwMDAiLCJleHAiOjE0NjY3MzEyNTUsImlhdCI6MTQ2NjczMTA3NX0.rvu_onWEK0PWM-w6K7JEShKHVplx9oCTdeKyhpJmSx4"
|
|
143
|
+
}, {
|
|
144
|
+
"name": "RFC-3986 sub-delims (uri)",
|
|
145
|
+
"canonicalUrl": "GET\u0026/test\u0026rfc\u003d%21%24%26%27%28%29%2A%2B%2C%3B%3D",
|
|
146
|
+
"signedUrl": "https://example.com/test?rfc\u003d%21%24%26%27%28%29*%2B%2C%3B%3D\u0026jwt\u003deyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJxc2giOiJiOGQwNDk4NzRmMWZlNWFiZTI3NGQyMGJkZWNlYmVlOGRhYWRhNDUzMTkxYTgyNzczOGVlYmNkNzU5ZWZkNGUxIiwiY29udGV4dCI6e30sImlzcyI6ImppcmE6MTIzNC01Njc4LTkwMDAiLCJleHAiOjE0NjY3MzEyNTUsImlhdCI6MTQ2NjczMTA3NX0.rvu_onWEK0PWM-w6K7JEShKHVplx9oCTdeKyhpJmSx4"
|
|
147
|
+
}, {
|
|
148
|
+
"name": "Empty",
|
|
149
|
+
"canonicalUrl": "GET\u0026/test\u0026notmuch\u003d",
|
|
150
|
+
"signedUrl": "https://example.com/test?notmuch\u003d\u0026jwt\u003deyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJxc2giOiIyMGZlY2RlZDk5NTE1MTZhMzQ0N2IxYjU1NmQwZWIzNTBkZTI5NzcwNTA1MjUzYTMwZGM3Mzk1MDJlMDVkZGM3IiwiY29udGV4dCI6e30sImlzcyI6ImppcmE6MTIzNC01Njc4LTkwMDAiLCJleHAiOjE0NjY3MzEyNTUsImlhdCI6MTQ2NjczMTA3NX0.P8btoE2iwXDoTpWr9eL64OcumNeFtRVVuNAg_vb5EwE"
|
|
151
|
+
}, {
|
|
152
|
+
"name": "Empty (uri)",
|
|
153
|
+
"canonicalUrl": "GET\u0026/test\u0026notmuch\u003d",
|
|
154
|
+
"signedUrl": "https://example.com/test?notmuch\u003d\u0026jwt\u003deyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJxc2giOiIyMGZlY2RlZDk5NTE1MTZhMzQ0N2IxYjU1NmQwZWIzNTBkZTI5NzcwNTA1MjUzYTMwZGM3Mzk1MDJlMDVkZGM3IiwiY29udGV4dCI6e30sImlzcyI6ImppcmE6MTIzNC01Njc4LTkwMDAiLCJleHAiOjE0NjY3MzEyNTUsImlhdCI6MTQ2NjczMTA3NX0.P8btoE2iwXDoTpWr9eL64OcumNeFtRVVuNAg_vb5EwE"
|
|
155
|
+
}, {
|
|
156
|
+
"name": "Encoded",
|
|
157
|
+
"canonicalUrl": "GET\u0026/test\u0026referrer\u003dhttp%3A%2F%2Ffrom.net%2Fp%3Fx%3DA%2B%252B%2BB%26y%3D%2524-_.%252B%2521%2A%2527%2528%2529%252C",
|
|
158
|
+
"signedUrl": "https://example.com/test?referrer\u003dhttp%3A%2F%2Ffrom.net%2Fp%3Fx%3DA%2B%252B%2BB%26y%3D%2524-_.%252B%2521*%2527%2528%2529%252C\u0026jwt\u003deyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJxc2giOiI3Y2E4MWI4ZTRlODNjMjM3NWVlYTdiOGI1MGJkMzc4NmJhOGI0MzI2MTE5M2EzYmQzY2NkZmNhMDYxMjBlZTMzIiwiY29udGV4dCI6e30sImlzcyI6ImppcmE6MTIzNC01Njc4LTkwMDAiLCJleHAiOjE0NjY3MzEyNTUsImlhdCI6MTQ2NjczMTA3NX0.OTKND114j4id2cHr_AdHLAK9GqhbxFE7ad0eT0DmEV8"
|
|
159
|
+
}, {
|
|
160
|
+
"name": "Encoded (uri)",
|
|
161
|
+
"canonicalUrl": "GET\u0026/test\u0026referrer\u003dhttp%3A%2F%2Ffrom.net%2Fp%3Fx%3DA%2B%252B%2BB%26y%3D%2524-_.%252B%2521%2A%2527%2528%2529%252C",
|
|
162
|
+
"signedUrl": "https://example.com/test?referrer\u003dhttp%3A%2F%2Ffrom.net%2Fp%3Fx%3DA%2B%252B%2BB%26y%3D%2524-_.%252B%2521*%2527%2528%2529%252C\u0026jwt\u003deyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJxc2giOiI3Y2E4MWI4ZTRlODNjMjM3NWVlYTdiOGI1MGJkMzc4NmJhOGI0MzI2MTE5M2EzYmQzY2NkZmNhMDYxMjBlZTMzIiwiY29udGV4dCI6e30sImlzcyI6ImppcmE6MTIzNC01Njc4LTkwMDAiLCJleHAiOjE0NjY3MzEyNTUsImlhdCI6MTQ2NjczMTA3NX0.OTKND114j4id2cHr_AdHLAK9GqhbxFE7ad0eT0DmEV8"
|
|
163
|
+
}, {
|
|
164
|
+
"name": "Multi-value",
|
|
165
|
+
"canonicalUrl": "GET\u0026/test\u0026ids\u003d-1,1,10,2,20",
|
|
166
|
+
"signedUrl": "https://example.com/test?ids\u003d-1\u0026ids\u003d1\u0026ids\u003d10\u0026ids\u003d2\u0026ids\u003d20\u0026jwt\u003deyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJxc2giOiJhNjQ2YzQ4NzQxZmFhZWI2NDlmOWNhNzg4OGFlMDI5ZWFkNDMyZTM4MDZmNTZjNGE1N2I4MGIzZTJhYzYyOGE5IiwiY29udGV4dCI6e30sImlzcyI6ImppcmE6MTIzNC01Njc4LTkwMDAiLCJleHAiOjE0NjY3MzEyNTUsImlhdCI6MTQ2NjczMTA3NX0.gUepTNdB4HtYcabEZSiuXZrf2vU18ZGft5cvAT2W6FI"
|
|
167
|
+
}, {
|
|
168
|
+
"name": "Multi-value (uri)",
|
|
169
|
+
"canonicalUrl": "GET\u0026/test\u0026ids\u003d-1,1,10,2,20",
|
|
170
|
+
"signedUrl": "https://example.com/test?ids\u003d-1\u0026ids\u003d1\u0026ids\u003d10\u0026ids\u003d2\u0026ids\u003d20\u0026jwt\u003deyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJxc2giOiJhNjQ2YzQ4NzQxZmFhZWI2NDlmOWNhNzg4OGFlMDI5ZWFkNDMyZTM4MDZmNTZjNGE1N2I4MGIzZTJhYzYyOGE5IiwiY29udGV4dCI6e30sImlzcyI6ImppcmE6MTIzNC01Njc4LTkwMDAiLCJleHAiOjE0NjY3MzEyNTUsImlhdCI6MTQ2NjczMTA3NX0.gUepTNdB4HtYcabEZSiuXZrf2vU18ZGft5cvAT2W6FI"
|
|
171
|
+
}, {
|
|
172
|
+
"name": "Multi-value II",
|
|
173
|
+
"canonicalUrl": "GET\u0026/test\u0026ids\u003d.1,.2,%3A1,%3A2",
|
|
174
|
+
"signedUrl": "https://example.com/test?ids\u003d.1\u0026ids\u003d.2\u0026ids\u003d%3A1\u0026ids\u003d%3A2\u0026jwt\u003deyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJxc2giOiJmMDUyNGQ0MmUwZjg2NjE4NjJlMWYxZTlhZGQ4NzU3OTcyYTAwNDNiYjcxMzZkNjQxNzM1ZDIxODc0YzVhMDU2IiwiY29udGV4dCI6e30sImlzcyI6ImppcmE6MTIzNC01Njc4LTkwMDAiLCJleHAiOjE0NjY3MzEyNTUsImlhdCI6MTQ2NjczMTA3NX0.bbmy58zcb675U8eE1NaDvtd85EcVsGjZfIcSLbgOwas"
|
|
175
|
+
}, {
|
|
176
|
+
"name": "Multi-value II (uri)",
|
|
177
|
+
"canonicalUrl": "GET\u0026/test\u0026ids\u003d.1,.2,%3A1,%3A2",
|
|
178
|
+
"signedUrl": "https://example.com/test?ids\u003d.1\u0026ids\u003d.2\u0026ids\u003d%3A1\u0026ids\u003d%3A2\u0026jwt\u003deyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJxc2giOiJmMDUyNGQ0MmUwZjg2NjE4NjJlMWYxZTlhZGQ4NzU3OTcyYTAwNDNiYjcxMzZkNjQxNzM1ZDIxODc0YzVhMDU2IiwiY29udGV4dCI6e30sImlzcyI6ImppcmE6MTIzNC01Njc4LTkwMDAiLCJleHAiOjE0NjY3MzEyNTUsImlhdCI6MTQ2NjczMTA3NX0.bbmy58zcb675U8eE1NaDvtd85EcVsGjZfIcSLbgOwas"
|
|
179
|
+
}, {
|
|
180
|
+
"name": "Multi-value Unicode",
|
|
181
|
+
"canonicalUrl": "GET\u0026/test\u0026chars\u003d%E5%AE%AE,%E5%B4%8E,%E9%A7%BF",
|
|
182
|
+
"signedUrl": "https://example.com/test?chars\u003d%E5%AE%AE\u0026chars\u003d%E5%B4%8E\u0026chars\u003d%E9%A7%BF\u0026jwt\u003deyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJxc2giOiI3MmE3ZjdjZTlmOTMxNTdmMjk2Yjg2MzM4MzE1NDIzZDZmM2I2YWJhNTA4MWYwNGJiZGI2YmIxODIxOGI2NWVlIiwiY29udGV4dCI6e30sImlzcyI6ImppcmE6MTIzNC01Njc4LTkwMDAiLCJleHAiOjE0NjY3MzEyNTUsImlhdCI6MTQ2NjczMTA3NX0.K8dOEK17rBCjHS_sNj58CO4_rB4IM-JeRoUYVv2osbc"
|
|
183
|
+
}, {
|
|
184
|
+
"name": "Multi-value Unicode (uri)",
|
|
185
|
+
"canonicalUrl": "GET\u0026/test\u0026chars\u003d%E5%AE%AE,%E5%B4%8E,%E9%A7%BF",
|
|
186
|
+
"signedUrl": "https://example.com/test?chars\u003d%E5%AE%AE\u0026chars\u003d%E5%B4%8E\u0026chars\u003d%E9%A7%BF\u0026jwt\u003deyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJxc2giOiI3MmE3ZjdjZTlmOTMxNTdmMjk2Yjg2MzM4MzE1NDIzZDZmM2I2YWJhNTA4MWYwNGJiZGI2YmIxODIxOGI2NWVlIiwiY29udGV4dCI6e30sImlzcyI6ImppcmE6MTIzNC01Njc4LTkwMDAiLCJleHAiOjE0NjY3MzEyNTUsImlhdCI6MTQ2NjczMTA3NX0.K8dOEK17rBCjHS_sNj58CO4_rB4IM-JeRoUYVv2osbc"
|
|
187
|
+
}, {
|
|
188
|
+
"name": "Multi-value Empty",
|
|
189
|
+
"canonicalUrl": "GET\u0026/test\u0026c\u003d,%20,%2520,%2B",
|
|
190
|
+
"signedUrl": "https://example.com/test?c\u003d\u0026c\u003d+\u0026c\u003d%2520\u0026c\u003d%2B\u0026jwt\u003deyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJxc2giOiJjYmJjYWM5YTZhMDJmM2FkOTZjNWFiNWJmODc2ZGQ5Zjc5YjJjNjFjZWVjNTY2MGExYzlkNzNhM2IxMDJlYzJjIiwiY29udGV4dCI6e30sImlzcyI6ImppcmE6MTIzNC01Njc4LTkwMDAiLCJleHAiOjE0NjY3MzEyNTUsImlhdCI6MTQ2NjczMTA3NX0.R_DWbzp9IZbL9lutC4eRBf-NcN4sllakpx5H59F329A"
|
|
191
|
+
}, {
|
|
192
|
+
"name": "Multi-value Empty (uri)",
|
|
193
|
+
"canonicalUrl": "GET\u0026/test\u0026c\u003d,%20,%2520,%2B",
|
|
194
|
+
"signedUrl": "https://example.com/test?c\u003d\u0026c\u003d+\u0026c\u003d%2520\u0026c\u003d%2B\u0026jwt\u003deyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJxc2giOiJjYmJjYWM5YTZhMDJmM2FkOTZjNWFiNWJmODc2ZGQ5Zjc5YjJjNjFjZWVjNTY2MGExYzlkNzNhM2IxMDJlYzJjIiwiY29udGV4dCI6e30sImlzcyI6ImppcmE6MTIzNC01Njc4LTkwMDAiLCJleHAiOjE0NjY3MzEyNTUsImlhdCI6MTQ2NjczMTA3NX0.R_DWbzp9IZbL9lutC4eRBf-NcN4sllakpx5H59F329A"
|
|
195
|
+
}, {
|
|
196
|
+
"name": "Key RFC-1738 Unsafe",
|
|
197
|
+
"canonicalUrl": "GET\u0026/test\u0026%231\u003dvalue",
|
|
198
|
+
"signedUrl": "https://example.com/test?%231\u003dvalue\u0026jwt\u003deyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJxc2giOiJlY2NiNGEyMzJkNTBjYTQxYWM0MDM5ODY3NWI2NDg3YTcxMWQ5ZTk3MjkxN2Q4YTYxY2JjMTIwZjlmYmRhNTk3IiwiY29udGV4dCI6e30sImlzcyI6ImppcmE6MTIzNC01Njc4LTkwMDAiLCJleHAiOjE0NjY3MzEyNTUsImlhdCI6MTQ2NjczMTA3NX0.OLjm-tHtgDfOwTtBQ50-JGJM4zIP-yZcsDRAuJn0P7s"
|
|
199
|
+
}, {
|
|
200
|
+
"name": "Key RFC-1738 Unsafe (uri)",
|
|
201
|
+
"canonicalUrl": "GET\u0026/test\u0026%231\u003dvalue",
|
|
202
|
+
"signedUrl": "https://example.com/test?%231\u003dvalue\u0026jwt\u003deyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJxc2giOiJlY2NiNGEyMzJkNTBjYTQxYWM0MDM5ODY3NWI2NDg3YTcxMWQ5ZTk3MjkxN2Q4YTYxY2JjMTIwZjlmYmRhNTk3IiwiY29udGV4dCI6e30sImlzcyI6ImppcmE6MTIzNC01Njc4LTkwMDAiLCJleHAiOjE0NjY3MzEyNTUsImlhdCI6MTQ2NjczMTA3NX0.OLjm-tHtgDfOwTtBQ50-JGJM4zIP-yZcsDRAuJn0P7s"
|
|
203
|
+
}, {
|
|
204
|
+
"name": "Key RFC-1738 Reserved",
|
|
205
|
+
"canonicalUrl": "GET\u0026/test\u0026%3A1\u003dvalue",
|
|
206
|
+
"signedUrl": "https://example.com/test?%3A1\u003dvalue\u0026jwt\u003deyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJxc2giOiI2ZDgyMzE4MWE2OGE0OTUyYzc1ZTRiNTFhZDBiOGQ1OWU4Nzk4NTljZGY5NzdlNzI1NDU0NTIwMWJjYTg0NjVkIiwiY29udGV4dCI6e30sImlzcyI6ImppcmE6MTIzNC01Njc4LTkwMDAiLCJleHAiOjE0NjY3MzEyNTUsImlhdCI6MTQ2NjczMTA3NX0.lqRCsE131cmicAXf2BoCtLiV4g7D50piFnSzJoE0rCk"
|
|
207
|
+
}, {
|
|
208
|
+
"name": "Key RFC-1738 Reserved (uri)",
|
|
209
|
+
"canonicalUrl": "GET\u0026/test\u0026%3A1\u003dvalue",
|
|
210
|
+
"signedUrl": "https://example.com/test?%3A1\u003dvalue\u0026jwt\u003deyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJxc2giOiI2ZDgyMzE4MWE2OGE0OTUyYzc1ZTRiNTFhZDBiOGQ1OWU4Nzk4NTljZGY5NzdlNzI1NDU0NTIwMWJjYTg0NjVkIiwiY29udGV4dCI6e30sImlzcyI6ImppcmE6MTIzNC01Njc4LTkwMDAiLCJleHAiOjE0NjY3MzEyNTUsImlhdCI6MTQ2NjczMTA3NX0.lqRCsE131cmicAXf2BoCtLiV4g7D50piFnSzJoE0rCk"
|
|
211
|
+
}, {
|
|
212
|
+
"name": "Key RFC-1738 Special",
|
|
213
|
+
"canonicalUrl": "GET\u0026/test\u0026%241\u003dvalue",
|
|
214
|
+
"signedUrl": "https://example.com/test?%241\u003dvalue\u0026jwt\u003deyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJxc2giOiJhOWY2MWYxYzgyNTBlYmZiOTIzNDY1NGU3MWRlYzIzM2M5M2MxNmE1NGZlMzBhNjQ5ZGZkNjViYWRmM2MwMTcxIiwiY29udGV4dCI6e30sImlzcyI6ImppcmE6MTIzNC01Njc4LTkwMDAiLCJleHAiOjE0NjY3MzEyNTUsImlhdCI6MTQ2NjczMTA3NX0.xSvBJ10iVN7_Y97j1qApcYXUVq8JoXkCLnYf0Fwj0mY"
|
|
215
|
+
}, {
|
|
216
|
+
"name": "Key RFC-1738 Special (uri)",
|
|
217
|
+
"canonicalUrl": "GET\u0026/test\u0026%241\u003dvalue",
|
|
218
|
+
"signedUrl": "https://example.com/test?%241\u003dvalue\u0026jwt\u003deyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJxc2giOiJhOWY2MWYxYzgyNTBlYmZiOTIzNDY1NGU3MWRlYzIzM2M5M2MxNmE1NGZlMzBhNjQ5ZGZkNjViYWRmM2MwMTcxIiwiY29udGV4dCI6e30sImlzcyI6ImppcmE6MTIzNC01Njc4LTkwMDAiLCJleHAiOjE0NjY3MzEyNTUsImlhdCI6MTQ2NjczMTA3NX0.xSvBJ10iVN7_Y97j1qApcYXUVq8JoXkCLnYf0Fwj0mY"
|
|
219
|
+
}, {
|
|
220
|
+
"name": "Multiple Parameters Simple",
|
|
221
|
+
"canonicalUrl": "GET\u0026/test\u0026a\u003dx\u0026b\u003dy",
|
|
222
|
+
"signedUrl": "https://example.com/test?a\u003dx\u0026b\u003dy\u0026jwt\u003deyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJxc2giOiJhYmQ1ZGU2MDRiOWQzY2RhNDRkM2M3YTlkZDY5OGEyMTI1OTY1NTM5NDY1OGE2NjQyZjg3YjlkODI1ODY5NDYwIiwiY29udGV4dCI6e30sImlzcyI6ImppcmE6MTIzNC01Njc4LTkwMDAiLCJleHAiOjE0NjY3MzEyNTUsImlhdCI6MTQ2NjczMTA3NX0.1jFYZh4FjFNsGo62Qj9E7xzGCVVunqj5vtXoz7a8bCo"
|
|
223
|
+
}, {
|
|
224
|
+
"name": "Multiple Parameters Simple (uri)",
|
|
225
|
+
"canonicalUrl": "GET\u0026/test\u0026a\u003dx\u0026b\u003dy",
|
|
226
|
+
"signedUrl": "https://example.com/test?a\u003dx\u0026b\u003dy\u0026jwt\u003deyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJxc2giOiJhYmQ1ZGU2MDRiOWQzY2RhNDRkM2M3YTlkZDY5OGEyMTI1OTY1NTM5NDY1OGE2NjQyZjg3YjlkODI1ODY5NDYwIiwiY29udGV4dCI6e30sImlzcyI6ImppcmE6MTIzNC01Njc4LTkwMDAiLCJleHAiOjE0NjY3MzEyNTUsImlhdCI6MTQ2NjczMTA3NX0.1jFYZh4FjFNsGo62Qj9E7xzGCVVunqj5vtXoz7a8bCo"
|
|
227
|
+
}, {
|
|
228
|
+
"name": "Multiple Multi-value Parameters",
|
|
229
|
+
"canonicalUrl": "GET\u0026/test\u0026a\u003dx1,x10\u0026b\u003dy1,y10",
|
|
230
|
+
"signedUrl": "https://example.com/test?a\u003dx1\u0026a\u003dx10\u0026b\u003dy1\u0026b\u003dy10\u0026jwt\u003deyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJxc2giOiIzMTBiYTNmZjdlMWU5YThjYWNkMzNkZDYxNzI1MDEzMDRiZjMyNTA5NmQ4MWNjYWQ0NDk0NjU0MjdlNThhOWM0IiwiY29udGV4dCI6e30sImlzcyI6ImppcmE6MTIzNC01Njc4LTkwMDAiLCJleHAiOjE0NjY3MzEyNTUsImlhdCI6MTQ2NjczMTA3NX0.7OJXrJdQpPUni7Qm0IrFz9KHxTgCMeE1WbVC1unQJ3g"
|
|
231
|
+
}, {
|
|
232
|
+
"name": "Multiple Multi-value Parameters (uri)",
|
|
233
|
+
"canonicalUrl": "GET\u0026/test\u0026a\u003dx1,x10\u0026b\u003dy1,y10",
|
|
234
|
+
"signedUrl": "https://example.com/test?a\u003dx1\u0026a\u003dx10\u0026b\u003dy1\u0026b\u003dy10\u0026jwt\u003deyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJxc2giOiIzMTBiYTNmZjdlMWU5YThjYWNkMzNkZDYxNzI1MDEzMDRiZjMyNTA5NmQ4MWNjYWQ0NDk0NjU0MjdlNThhOWM0IiwiY29udGV4dCI6e30sImlzcyI6ImppcmE6MTIzNC01Njc4LTkwMDAiLCJleHAiOjE0NjY3MzEyNTUsImlhdCI6MTQ2NjczMTA3NX0.7OJXrJdQpPUni7Qm0IrFz9KHxTgCMeE1WbVC1unQJ3g"
|
|
235
|
+
}, {
|
|
236
|
+
"name": "Multiple Parameters Spaces",
|
|
237
|
+
"canonicalUrl": "GET\u0026/test\u0026a\u003danother%20one,one%20string\u0026b\u003dand%20yet%20more,more%20here",
|
|
238
|
+
"signedUrl": "https://example.com/test?a\u003danother+one\u0026a\u003done+string\u0026b\u003dand+yet+more\u0026b\u003dmore+here\u0026jwt\u003deyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJxc2giOiI3MDA3MjFlNjUzODU3ODFmYzFmYTI0ODIyMGM3NTQwMGYxZThhMTk3YzgzOGVmMTc3OWYwMGI2OWJmYTRhNmZmIiwiY29udGV4dCI6e30sImlzcyI6ImppcmE6MTIzNC01Njc4LTkwMDAiLCJleHAiOjE0NjY3MzEyNTUsImlhdCI6MTQ2NjczMTA3NX0.g5YMPR92qU3hw2uPmdWVztIIl25QKF5QlqsvCNZ7TDE"
|
|
239
|
+
}, {
|
|
240
|
+
"name": "Multiple Parameters Spaces (uri)",
|
|
241
|
+
"canonicalUrl": "GET\u0026/test\u0026a\u003danother%20one,one%20string\u0026b\u003dand%20yet%20more,more%20here",
|
|
242
|
+
"signedUrl": "https://example.com/test?a\u003danother+one\u0026a\u003done+string\u0026b\u003dand+yet+more\u0026b\u003dmore+here\u0026jwt\u003deyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJxc2giOiI3MDA3MjFlNjUzODU3ODFmYzFmYTI0ODIyMGM3NTQwMGYxZThhMTk3YzgzOGVmMTc3OWYwMGI2OWJmYTRhNmZmIiwiY29udGV4dCI6e30sImlzcyI6ImppcmE6MTIzNC01Njc4LTkwMDAiLCJleHAiOjE0NjY3MzEyNTUsImlhdCI6MTQ2NjczMTA3NX0.g5YMPR92qU3hw2uPmdWVztIIl25QKF5QlqsvCNZ7TDE"
|
|
243
|
+
}, {
|
|
244
|
+
"name": "Multiple Parameters Comma-delimited",
|
|
245
|
+
"canonicalUrl": "GET\u0026/test\u0026a\u003d1%2C2%2C3,4%2C5%2C6\u0026b\u003da%2Cb%2Cc,d%2Ce%2Cf",
|
|
246
|
+
"signedUrl": "https://example.com/test?a\u003d1%2C2%2C3\u0026a\u003d4%2C5%2C6\u0026b\u003da%2Cb%2Cc\u0026b\u003dd%2Ce%2Cf\u0026jwt\u003deyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJxc2giOiIwNmI3NmViNjNhY2NjY2UyMzU2Y2RmYzY2ZjRhYmQxZTNhMDYxYzAzMDVjOWZjNzZiNjE2YWU3MWZlM2I2YWI1IiwiY29udGV4dCI6e30sImlzcyI6ImppcmE6MTIzNC01Njc4LTkwMDAiLCJleHAiOjE0NjY3MzEyNTUsImlhdCI6MTQ2NjczMTA3NX0.6skGpsaWS3sR1ft8hdnJL5EvgFDlyUYmmjcziQrIK1s"
|
|
247
|
+
}, {
|
|
248
|
+
"name": "Multiple Parameters Comma-delimited (uri)",
|
|
249
|
+
"canonicalUrl": "GET\u0026/test\u0026a\u003d1%2C2%2C3,4%2C5%2C6\u0026b\u003da%2Cb%2Cc,d%2Ce%2Cf",
|
|
250
|
+
"signedUrl": "https://example.com/test?a\u003d1%2C2%2C3\u0026a\u003d4%2C5%2C6\u0026b\u003da%2Cb%2Cc\u0026b\u003dd%2Ce%2Cf\u0026jwt\u003deyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJxc2giOiIwNmI3NmViNjNhY2NjY2UyMzU2Y2RmYzY2ZjRhYmQxZTNhMDYxYzAzMDVjOWZjNzZiNjE2YWU3MWZlM2I2YWI1IiwiY29udGV4dCI6e30sImlzcyI6ImppcmE6MTIzNC01Njc4LTkwMDAiLCJleHAiOjE0NjY3MzEyNTUsImlhdCI6MTQ2NjczMTA3NX0.6skGpsaWS3sR1ft8hdnJL5EvgFDlyUYmmjcziQrIK1s"
|
|
251
|
+
}, {
|
|
252
|
+
"name": "Parameter Order",
|
|
253
|
+
"canonicalUrl": "GET\u0026/test\u0026a1\u003d2\u0026a10\u003d1\u0026b1\u003d3\u0026b10\u003d4",
|
|
254
|
+
"signedUrl": "https://example.com/test?a10\u003d1\u0026a1\u003d2\u0026b1\u003d3\u0026b10\u003d4\u0026jwt\u003deyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJxc2giOiIxNTljYzNkMzAwM2YwNjdjM2FlMjYzZDE5ZGVkNDJkZWRkMjgyMjFjY2U0ZDQ3NTdiMTNmYzc3MjJhMjQ0MDhmIiwiY29udGV4dCI6e30sImlzcyI6ImppcmE6MTIzNC01Njc4LTkwMDAiLCJleHAiOjE0NjY3MzEyNTUsImlhdCI6MTQ2NjczMTA3NX0.CEfY2ck1VpaOVlfNi9iXiF03lowoqm_WgHvtgf5Xfps"
|
|
255
|
+
}, {
|
|
256
|
+
"name": "Parameter Order (uri)",
|
|
257
|
+
"canonicalUrl": "GET\u0026/test\u0026a1\u003d2\u0026a10\u003d1\u0026b1\u003d3\u0026b10\u003d4",
|
|
258
|
+
"signedUrl": "https://example.com/test?a10\u003d1\u0026a1\u003d2\u0026b1\u003d3\u0026b10\u003d4\u0026jwt\u003deyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJxc2giOiIxNTljYzNkMzAwM2YwNjdjM2FlMjYzZDE5ZGVkNDJkZWRkMjgyMjFjY2U0ZDQ3NTdiMTNmYzc3MjJhMjQ0MDhmIiwiY29udGV4dCI6e30sImlzcyI6ImppcmE6MTIzNC01Njc4LTkwMDAiLCJleHAiOjE0NjY3MzEyNTUsImlhdCI6MTQ2NjczMTA3NX0.CEfY2ck1VpaOVlfNi9iXiF03lowoqm_WgHvtgf5Xfps"
|
|
259
|
+
}, {
|
|
260
|
+
"name": "Upper- and Lower-case Parameters",
|
|
261
|
+
"canonicalUrl": "GET\u0026/test\u0026A\u003dA\u0026B\u003dB\u0026a\u003da\u0026b\u003db",
|
|
262
|
+
"signedUrl": "https://example.com/test?A\u003dA\u0026a\u003da\u0026b\u003db\u0026B\u003dB\u0026jwt\u003deyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJxc2giOiI1MzlhZGMyYjBhZWYyZWM4NjU5ODI1ODkzYjhiOTJlNmE1M2M5NDgzZTIxNTBiODE4NWIwODQ5MGQ4YjZkZTYwIiwiY29udGV4dCI6e30sImlzcyI6ImppcmE6MTIzNC01Njc4LTkwMDAiLCJleHAiOjE0NjY3MzEyNTUsImlhdCI6MTQ2NjczMTA3NX0.wOC7mInLeAu_mQpoHlGW2DIlEeEfiqFvn32sea8vDvc"
|
|
263
|
+
}, {
|
|
264
|
+
"name": "Upper- and Lower-case Parameters (uri)",
|
|
265
|
+
"canonicalUrl": "GET\u0026/test\u0026A\u003dA\u0026B\u003dB\u0026a\u003da\u0026b\u003db",
|
|
266
|
+
"signedUrl": "https://example.com/test?A\u003dA\u0026a\u003da\u0026b\u003db\u0026B\u003dB\u0026jwt\u003deyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJxc2giOiI1MzlhZGMyYjBhZWYyZWM4NjU5ODI1ODkzYjhiOTJlNmE1M2M5NDgzZTIxNTBiODE4NWIwODQ5MGQ4YjZkZTYwIiwiY29udGV4dCI6e30sImlzcyI6ImppcmE6MTIzNC01Njc4LTkwMDAiLCJleHAiOjE0NjY3MzEyNTUsImlhdCI6MTQ2NjczMTA3NX0.wOC7mInLeAu_mQpoHlGW2DIlEeEfiqFvn32sea8vDvc"
|
|
267
|
+
}, {
|
|
268
|
+
"name": "Search Request View",
|
|
269
|
+
"canonicalUrl": "GET\u0026/search-view\u0026cp\u003djira\u0026endIssue\u003d2\u0026issues\u003dissues%3DTEST-2%2CTEST-1\u0026lic\u003dnone\u0026link\u003dhttp%3A%2F%2Fion%3A2990%2Fjira%2Fsecure%2FIssueNavigator.jspa%3Freset%3Dtrue%26jqlQuery%3Dissuetype%2B%253D%2BBug\u0026loc\u003den-US\u0026startIssue\u003d0\u0026totalIssues\u003d2\u0026tz\u003dAustralia%2FSydney\u0026user_id\u003dadmin\u0026user_key\u003dadmin\u0026xdm_c\u003dchannel-acmodule-1564427223927602208\u0026xdm_e\u003dhttp%3A%2F%2Fion.local%3A2990",
|
|
270
|
+
"signedUrl": "https://example.com/search-view?link\u003dhttp%3A%2F%2Fion%3A2990%2Fjira%2Fsecure%2FIssueNavigator.jspa%3Freset%3Dtrue%26jqlQuery%3Dissuetype%2B%253D%2BBug\u0026startIssue\u003d0\u0026totalIssues\u003d2\u0026endIssue\u003d2\u0026issues\u003dissues%3DTEST-2%2CTEST-1\u0026tz\u003dAustralia%2FSydney\u0026loc\u003den-US\u0026user_id\u003dadmin\u0026user_key\u003dadmin\u0026xdm_e\u003dhttp%3A%2F%2Fion.local%3A2990\u0026xdm_c\u003dchannel-acmodule-1564427223927602208\u0026cp\u003djira\u0026lic\u003dnone\u0026jwt\u003deyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJxc2giOiIwY2I3NGI4MGRkN2Y3NzkzODQ5ODY3Mjk4Y2EyZDg4OWU0ZDhiNjYxMTFiNjg5NjIyN2JkYmI0OTBkYzQ0YWUxIiwiY29udGV4dCI6e30sImlzcyI6ImppcmE6MTIzNC01Njc4LTkwMDAiLCJleHAiOjE0NjY3MzEyNTUsImlhdCI6MTQ2NjczMTA3NX0.UXWVrjqrCcjX6Mt6gIap4nK7o3aTLRz0ab1fMwwSJqo"
|
|
271
|
+
}, {
|
|
272
|
+
"name": "Search Request View (uri)",
|
|
273
|
+
"canonicalUrl": "GET\u0026/search-view\u0026cp\u003djira\u0026endIssue\u003d2\u0026issues\u003dissues%3DTEST-2%2CTEST-1\u0026lic\u003dnone\u0026link\u003dhttp%3A%2F%2Fion%3A2990%2Fjira%2Fsecure%2FIssueNavigator.jspa%3Freset%3Dtrue%26jqlQuery%3Dissuetype%2B%253D%2BBug\u0026loc\u003den-US\u0026startIssue\u003d0\u0026totalIssues\u003d2\u0026tz\u003dAustralia%2FSydney\u0026user_id\u003dadmin\u0026user_key\u003dadmin\u0026xdm_c\u003dchannel-acmodule-1564427223927602208\u0026xdm_e\u003dhttp%3A%2F%2Fion.local%3A2990",
|
|
274
|
+
"signedUrl": "https://example.com/search-view?link\u003dhttp%3A%2F%2Fion%3A2990%2Fjira%2Fsecure%2FIssueNavigator.jspa%3Freset%3Dtrue%26jqlQuery%3Dissuetype%2B%253D%2BBug\u0026startIssue\u003d0\u0026totalIssues\u003d2\u0026endIssue\u003d2\u0026issues\u003dissues%3DTEST-2%2CTEST-1\u0026tz\u003dAustralia%2FSydney\u0026loc\u003den-US\u0026user_id\u003dadmin\u0026user_key\u003dadmin\u0026xdm_e\u003dhttp%3A%2F%2Fion.local%3A2990\u0026xdm_c\u003dchannel-acmodule-1564427223927602208\u0026cp\u003djira\u0026lic\u003dnone\u0026jwt\u003deyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJxc2giOiIwY2I3NGI4MGRkN2Y3NzkzODQ5ODY3Mjk4Y2EyZDg4OWU0ZDhiNjYxMTFiNjg5NjIyN2JkYmI0OTBkYzQ0YWUxIiwiY29udGV4dCI6e30sImlzcyI6ImppcmE6MTIzNC01Njc4LTkwMDAiLCJleHAiOjE0NjY3MzEyNTUsImlhdCI6MTQ2NjczMTA3NX0.UXWVrjqrCcjX6Mt6gIap4nK7o3aTLRz0ab1fMwwSJqo"
|
|
275
|
+
}, {
|
|
276
|
+
"name": "BasePath only",
|
|
277
|
+
"canonicalUrl": "GET\u0026/test\u0026",
|
|
278
|
+
"signedUrl": "https://example.com/test?jwt\u003deyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJxc2giOiJiYWQzMjhmYWM5OTAzNDlhOGM4ODM5M2MxNzU1YmM0Zjk4NGE5YzM4NzIwMjIyOWI4ZWQ1MmUwNGZmN2U5ZmVjIiwiY29udGV4dCI6e30sImlzcyI6ImppcmE6MTIzNC01Njc4LTkwMDAiLCJleHAiOjE0NjY3MzEyNTUsImlhdCI6MTQ2NjczMTA3NX0.1LHKcYMbSI-xGystYrcpniFDmOkA45g-aJ7NhfyB-wY"
|
|
279
|
+
}, {
|
|
280
|
+
"name": "BasePath only (uri)",
|
|
281
|
+
"canonicalUrl": "GET\u0026/test\u0026",
|
|
282
|
+
"signedUrl": "https://example.com/test?jwt\u003deyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJxc2giOiJiYWQzMjhmYWM5OTAzNDlhOGM4ODM5M2MxNzU1YmM0Zjk4NGE5YzM4NzIwMjIyOWI4ZWQ1MmUwNGZmN2U5ZmVjIiwiY29udGV4dCI6e30sImlzcyI6ImppcmE6MTIzNC01Njc4LTkwMDAiLCJleHAiOjE0NjY3MzEyNTUsImlhdCI6MTQ2NjczMTA3NX0.1LHKcYMbSI-xGystYrcpniFDmOkA45g-aJ7NhfyB-wY"
|
|
283
|
+
}, {
|
|
284
|
+
"name": "BasePath with Delimiter",
|
|
285
|
+
"canonicalUrl": "GET\u0026/endsWithDelimiter\u0026a\u003db",
|
|
286
|
+
"signedUrl": "https://example.com/endsWithDelimiter/?a\u003db\u0026jwt\u003deyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJxc2giOiI4Zjc3YzZhMGU2YmYyNTA0MTEyMWVlNDQ0ODBkM2M5N2FlOWNjYTRiN2EwMDdlYTZlMWQ2NDhkOWEyNmU1ZDFkIiwiY29udGV4dCI6e30sImlzcyI6ImppcmE6MTIzNC01Njc4LTkwMDAiLCJleHAiOjE0NjY3MzEyNTUsImlhdCI6MTQ2NjczMTA3NX0.Lssm_JCVXZ7Qh-FEMJZx-eblxAa13MlzkReNLvARJI8"
|
|
287
|
+
}, {
|
|
288
|
+
"name": "BasePath with Delimiter (uri)",
|
|
289
|
+
"canonicalUrl": "GET\u0026/endsWithDelimiter\u0026a\u003db",
|
|
290
|
+
"signedUrl": "https://example.com/endsWithDelimiter/?a\u003db\u0026jwt\u003deyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJxc2giOiI4Zjc3YzZhMGU2YmYyNTA0MTEyMWVlNDQ0ODBkM2M5N2FlOWNjYTRiN2EwMDdlYTZlMWQ2NDhkOWEyNmU1ZDFkIiwiY29udGV4dCI6e30sImlzcyI6ImppcmE6MTIzNC01Njc4LTkwMDAiLCJleHAiOjE0NjY3MzEyNTUsImlhdCI6MTQ2NjczMTA3NX0.Lssm_JCVXZ7Qh-FEMJZx-eblxAa13MlzkReNLvARJI8"
|
|
291
|
+
}, {
|
|
292
|
+
"name": "BasePath with Delimiter Only",
|
|
293
|
+
"canonicalUrl": "GET\u0026/endsWithDelimiter\u0026",
|
|
294
|
+
"signedUrl": "https://example.com/endsWithDelimiter/?jwt\u003deyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJxc2giOiI0Yzc5OWU5MWZjOGUxYmU5YjFmMDM0ZjIxOTFhZTgwY2IyMDgwYjU0YTg1ZTlhMjQ2NGFkMmYyMTE1ZjhkOTg3IiwiY29udGV4dCI6e30sImlzcyI6ImppcmE6MTIzNC01Njc4LTkwMDAiLCJleHAiOjE0NjY3MzEyNTUsImlhdCI6MTQ2NjczMTA3NX0.wqBRfpzUg79FTLQZiUqNIk9qGEBFXhrZmQ5GvicOFY8"
|
|
295
|
+
}, {
|
|
296
|
+
"name": "BasePath with Delimiter Only (uri)",
|
|
297
|
+
"canonicalUrl": "GET\u0026/endsWithDelimiter\u0026",
|
|
298
|
+
"signedUrl": "https://example.com/endsWithDelimiter/?jwt\u003deyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJxc2giOiI0Yzc5OWU5MWZjOGUxYmU5YjFmMDM0ZjIxOTFhZTgwY2IyMDgwYjU0YTg1ZTlhMjQ2NGFkMmYyMTE1ZjhkOTg3IiwiY29udGV4dCI6e30sImlzcyI6ImppcmE6MTIzNC01Njc4LTkwMDAiLCJleHAiOjE0NjY3MzEyNTUsImlhdCI6MTQ2NjczMTA3NX0.wqBRfpzUg79FTLQZiUqNIk9qGEBFXhrZmQ5GvicOFY8"
|
|
299
|
+
}, {
|
|
300
|
+
"name": "BasePath RFC3986 Unreserved",
|
|
301
|
+
"canonicalUrl": "GET\u0026/path-._~\u0026a\u003db",
|
|
302
|
+
"signedUrl": "https://example.com/path-._~?a\u003db\u0026jwt\u003deyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJxc2giOiI1ZDE1NzRlYTBmZDg5NzRmYTQzMjZkODdiM2VmZWM3NDAwNGJmMTNkMzUzOTU1OTlkZTQyNTMyNzE3OGMxNzNiIiwiY29udGV4dCI6e30sImlzcyI6ImppcmE6MTIzNC01Njc4LTkwMDAiLCJleHAiOjE0NjY3MzEyNTUsImlhdCI6MTQ2NjczMTA3NX0.oWGLh5OdI0tw1i6FL6CDOm-qGpGJQnru9rk5B37O2T8"
|
|
303
|
+
}, {
|
|
304
|
+
"name": "BasePath RFC3986 Unreserved (uri)",
|
|
305
|
+
"canonicalUrl": "GET\u0026/path-._~\u0026a\u003db",
|
|
306
|
+
"signedUrl": "https://example.com/path-._~?a\u003db\u0026jwt\u003deyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJxc2giOiI1ZDE1NzRlYTBmZDg5NzRmYTQzMjZkODdiM2VmZWM3NDAwNGJmMTNkMzUzOTU1OTlkZTQyNTMyNzE3OGMxNzNiIiwiY29udGV4dCI6e30sImlzcyI6ImppcmE6MTIzNC01Njc4LTkwMDAiLCJleHAiOjE0NjY3MzEyNTUsImlhdCI6MTQ2NjczMTA3NX0.oWGLh5OdI0tw1i6FL6CDOm-qGpGJQnru9rk5B37O2T8"
|
|
307
|
+
}, {
|
|
308
|
+
"name": "BasePath RFC3986 Subdelimiters",
|
|
309
|
+
"canonicalUrl": "GET\u0026/path!$%26\u0027()*+,;\u003d\u0026a\u003db",
|
|
310
|
+
"signedUrl": "https://example.com/path!$\u0026\u0027()*+,;\u003d?a\u003db\u0026jwt\u003deyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJxc2giOiI5ZWY4MDNmOWNiOGRlYTRmN2Y4NzVjYWZmOGQzMWU5NTk2MmM2ZThiZDQ0ZDY0YTg0OGQ2ZWJiMDU1YjIxNDRiIiwiY29udGV4dCI6e30sImlzcyI6ImppcmE6MTIzNC01Njc4LTkwMDAiLCJleHAiOjE0NjY3MzEyNTUsImlhdCI6MTQ2NjczMTA3NX0.xT24PP9ialy7yso14IaFYO9c5dV2oJ1OMTrPon7yRF4"
|
|
311
|
+
}, {
|
|
312
|
+
"name": "BasePath RFC3986 Subdelimiters (uri)",
|
|
313
|
+
"canonicalUrl": "GET\u0026/path!$%26\u0027()*+,;\u003d\u0026a\u003db",
|
|
314
|
+
"signedUrl": "https://example.com/path!$\u0026\u0027()*+,;\u003d?a\u003db\u0026jwt\u003deyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJxc2giOiI5ZWY4MDNmOWNiOGRlYTRmN2Y4NzVjYWZmOGQzMWU5NTk2MmM2ZThiZDQ0ZDY0YTg0OGQ2ZWJiMDU1YjIxNDRiIiwiY29udGV4dCI6e30sImlzcyI6ImppcmE6MTIzNC01Njc4LTkwMDAiLCJleHAiOjE0NjY3MzEyNTUsImlhdCI6MTQ2NjczMTA3NX0.xT24PP9ialy7yso14IaFYO9c5dV2oJ1OMTrPon7yRF4"
|
|
315
|
+
}],
|
|
316
|
+
"comment": "Generated by com.atlassian.plugin.connect.plugin.auth.jwt.JwtSigningInteroperabilityTest.SigningTests on Fri Jun 24 11:17:55 AEST 2016"
|
|
317
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
describe JIRA::Resource::Properties do
|
|
4
|
+
with_each_client do |site_url, client|
|
|
5
|
+
context 'when accessing singular resource' do
|
|
6
|
+
let(:client) { client }
|
|
7
|
+
let(:site_url) { site_url }
|
|
8
|
+
let(:key) { 'xyz' }
|
|
9
|
+
let(:target) { described_class.new(client, attrs: { 'key' => 'xyz' }, issue_id: '10002') }
|
|
10
|
+
let(:belongs_to) { JIRA::Resource::Issue.new(client, attrs: { 'id' => '10002' }) }
|
|
11
|
+
let(:expected_attributes) { { 'key' => key, 'value' => 'supercalifragilistic' } }
|
|
12
|
+
let(:attributes_for_put) { { 'value' => 'expialidocious' } }
|
|
13
|
+
let(:expected_attributes_from_put) { { 'key' => key, 'value' => 'expialidocious' } }
|
|
14
|
+
|
|
15
|
+
it_behaves_like 'a resource'
|
|
16
|
+
it_behaves_like 'a resource with a singular GET endpoint'
|
|
17
|
+
it_behaves_like 'a resource with a DELETE endpoint'
|
|
18
|
+
it_behaves_like 'a resource with a PUT endpoint'
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
context 'when accessing collection' do
|
|
22
|
+
let(:client) { client }
|
|
23
|
+
let(:site_url) { site_url }
|
|
24
|
+
let(:key) { 'xyz' }
|
|
25
|
+
let(:belongs_to) { JIRA::Resource::Issue.new(client, attrs: { 'id' => '10002' }) }
|
|
26
|
+
let(:expected_collection_length) { 2 }
|
|
27
|
+
let(:expected_attributes) { { 'key' => key, 'value' => 'supercalifragilistic' } }
|
|
28
|
+
|
|
29
|
+
before do
|
|
30
|
+
## Since properties collections do subsequent queries on each individual properties records,
|
|
31
|
+
## we need to additionally define stub requests for each of the individual records
|
|
32
|
+
additional_targets = [
|
|
33
|
+
described_class.new(client, attrs: { 'key' => 'foo' }, issue_id: '10002'),
|
|
34
|
+
described_class.new(client, attrs: { 'key' => 'xyz' }, issue_id: '10002')
|
|
35
|
+
]
|
|
36
|
+
additional_targets.each do |target|
|
|
37
|
+
req_url = site_url + target.url
|
|
38
|
+
stub_request(:get, req_url).to_return(status: 200, body: get_mock_from_url(:get, req_url))
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
it_behaves_like 'a resource with a collection GET endpoint'
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|
|
@@ -38,9 +38,10 @@ describe JIRA::Resource::Transition do
|
|
|
38
38
|
|
|
39
39
|
describe 'POST endpoint' do
|
|
40
40
|
it 'saves a new resource' do
|
|
41
|
-
|
|
41
|
+
req_url = build_url
|
|
42
|
+
stub_request(:post, req_url)
|
|
42
43
|
.with(body: attributes_for_post.to_json)
|
|
43
|
-
.to_return(status: 200, body:
|
|
44
|
+
.to_return(status: 200, body: get_mock_from_url(:post, req_url))
|
|
44
45
|
subject = build_receiver.build
|
|
45
46
|
expect(subject.save(attributes_for_post)).to be_truthy
|
|
46
47
|
end
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
require 'spec_helper'
|
|
2
2
|
|
|
3
3
|
describe JIRA::Resource::Webhook do
|
|
4
|
-
|
|
4
|
+
## This endpoint uses a different base path, so override this client's rest_base_path option
|
|
5
|
+
## so this test can still use the SharedExampleGroups
|
|
6
|
+
with_each_client(rest_base_path: described_class.const_get(:REST_BASE_PATH)) do |site_url, client|
|
|
5
7
|
let(:client) { client }
|
|
6
8
|
let(:site_url) { site_url }
|
|
7
9
|
|
|
@@ -20,7 +22,7 @@ describe JIRA::Resource::Webhook do
|
|
|
20
22
|
|
|
21
23
|
it 'returns a collection of components' do
|
|
22
24
|
stub_request(:get, site_url + described_class.singular_path(client, key))
|
|
23
|
-
.to_return(status: 200, body: get_mock_response('webhook/
|
|
25
|
+
.to_return(status: 200, body: get_mock_response('webhook/2.json'))
|
|
24
26
|
|
|
25
27
|
webhook = client.Webhook.find(key)
|
|
26
28
|
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
# rubocop:disable RSpec/LeakyLocalVariable
|
|
4
|
+
describe JIRA::Atlassian::Jwt do
|
|
5
|
+
let(:jwt_opts) do
|
|
6
|
+
{
|
|
7
|
+
algorithm: 'HS256',
|
|
8
|
+
leeway: (3600 * 24 * 365 * 10) # 10 years of leeway -- the JWT gem verifies the token expiry time
|
|
9
|
+
}
|
|
10
|
+
end
|
|
11
|
+
let(:base_url) { '' }
|
|
12
|
+
|
|
13
|
+
it 'generates claims' do
|
|
14
|
+
url = 'https://example.atlassian.com/jira/projects'
|
|
15
|
+
issuer = 'com.atlassian.test'
|
|
16
|
+
|
|
17
|
+
now = Time.now.to_i
|
|
18
|
+
qsh = Digest::SHA256.hexdigest(
|
|
19
|
+
described_class.create_canonical_request(url, 'get', base_url)
|
|
20
|
+
)
|
|
21
|
+
|
|
22
|
+
expected_claim = {
|
|
23
|
+
iss: 'com.atlassian.test',
|
|
24
|
+
iat: now,
|
|
25
|
+
exp: now + 60,
|
|
26
|
+
qsh: qsh
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
claim = described_class.build_claims(issuer, url, 'get', base_url, now, now + 60)
|
|
30
|
+
expect(claim).to eq expected_claim
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
# Offical Atlassian signed URL test data
|
|
34
|
+
json_tests = File.read(File.expand_path('../../data/files/jwt-signed-urls.json', File.dirname(__FILE__)))
|
|
35
|
+
|
|
36
|
+
test_data = JSON.parse(json_tests)
|
|
37
|
+
shared_secret = test_data['secret']
|
|
38
|
+
|
|
39
|
+
test_data['tests'].each do |test|
|
|
40
|
+
signed_url = test['signedUrl']
|
|
41
|
+
signed_uri = URI.parse(signed_url)
|
|
42
|
+
token = CGI.parse(signed_uri.query)['jwt'].first
|
|
43
|
+
|
|
44
|
+
it "#{test['name']} - Canonical URL" do
|
|
45
|
+
canonical_uri = described_class.create_canonical_request(signed_url, 'GET', base_url)
|
|
46
|
+
|
|
47
|
+
# Remote the jwt query param from the signed URL to get the original
|
|
48
|
+
expect(canonical_uri).to eq test['canonicalUrl']
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
it "#{test['name']} - QSH match" do
|
|
52
|
+
expected_qsh = Digest::SHA256.hexdigest(described_class.create_canonical_request(signed_url, 'GET', base_url))
|
|
53
|
+
|
|
54
|
+
decoded_token = JWT.decode(token, shared_secret, true, jwt_opts).first
|
|
55
|
+
|
|
56
|
+
expect(expected_qsh).to eq decoded_token['qsh']
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
# rubocop:enable RSpec/LeakyLocalVariable
|
|
@@ -244,7 +244,8 @@ describe JIRA::Resource::Issue do
|
|
|
244
244
|
'comment' => { 'comments' => [{ 'foo' => 'bar' }, { 'baz' => 'flum' }] },
|
|
245
245
|
'attachment' => [{ 'foo' => 'bar' }, { 'baz' => 'flum' }],
|
|
246
246
|
'worklog' => { 'worklogs' => [{ 'foo' => 'bar' }, { 'baz' => 'flum' }] }
|
|
247
|
-
}
|
|
247
|
+
},
|
|
248
|
+
'properties' => [{ 'foo' => 'bar' }, { 'baz' => 'flum' }]
|
|
248
249
|
})
|
|
249
250
|
end
|
|
250
251
|
|
|
@@ -284,6 +285,9 @@ describe JIRA::Resource::Issue do
|
|
|
284
285
|
|
|
285
286
|
expect(subject).to have_many(:worklogs, JIRA::Resource::Worklog)
|
|
286
287
|
expect(subject.worklogs.length).to eq(2)
|
|
288
|
+
|
|
289
|
+
expect(subject).to have_many(:properties, JIRA::Resource::Properties)
|
|
290
|
+
expect(subject.properties.length).to eq(2)
|
|
287
291
|
end
|
|
288
292
|
end
|
|
289
293
|
end
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
module ClientsHelper
|
|
2
|
-
def with_each_client(&)
|
|
2
|
+
def with_each_client(opts = {}, &)
|
|
3
3
|
clients = {}
|
|
4
4
|
|
|
5
|
-
oauth_client = JIRA::Client.new(consumer_key: 'foo', consumer_secret: 'bar')
|
|
5
|
+
oauth_client = JIRA::Client.new({ consumer_key: 'foo', consumer_secret: 'bar' }.merge(opts))
|
|
6
6
|
oauth_client.set_access_token('abc', '123')
|
|
7
7
|
clients['http://localhost:2990'] = oauth_client
|
|
8
8
|
|
|
9
|
-
basic_client = JIRA::Client.new(username: 'foo', password: 'bar', auth_type: :basic, use_ssl: false)
|
|
9
|
+
basic_client = JIRA::Client.new({ username: 'foo', password: 'bar', auth_type: :basic, use_ssl: false }.merge(opts))
|
|
10
10
|
clients['http://localhost:2990'] = basic_client
|
|
11
11
|
|
|
12
12
|
clients.each(&)
|
|
@@ -1,20 +1,18 @@
|
|
|
1
1
|
require 'cgi'
|
|
2
2
|
|
|
3
|
-
def
|
|
4
|
-
prefix =
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
end
|
|
17
|
-
file_path = url.sub(client.options[:rest_base_path], '')
|
|
3
|
+
def build_url(options = {})
|
|
4
|
+
prefix = defined?(belongs_to) ? "#{belongs_to.path_component}/" : '/'
|
|
5
|
+
path = if options.key?(:key)
|
|
6
|
+
described_class.singular_path(client, options[:key], prefix)
|
|
7
|
+
else
|
|
8
|
+
described_class.collection_path(client, prefix)
|
|
9
|
+
end
|
|
10
|
+
site_url + path
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def get_mock_from_url(method, url, options = {})
|
|
14
|
+
# Remove site_url and rest api portion of the url
|
|
15
|
+
file_path = url.sub(site_url + client.options[:rest_base_path], '')
|
|
18
16
|
file_path = "#{file_path}.#{options[:suffix]}" if options[:suffix]
|
|
19
17
|
file_path = "#{file_path}.#{method}" unless method == :get
|
|
20
18
|
value_if_not_found = options.key?(:value_if_not_found) ? options[:value_if_not_found] : false
|
|
@@ -63,8 +61,8 @@ end
|
|
|
63
61
|
|
|
64
62
|
shared_examples 'a resource with a collection GET endpoint' do
|
|
65
63
|
it 'gets the collection' do
|
|
66
|
-
|
|
67
|
-
|
|
64
|
+
req_url = build_url
|
|
65
|
+
stub_request(:get, req_url).to_return(status: 200, body: get_mock_from_url(:get, req_url))
|
|
68
66
|
collection = build_receiver.all
|
|
69
67
|
|
|
70
68
|
expect(collection.length).to eq(expected_collection_length)
|
|
@@ -74,10 +72,8 @@ end
|
|
|
74
72
|
|
|
75
73
|
shared_examples 'a resource with JQL inputs and a collection GET endpoint' do
|
|
76
74
|
it 'gets the collection' do
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
"#{site_url}#{client.options[:rest_base_path]}/search/jql?jql=#{CGI.escape(jql_query_string)}"
|
|
80
|
-
).to_return(status: 200, body: get_mock_response('issue.json'))
|
|
75
|
+
req_url = "#{site_url}#{client.options[:rest_base_path]}/search/jql?jql=#{CGI.escape(jql_query_string)}"
|
|
76
|
+
stub_request(:get, req_url).to_return(status: 200, body: get_mock_response('issue.json'))
|
|
81
77
|
|
|
82
78
|
collection = build_receiver.jql(jql_query_string)
|
|
83
79
|
|
|
@@ -90,8 +86,8 @@ shared_examples 'a resource with a singular GET endpoint' do
|
|
|
90
86
|
it 'GETs a single resource' do
|
|
91
87
|
# E.g., for JIRA::Resource::Project, we need to call
|
|
92
88
|
# client.Project.find()
|
|
93
|
-
|
|
94
|
-
|
|
89
|
+
req_url = build_url(key:)
|
|
90
|
+
stub_request(:get, req_url).to_return(status: 200, body: get_mock_from_url(:get, req_url))
|
|
95
91
|
subject = client.send(class_basename).find(key, options)
|
|
96
92
|
|
|
97
93
|
expect(subject).to have_attributes(expected_attributes)
|
|
@@ -100,8 +96,8 @@ shared_examples 'a resource with a singular GET endpoint' do
|
|
|
100
96
|
it 'builds and fetches a single resource' do
|
|
101
97
|
# E.g., for JIRA::Resource::Project, we need to call
|
|
102
98
|
# client.Project.build('key' => 'ABC123')
|
|
103
|
-
|
|
104
|
-
|
|
99
|
+
req_url = build_url(key:)
|
|
100
|
+
stub_request(:get, req_url).to_return(status: 200, body: get_mock_from_url(:get, req_url))
|
|
105
101
|
|
|
106
102
|
subject = build_receiver.build(described_class.key_attribute.to_s => key)
|
|
107
103
|
subject.fetch
|
|
@@ -110,7 +106,7 @@ shared_examples 'a resource with a singular GET endpoint' do
|
|
|
110
106
|
end
|
|
111
107
|
|
|
112
108
|
it 'handles a 404' do
|
|
113
|
-
stub_request(:get,
|
|
109
|
+
stub_request(:get, build_url(key: '99999'))
|
|
114
110
|
.to_return(status: 404, body: "{\"errorMessages\":[\"#{class_basename} Does Not Exist\"],\"errors\": {}}")
|
|
115
111
|
expect do
|
|
116
112
|
client.send(class_basename).find('99999', options)
|
|
@@ -122,8 +118,8 @@ shared_examples 'a resource with a DELETE endpoint' do
|
|
|
122
118
|
it 'deletes a resource' do
|
|
123
119
|
# E.g., for JIRA::Resource::Project, we need to call
|
|
124
120
|
# client.Project.delete()
|
|
125
|
-
|
|
126
|
-
|
|
121
|
+
req_url = build_url(key:)
|
|
122
|
+
stub_request(:delete, req_url).to_return(status: 204, body: nil)
|
|
127
123
|
|
|
128
124
|
subject = build_receiver.build(described_class.key_attribute.to_s => key)
|
|
129
125
|
expect(subject.delete).to be_truthy
|
|
@@ -132,8 +128,8 @@ end
|
|
|
132
128
|
|
|
133
129
|
shared_examples 'a resource with a POST endpoint' do
|
|
134
130
|
it 'saves a new resource' do
|
|
135
|
-
|
|
136
|
-
|
|
131
|
+
req_url = build_url
|
|
132
|
+
stub_request(:post, req_url).to_return(status: 201, body: get_mock_from_url(:post, req_url))
|
|
137
133
|
subject = build_receiver.build
|
|
138
134
|
expect(subject.save(attributes_for_post)).to be_truthy
|
|
139
135
|
expected_attributes_from_post.each do |method_name, value|
|
|
@@ -144,10 +140,10 @@ end
|
|
|
144
140
|
|
|
145
141
|
shared_examples 'a resource with a PUT endpoint' do
|
|
146
142
|
it 'saves an existing component' do
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
stub_request(:put,
|
|
150
|
-
.to_return(status: 200, body:
|
|
143
|
+
req_url = build_url(key:)
|
|
144
|
+
stub_request(:get, req_url).to_return(status: 200, body: get_mock_from_url(:get, req_url))
|
|
145
|
+
stub_request(:put, req_url)
|
|
146
|
+
.to_return(status: 200, body: get_mock_from_url(:put, req_url, value_if_not_found: nil))
|
|
151
147
|
subject = build_receiver.build(described_class.key_attribute.to_s => key)
|
|
152
148
|
subject.fetch
|
|
153
149
|
expect(subject.save(attributes_for_put)).to be_truthy
|
|
@@ -159,10 +155,10 @@ end
|
|
|
159
155
|
|
|
160
156
|
shared_examples 'a resource with a PUT endpoint that rejects invalid fields' do
|
|
161
157
|
it 'fails to save with an invalid field' do
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
stub_request(:put,
|
|
165
|
-
.to_return(status: 400, body:
|
|
158
|
+
req_url = build_url(key:)
|
|
159
|
+
stub_request(:get, req_url).to_return(status: 200, body: get_mock_from_url(:get, req_url))
|
|
160
|
+
stub_request(:put, req_url)
|
|
161
|
+
.to_return(status: 400, body: get_mock_from_url(:put, req_url, suffix: 'invalid'))
|
|
166
162
|
subject = client.send(class_basename).build(described_class.key_attribute.to_s => key)
|
|
167
163
|
subject.fetch
|
|
168
164
|
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: jira-ruby
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 3.
|
|
4
|
+
version: 3.2.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- SUMO Heavy Industries
|
|
8
8
|
- test IO
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2026-
|
|
11
|
+
date: 2026-05-20 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: activesupport
|
|
@@ -25,7 +25,7 @@ dependencies:
|
|
|
25
25
|
- !ruby/object:Gem::Version
|
|
26
26
|
version: '0'
|
|
27
27
|
- !ruby/object:Gem::Dependency
|
|
28
|
-
name:
|
|
28
|
+
name: cgi
|
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
|
30
30
|
requirements:
|
|
31
31
|
- - ">="
|
|
@@ -39,19 +39,19 @@ dependencies:
|
|
|
39
39
|
- !ruby/object:Gem::Version
|
|
40
40
|
version: '0'
|
|
41
41
|
- !ruby/object:Gem::Dependency
|
|
42
|
-
name:
|
|
42
|
+
name: jwt
|
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
|
44
44
|
requirements:
|
|
45
45
|
- - ">="
|
|
46
46
|
- !ruby/object:Gem::Version
|
|
47
|
-
version: '
|
|
47
|
+
version: '2.1'
|
|
48
48
|
type: :runtime
|
|
49
49
|
prerelease: false
|
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
|
51
51
|
requirements:
|
|
52
52
|
- - ">="
|
|
53
53
|
- !ruby/object:Gem::Version
|
|
54
|
-
version: '
|
|
54
|
+
version: '2.1'
|
|
55
55
|
- !ruby/object:Gem::Dependency
|
|
56
56
|
name: multipart-post
|
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -101,6 +101,7 @@ files:
|
|
|
101
101
|
- Rakefile
|
|
102
102
|
- jira-ruby.gemspec
|
|
103
103
|
- lib/jira-ruby.rb
|
|
104
|
+
- lib/jira/atlassian/jwt.rb
|
|
104
105
|
- lib/jira/base.rb
|
|
105
106
|
- lib/jira/base_factory.rb
|
|
106
107
|
- lib/jira/client.rb
|
|
@@ -129,6 +130,7 @@ files:
|
|
|
129
130
|
- lib/jira/resource/issuetype.rb
|
|
130
131
|
- lib/jira/resource/priority.rb
|
|
131
132
|
- lib/jira/resource/project.rb
|
|
133
|
+
- lib/jira/resource/properties.rb
|
|
132
134
|
- lib/jira/resource/rapidview.rb
|
|
133
135
|
- lib/jira/resource/remotelink.rb
|
|
134
136
|
- lib/jira/resource/resolution.rb
|
|
@@ -145,6 +147,7 @@ files:
|
|
|
145
147
|
- lib/jira/resource/worklog.rb
|
|
146
148
|
- lib/jira/version.rb
|
|
147
149
|
- lib/tasks/generate.rake
|
|
150
|
+
- spec/data/files/jwt-signed-urls.json
|
|
148
151
|
- spec/data/files/short.txt
|
|
149
152
|
- spec/integration/attachment_spec.rb
|
|
150
153
|
- spec/integration/comment_spec.rb
|
|
@@ -155,6 +158,7 @@ files:
|
|
|
155
158
|
- spec/integration/issuetype_spec.rb
|
|
156
159
|
- spec/integration/priority_spec.rb
|
|
157
160
|
- spec/integration/project_spec.rb
|
|
161
|
+
- spec/integration/properties_spec.rb
|
|
158
162
|
- spec/integration/rapidview_spec.rb
|
|
159
163
|
- spec/integration/resolution_spec.rb
|
|
160
164
|
- spec/integration/status_category_spec.rb
|
|
@@ -165,6 +169,7 @@ files:
|
|
|
165
169
|
- spec/integration/watcher_spec.rb
|
|
166
170
|
- spec/integration/webhook_spec.rb
|
|
167
171
|
- spec/integration/worklog_spec.rb
|
|
172
|
+
- spec/jira/atlassian/jwt_spec.rb
|
|
168
173
|
- spec/jira/base_factory_spec.rb
|
|
169
174
|
- spec/jira/base_spec.rb
|
|
170
175
|
- spec/jira/client_spec.rb
|
|
@@ -208,6 +213,10 @@ files:
|
|
|
208
213
|
- spec/mock_responses/issue/10002/comment.post.json
|
|
209
214
|
- spec/mock_responses/issue/10002/comment/10000.json
|
|
210
215
|
- spec/mock_responses/issue/10002/comment/10000.put.json
|
|
216
|
+
- spec/mock_responses/issue/10002/properties.json
|
|
217
|
+
- spec/mock_responses/issue/10002/properties/foo.json
|
|
218
|
+
- spec/mock_responses/issue/10002/properties/xyz.json
|
|
219
|
+
- spec/mock_responses/issue/10002/properties/xyz.put.json
|
|
211
220
|
- spec/mock_responses/issue/10002/transitions.json
|
|
212
221
|
- spec/mock_responses/issue/10002/transitions.post.json
|
|
213
222
|
- spec/mock_responses/issue/10002/watchers.json
|
|
@@ -219,8 +228,6 @@ files:
|
|
|
219
228
|
- spec/mock_responses/issueLinkType/10000.json
|
|
220
229
|
- spec/mock_responses/issuetype.json
|
|
221
230
|
- spec/mock_responses/issuetype/5.json
|
|
222
|
-
- spec/mock_responses/jira/rest/webhooks/1.0/webhook.json
|
|
223
|
-
- spec/mock_responses/jira/rest/webhooks/1.0/webhook/2.json
|
|
224
231
|
- spec/mock_responses/priority.json
|
|
225
232
|
- spec/mock_responses/priority/1.json
|
|
226
233
|
- spec/mock_responses/project.json
|
|
@@ -244,7 +251,7 @@ files:
|
|
|
244
251
|
- spec/mock_responses/version/10000.json
|
|
245
252
|
- spec/mock_responses/version/10000.put.json
|
|
246
253
|
- spec/mock_responses/webhook.json
|
|
247
|
-
- spec/mock_responses/webhook/
|
|
254
|
+
- spec/mock_responses/webhook/2.json
|
|
248
255
|
- spec/spec_helper.rb
|
|
249
256
|
- spec/support/clients_helper.rb
|
|
250
257
|
- spec/support/matchers/have_attributes.rb
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
[{"name":"from API",
|
|
2
|
-
"url":"http://localhost:3000/webhooks/1",
|
|
3
|
-
"excludeBody":false,
|
|
4
|
-
"filters":{"issue-related-events-section":""},
|
|
5
|
-
"events":[],
|
|
6
|
-
"enabled":true,
|
|
7
|
-
"self":"http://localhost:2990/jira/rest/webhooks/1.0/webhook/2",
|
|
8
|
-
"lastUpdatedUser":"admin",
|
|
9
|
-
"lastUpdatedDisplayName":"admin",
|
|
10
|
-
"lastUpdated":1453306520188
|
|
11
|
-
}]
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
{"name":"from API",
|
|
2
|
-
"url":"http://localhost:3000/webhooks/1",
|
|
3
|
-
"excludeBody":false,
|
|
4
|
-
"filters":{"issue-related-events-section":""},
|
|
5
|
-
"events":[],
|
|
6
|
-
"enabled":true,
|
|
7
|
-
"self":"http://localhost:2990/jira/rest/webhooks/1.0/webhook/2",
|
|
8
|
-
"lastUpdatedUser":"admin",
|
|
9
|
-
"lastUpdatedDisplayName":"admin",
|
|
10
|
-
"lastUpdated":1453306520188
|
|
11
|
-
}
|
|
File without changes
|