Skip to content

Commit

Permalink
Merge pull request #48 from jrester/uri_escape
Browse files Browse the repository at this point in the history
Make encoding of URI optional
  • Loading branch information
taylorfinnell authored Apr 29, 2020
2 parents da46c62 + facd698 commit 7c87c0b
Show file tree
Hide file tree
Showing 5 changed files with 41 additions and 189 deletions.
23 changes: 7 additions & 16 deletions spec/awscr-signer/v4/request_spec.cr
Original file line number Diff line number Diff line change
Expand Up @@ -5,58 +5,49 @@ module Awscr
describe Request do
it "does not modify http request body" do
body = IO::Memory.new("body")
request = Request.new("GET", URI.parse("/"), body)
request = Request.new("GET", "/", body)
body.gets_to_end.should eq("body")
end

it "alerts of ignored query params" do
expect_raises Exception do
Request.new("GET", URI.parse("http://google.com?test=1"), "")
Request.new("GET", "http://google.com?test=1", "")
end
end

describe "digest" do
it "returns unsigned payload if body is unsigned payload" do
request = Request.new("GET", URI.parse("/"), "UNSIGNED-PAYLOAD")
request = Request.new("GET", "/", "UNSIGNED-PAYLOAD")

request.digest.should eq("UNSIGNED-PAYLOAD")
end

it "returns digest of body" do
body = IO::Memory.new("body")
request = Request.new("GET", URI.parse("/"), body)
request = Request.new("GET", "/", body)

request.digest.should eq("230d8358dc8e8890b4c58deeb62912ee2f20357ae92a5cc861b98e68fe31acb5")
end
end

describe "host" do
it "returns the uri host" do
request = Request.new("GET", URI.parse("/"), "")
request = Request.new("GET", "/", "")
request.host.should eq(nil)
end

it "returns host if set" do
request = Request.new("GET", URI.parse("/"), "")
request = Request.new("GET", "/", "")
request.headers.add("Host", "test")

request.host.should eq("test")
end
end

describe "full_path" do
it "returns the full url incl query string" do
request = Request.new("GET", URI.parse("http://google.com"), "")
request.query.add("blah", "1")

request.full_path.should eq("http://google.com?blah=1")
end
end

describe "to_s" do
it "returns a valid string" do
body = ""
request = Request.new("GET", URI.parse("/"), body)
request = Request.new("GET", "/", body)

request.headers.add("Content-Type", "application/x-www-form-urlencoded; charset=utf-8")
request.headers.add("Host", "iam.amazonaws.com")
Expand Down
103 changes: 0 additions & 103 deletions spec/awscr-signer/v4/uri_spec.cr

This file was deleted.

16 changes: 8 additions & 8 deletions src/awscr-signer/signers/v4.cr
Original file line number Diff line number Diff line change
Expand Up @@ -25,22 +25,22 @@ module Awscr
end

# Sign an HTTP::Request
def sign(request : HTTP::Request, add_sha = true)
header_impl(request, add_sha)
def sign(request : HTTP::Request, add_sha = true, encode_path = true)
header_impl(request, add_sha, encode_path)
end

def presign(request)
querystring_impl(request)
def presign(request, encode_path = true)
querystring_impl(request, encode_path)
end

private def querystring_impl(request)
private def querystring_impl(request, encode_path)
scope = Signer::Scope.new(@region, @service)
request.query_params.add("X-Amz-Algorithm", Signer::ALGORITHM)
request.query_params.add("X-Amz-Credential", "#{@credentials.key}/#{scope}")
request.query_params.add("X-Amz-Date", scope.date.iso8601)

canonical_request = Signer::V4::Request.new(request.method,
URI.parse(request.path), request.body)
request.path, request.body, encode_path)

request.query_params.to_h.each do |k, v|
canonical_request.query.add(k, v)
Expand All @@ -57,7 +57,7 @@ module Awscr
request.query_params.add("X-Amz-Signature", signature.to_s)
end

private def header_impl(request, add_sha)
private def header_impl(request, add_sha, encode_path)
scope = Signer::Scope.new(@region, @service)

@amz_security_token.try do |token|
Expand All @@ -74,7 +74,7 @@ module Awscr
end

canonical_request = Signer::V4::Request.new(request.method,
URI.parse(request.path), request.body)
request.path, request.body, encode_path)

request.query_params.to_h.each do |k, v|
canonical_request.query.add(k, v)
Expand Down
38 changes: 26 additions & 12 deletions src/awscr-signer/v4/request.cr
Original file line number Diff line number Diff line change
Expand Up @@ -30,17 +30,14 @@ module Awscr
# The request body
getter body

@uri : Uri
@path : String
@digest : String
@body : IO
@query : QueryString
@encode : Bool

def initialize(method : String, uri : URI, body : IO | String | Nil)
raise Exception.new("You may not give a URI with query params, they are
ignored. Use #query object intead") unless uri.query.nil?

@method = method
@uri = Uri.new(uri)
def initialize(@method : String, path : String, body : IO | String | Nil, @encode=true)
@path = build_path(path)
@query = QueryString.new
@headers = HeaderCollection.new
@body = build_body(body)
Expand All @@ -51,15 +48,11 @@ module Awscr
@headers["Host"]?.try(&.value)
end

def full_path
"#{@uri}?#{query}"
end

# Returns the request as a String.
def to_s(io : IO)
io << [
@method,
@uri.path,
@path,
query,
headers,
@headers.keys.join(";"),
Expand All @@ -83,6 +76,27 @@ module Awscr
end
end

# Encodes the path except '/' and '~'
def self.encode_path(path)
String.build do |io|
URI.encode(path, io) { |byte| URI.unreserved?(byte) || byte.chr == '/' || byte.chr == '~' }
end
end

private def build_path(path)
return "/" if path.blank?
uri = URI.parse(path)
raise Exception.new("You may not give a URI with query params, they are
ignored. Use #query object intead") unless uri.query.nil?

path = uri.normalize.path
if @encode
self.class.encode_path(path)
else
path
end
end

private def build_body(body)
case body
when IO
Expand Down
50 changes: 0 additions & 50 deletions src/awscr-signer/v4/uri.cr

This file was deleted.

0 comments on commit 7c87c0b

Please sign in to comment.