Skip to content

Commit

Permalink
Add from_multipart
Browse files Browse the repository at this point in the history
  • Loading branch information
paulcsmith committed Mar 19, 2020
1 parent 104ee2d commit 7578a11
Show file tree
Hide file tree
Showing 2 changed files with 55 additions and 13 deletions.
22 changes: 19 additions & 3 deletions spec/lucky/params_spec.cr
Original file line number Diff line number Diff line change
Expand Up @@ -39,10 +39,26 @@ describe Lucky::Params do
end
end

describe "#from_multiple_form" do
end
describe "#from_multipart" do
it "returns a Tuple with form data in first position" do
request = build_multipart_request form_parts: {"from" => "multipart"}

params = Lucky::Params.new(request)

params.from_multipart.first["from"].should eq("multipart")
end

describe "#from_multiple_files" do
it "returns a Tuple with files in second position" do
request = build_multipart_request file_parts: {
"avatar" => "file_contents",
}

params = Lucky::Params.new(request)

file = params.from_multipart.last["avatar"]
file.should be_a(Lucky::UploadedFile)
File.read(file.path).should eq "file_contents"
end
end

it "works when parsing params twice" do
Expand Down
46 changes: 36 additions & 10 deletions src/lucky/params.cr
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@ class Lucky::Params
@request : HTTP::Request
@route_params : Hash(String, String) = {} of String => String

alias MultipartParams = Hash(String, String)
alias MultipartFiles = Hash(String, Lucky::UploadedFile)

# :nodoc:
private getter :request
# :nodoc:
Expand Down Expand Up @@ -47,7 +50,7 @@ class Lucky::Params

# Returns just the query params as `HTTP::Params`
#
# Returns an `HTTP::Params` object for only the query params. This is rarely
# Returns an `HTTP::Params` object for only the query params. This method is rarely
# helpful since you can get query params with `get`, but if you do need raw
# access to the query params this is the way to get them.
#
Expand All @@ -62,7 +65,7 @@ class Lucky::Params

# Returns x-www-form-urlencoded body params as `HTTP::Params`
#
# Returns an `HTTP::Params` object for the request body. This is rarely
# Returns an `HTTP::Params` object for the request body. This method is rarely
# helpful since you can get query params with `get`, but if you do need raw
# access to the body params this is the way to get them.
#
Expand All @@ -75,6 +78,24 @@ class Lucky::Params
form_params
end

# Returns multipart params and files.
#
# Return a Tuple with a hash of params and a hash of `Lucky::UploadedFile`.
# This method is rarely helpful since you can get params with `get` and files
# with `get_file`, but if you need something more custom you can use this method
# to get better access to the raw params.
#
# ```crystal
# form_params = params.from_multipart.last # Hash(String, String)
# form_params["name"] # "Kyle"
#
# files = params.from_multipart.last # Hash(String, Lucky::UploadedFile)
# files["avatar"] # Lucky::UploadedFile
# ```
def from_multipart : Tuple(MultipartParams, MultipartFiles)
parse_multipart_request
end

# Retrieve a value from the params hash, raise if key is absent
#
# If no key is found a `Lucky::MissingParamError` will be raised:
Expand All @@ -90,8 +111,8 @@ class Lucky::Params
# Retrieve a value from the params hash, return nil if key is absent
#
# ```crystal
# params.get?("page") # 1 : (String | Nil)
# params.get?("missing") # nil : (String | Nil)
# params.get?("page") # 1 : (String | Nil)
# ```
def get?(key : String | Symbol) : String?
route_params[key.to_s]? || body_param(key.to_s) || query_params[key.to_s]?
Expand All @@ -102,8 +123,12 @@ class Lucky::Params
# If no key is found a `Lucky::MissingParamError` will be raised:
#
# ```crystal
# params.get_file("avatar_file") # Lucky::UploadedFile
# params.get_file("missing") # Raise: Missing parameter: missing
# params.get_file("missing") # Raise: Missing parameter: missing
#
# file = params.get_file("avatar_file") # Lucky::UploadedFile
# file.name # avatar.png
# file.metadata # HTTP::FormData::FileMetadata
# file.tempfile.read # Get the file contents
# ```
def get_file(key) : Lucky::UploadedFile
get_file?(key) || raise Lucky::MissingParamError.new(key.to_s)
Expand All @@ -112,8 +137,12 @@ class Lucky::Params
# Retrieve a file from the params hash, return nil if key is absent
#
# ```crystal
# params.get_file?("avatar_file") # (Lucky::UploadedFile | Nil)
# params.get_file?("missing") # nil
# params.get_file?("missing") # nil
#
# file = params.get_file?("avatar_file") # Lucky::UploadedFile
# file.not_nil!.name # avatar.png
# file.not_nil!.metadata # HTTP::FormData::FileMetadata
# file.not_nil!.tempfile.read # Get the file contents
# ```
def get_file?(key : String | Symbol) : Lucky::UploadedFile?
multipart_files[key.to_s]?
Expand Down Expand Up @@ -413,9 +442,6 @@ class Lucky::Params
@_parsed_multipart_request ||= parse_form_data
end

alias MultipartParams = Hash(String, String)
alias MultipartFiles = Hash(String, Lucky::UploadedFile)

private def parse_form_data : Tuple(MultipartParams, MultipartFiles)
multipart_params = MultipartParams.new
multipart_files = MultipartFiles.new
Expand Down

0 comments on commit 7578a11

Please sign in to comment.