private function normalizeOptions(array $options)
    {
        $options += [
            'method' => 'GET',
            'cname' => self::DEFAULT_DOWNLOAD_HOST,
            'contentMd5' => null,
            'contentType' => null,
            'headers' => [],
            'saveAsName' => null,
            'responseDisposition' => null,
            'responseType' => null,
            'keyFile' => null,
            'keyFilePath' => null,
            'allowPost' => false,
            'forceOpenssl' => false,
            'queryParams' => [],
            'timestamp' => null
        ];

        $allowedMethods = ['GET', 'PUT', 'POST', 'DELETE'];
        $options['method'] = strtoupper($options['method']);
        if (!in_array($options['method'], $allowedMethods)) {
            throw new \InvalidArgumentException('$options.method must be one of `GET`, `PUT` or `DELETE`.');
        }

        if ($options['method'] === 'POST' && !$options['allowPost']) {
            throw new \InvalidArgumentException(
                'Invalid method. To create an upload URI, use StorageObject::signedUploadUrl().'
            );
        }
        unset($options['allowPost']);

        // For backwards compatibility, strip protocol from cname.
        $cnameParts = explode('//', $options['cname']);
        if (count($cnameParts) > 1) {
            $options['cname'] = $cnameParts[1];
        }

        $options['cname'] = trim($options['cname'], '/');

        // If a timestamp is provided, use it in place of `now` for v4 URLs only..
        // This option exists for testing purposes, and should not generally be provided by users.
        if ($options['timestamp']) {
            if (!($options['timestamp'] instanceof \DateTimeInterface)) {
                if (!is_string($options['timestamp'])) {
                    throw new \InvalidArgumentException(
                        'User-provided timestamps must be a string or instance of `\DateTimeInterface`.'
                    );
                }

                $options['timestamp'] = \DateTimeImmutable::createFromFormat(
                    self::V4_TIMESTAMP_FORMAT,
                    $options['timestamp'],
                    new \DateTimeZone('UTC')
                );

                if (!$options['timestamp']) {
                    throw new \InvalidArgumentException(
                        'Given timestamp string is in an invalid format. Provide timestamp formatted as follows: `' .
                        self::V4_TIMESTAMP_FORMAT .
                        '`. Note that timestamps MUST be in UTC.'
                    );
                }
            }
        } else {
            $options['timestamp'] = new \DateTimeImmutable('now', new \DateTimeZone('UTC'));
        }

        return $options;
    }