Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #147 from croservices/IRI-handling
Iri handling
- Loading branch information
Showing
6 changed files
with
137 additions
and
78 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
use Cro::Uri :decode-percents, :encode-percents; | ||
use Cro::HTTP::MultiValue; | ||
use Cro::Uri::HTTP; | ||
use Cro::Iri; | ||
use Cro::ResourceIdentifier::HTTP; | ||
|
||
class Cro::Iri::HTTP is Cro::Iri does Cro::ResourceIdentifier::HTTP { | ||
grammar Parser is Cro::Iri::GenericParser { | ||
proto token request-target { * } | ||
token request-target:sym<origin-form> { | ||
<iabsolute-path> [ "?" <iquery> ]? | ||
} | ||
|
||
token iabsolute-path { | ||
[ "/" <isegment> ]+ | ||
} | ||
} | ||
|
||
grammar Actions is Cro::Iri::GenericActions { | ||
method request-target:sym<origin-form>($/) { | ||
make Cro::Iri::HTTP.bless( | ||
path => $<iabsolute-path>.ast, | ||
|(query => .ast with $<iquery>) | ||
); | ||
} | ||
|
||
method iabsolute-path($/) { | ||
make ~$/; | ||
} | ||
} | ||
|
||
method to-uri-http(--> Cro::Uri::HTTP) { | ||
Cro::Uri::HTTP.new(:$.path, :$.query) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
use Cro::HTTP::MultiValue; | ||
use Cro::Uri :decode-percents, :encode-percents; | ||
|
||
package Cro::ResourceIdentifier::HTTP { | ||
#| Decodes a query string part. This involves replacing any + | ||
#| characters with spaces, followed by the standard URI decoding | ||
#| algorithm. | ||
our sub decode-query-string-part(Str $part --> Str) is export(:decode-query-string-part) { | ||
decode-percents $part.subst('+', ' ', :g) | ||
} | ||
} | ||
|
||
role Cro::ResourceIdentifier::HTTP { | ||
has @!cached-query-list; | ||
has %!cached-query-hash; | ||
|
||
method query-list() { | ||
# Race to compute this. The bind makes it thread-safe to put in place. | ||
unless @!cached-query-list { | ||
with self.query { | ||
@!cached-query-list := list eager .split('&').map: -> $kv { | ||
my @kv := $kv.split('=', 2).list; | ||
Pair.new: | ||
key => Cro::ResourceIdentifier::HTTP::decode-query-string-part(@kv[0]), | ||
value => Cro::ResourceIdentifier::HTTP::decode-query-string-part(@kv[1] // '') | ||
} | ||
} | ||
} | ||
@!cached-query-list | ||
} | ||
|
||
method query-hash() { | ||
# Race to compute this. The bind at the end makes it thread-safe to | ||
# put it in place, as opposed to an assignment which would not be. | ||
unless %!cached-query-hash { | ||
my %query-hash; | ||
with self.query { | ||
for .split('&') -> $kv { | ||
my @kv := $kv.split('=', 2).list; | ||
my $key = Cro::ResourceIdentifier::HTTP::decode-query-string-part(@kv[0]); | ||
my $value = Cro::ResourceIdentifier::HTTP::decode-query-string-part(@kv[1] // ''); | ||
with %query-hash{$key} -> $existing { | ||
%query-hash{$key} = Cro::HTTP::MultiValue.new( | ||
$existing ~~ Cro::HTTP::MultiValue | ||
?? $existing.Slip | ||
!! $existing, | ||
$value | ||
); | ||
} | ||
else { | ||
%query-hash{$key} = $value; | ||
} | ||
} | ||
} | ||
%!cached-query-hash := %query-hash; | ||
} | ||
%!cached-query-hash | ||
} | ||
|
||
#| Encodes the specified query string parameters and returns a new URI that incorporates | ||
#| them. Any existing query string parameters will be retained. | ||
method add-query(*@pairs, *%named-paris) { | ||
my @parts; | ||
if self.query -> $existing { | ||
@parts.push($existing); | ||
} | ||
for flat @pairs, %named-paris.pairs { | ||
@parts.push(encode-percents(.key.Str) ~ '=' ~ encode-percents(.value.Str)); | ||
} | ||
self.add('?' ~ @parts.join("&")) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters