Skip to content
Open
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 13 additions & 4 deletions google-apis-core/lib/google/apis/core/storage_upload.rb
Original file line number Diff line number Diff line change
Expand Up @@ -176,22 +176,32 @@ def send_upload_command(client)
request_header = header.dup
request_header[CONTENT_RANGE_HEADER] = get_content_range_header current_chunk_size
request_header[CONTENT_LENGTH_HEADER] = current_chunk_size.to_s
last_chunk= remaining_content_size <= current_chunk_size
Comment thread
shubhangi-google marked this conversation as resolved.
Outdated
hash_data= JSON.parse(body)
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

critical

The body variable (which is self.body of the command) can be an empty string if no request_object (metadata) is provided. JSON.parse('') will raise a JSON::ParserError, causing the upload to crash. This line needs to safely handle cases where body is empty or not valid JSON.

Furthermore, if the body contains static metadata like checksums, parsing it in every send_upload_command call (which occurs for each chunk) is inefficient. Consider parsing this data once, perhaps in the prepare! method, and storing the formatted_string in an instance variable for reuse.

hash_data = body.to_s.empty? ? {} : JSON.parse(body)


target_keys = ["crc32c", "md5Hash", "md5"]
selected_keys = hash_data.slice(*target_keys)
formatted_string = selected_keys.map do |key, value|
output_key = (key == "md5Hash") ? "md5" : key
"#{output_key}=#{value}"
end.join(',')
request_header['X-Goog-Hash'] = formatted_string if last_chunk

chunk_body =
if @upload_chunk_size == 0
upload_io
else
StringIO.new(upload_io.read(current_chunk_size))
end

response = client.put(@upload_url, chunk_body, request_header)

result = process_response(response.status.to_i, response.headers, response.body)
@upload_incomplete = false if response.status.to_i.eql? OK_STATUS
@offset += current_chunk_size if @upload_incomplete
success(result)

rescue => e
logger.warn {
"error occured please use uploadId-#{response.headers['X-GUploader-UploadID']} to resume your upload"
"error occurred please use uploadId-#{response.headers['X-GUploader-UploadID']} to resume your upload , error==> #{e}"
} unless response.nil?
upload_io.pos = @offset
error(e, rethrow: true)
Expand Down Expand Up @@ -246,7 +256,6 @@ def cancel_resumable_upload(client)

def handle_resumable_upload_http_response_codes(response)
code = response.status.to_i

case code
when 308
if response.headers['Range']
Expand Down