protected function normalizeProxy(Options $options, $value)
    {
        if (!$value) {
            // proxy setting is optional
            return false;
        }
        if (is_string($value)) {
            $url_parts = parse_url($value);
            if ($url_parts === false) {
                throw new InvalidOptionsException('"proxy" configuration setting contains a malformed url.');
            }

            $proxy_array = array(
                'proxy_host' => $url_parts['host']
            );
            if (isset($url_parts['port'])) {
                $proxy_array['proxy_port'] = $url_parts['port'];
            }
            if (isset($url_parts['user'])) {
                $proxy_array['proxy_login'] = $url_parts['user'];
            }
            if (isset($url_parts['pass'])) {
                $proxy_array['proxy_password'] = $url_parts['pass'];
            }
            $value = $proxy_array;
        } elseif (is_array($value)) {
            foreach ($value as $k => $v) {
                // Prepend proxy_ to each key to match the expended proxy option names of the PHP SoapClient.
                $value['proxy_' . $k] = $v;
                unset($value[$k]);
            }

            if (empty($value['proxy_host']) || empty($value['proxy_port'])) {
                throw new InvalidOptionsException(
                    '"proxy" configuration setting must contain at least keys "host" and "port'
                );
            }
        } else {
            throw new InvalidOptionsException(
                '"proxy" configuration setting must be either a string containing the proxy url '
                . 'or an array containing at least a key "host" and "port"'
            );
        }

        // Make sure port is an integer
        $value['proxy_port'] = intval($value['proxy_port']);

        return $value;
    }