Fix multipart upload and back params.files (#499)

This commit is contained in:
Serdar Dogruyol 2018-11-05 02:20:21 +03:00 committed by GitHub
parent 207f38251a
commit 7358994e91
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 51 additions and 0 deletions

24
src/kemal/file_upload.cr Normal file
View file

@ -0,0 +1,24 @@
module Kemal
struct FileUpload
getter tempfile : File
getter filename : String?
getter headers : HTTP::Headers
getter creation_time : Time?
getter modification_time : Time?
getter read_time : Time?
getter size : UInt64?
def initialize(upload)
@tempfile = File.tempfile
::File.open(@tempfile.path, "w") do |file|
IO.copy(upload.body, file)
end
@filename = upload.filename
@headers = upload.headers
@creation_time = upload.creation_time
@modification_time = upload.modification_time
@read_time = upload.read_time
@size = upload.size
end
end
end

View file

@ -9,15 +9,18 @@ module Kemal
PARTS = %w(url query body json)
# :nodoc:
alias AllParamTypes = Nil | String | Int64 | Float64 | Bool | Hash(String, JSON::Any) | Array(JSON::Any)
getter files
def initialize(@request : HTTP::Request, @url : Hash(String, String) = {} of String => String)
@query = HTTP::Params.new({} of String => Array(String))
@body = HTTP::Params.new({} of String => Array(String))
@json = {} of String => AllParamTypes
@files = {} of String => FileUpload
@url_parsed = false
@query_parsed = false
@body_parsed = false
@json_parsed = false
@files_parsed = false
end
private def unescape_url_param(value : String)
@ -40,11 +43,17 @@ module Kemal
private def parse_body
content_type = @request.headers["Content-Type"]?
return unless content_type
if content_type.try(&.starts_with?(URL_ENCODED_FORM))
@body = parse_part(@request.body)
return
end
if content_type.try(&.starts_with?(MULTIPART_FORM))
parse_files
end
end
private def parse_query
@ -55,6 +64,24 @@ module Kemal
@url.each { |key, value| @url[key] = unescape_url_param(value) }
end
private def parse_files
return if @files_parsed
HTTP::FormData.parse(@request) do |upload|
next unless upload
filename = upload.filename
if !filename.nil?
@files[upload.name] = FileUpload.new(upload)
else
@body.add(upload.name, upload.body.gets_to_end)
end
end
@files_parsed = true
end
# Parses JSON request body if Content-Type is `application/json`.
#
# - If request body is a JSON `Hash` then all the params are parsed and added into `params`.