storage_extended_error parse_extended_error(const web::http::http_response& response)
    {
        const web::http::http_headers& headers = response.headers();

        utility::string_t content_type;
        headers.match(web::http::header_names::content_type, content_type);
        std::transform(content_type.begin(), content_type.end(), content_type.begin(), core::utility_char_tolower);

        if (is_matching_content_type(content_type, protocol::header_value_content_type_json)) // application/json
        {
            web::json::value document = response.extract_json().get();
            return protocol::parse_table_error(document);
        }
        else // application/xml
        {
            utility::string_t error_code;
            utility::string_t error_message;
            std::unordered_map<utility::string_t, utility::string_t> details;

            concurrency::streams::istream body_stream = response.body();
            protocol::storage_error_reader reader(body_stream);
            error_code = reader.move_error_code();
            error_message = reader.move_error_message();
            details = reader.move_details();

            return storage_extended_error(std::move(error_code), std::move(error_message), std::move(details));
        }
    }
    cloud_blob_properties blob_response_parsers::parse_blob_properties(const web::http::http_response& response)
    {
        cloud_blob_properties properties;

        properties.m_etag = parse_etag(response);
        properties.m_last_modified = parse_last_modified(response);
        properties.m_lease_status = parse_lease_status(response);
        properties.m_lease_state = parse_lease_state(response);
        properties.m_lease_duration = parse_lease_duration(response);
        properties.m_size = parse_blob_size(response);

        auto& headers = response.headers();
        properties.m_page_blob_sequence_number = utility::conversions::scan_string<int64_t>(get_header_value(headers, ms_header_blob_sequence_number));
        properties.m_append_blob_committed_block_count = utility::conversions::scan_string<int>(get_header_value(headers, ms_header_blob_committed_block_count));
        properties.m_cache_control = get_header_value(headers, web::http::header_names::cache_control);
        properties.m_content_disposition = get_header_value(headers, header_content_disposition);
        properties.m_content_encoding = get_header_value(headers, web::http::header_names::content_encoding);
        properties.m_content_language = get_header_value(headers, web::http::header_names::content_language);
        properties.m_content_type = get_header_value(headers, web::http::header_names::content_type);
        properties.m_type = parse_blob_type(get_header_value(headers, ms_header_blob_type));
        properties.m_content_md5 = get_header_value(headers, ms_header_blob_content_md5);
        if (properties.m_content_md5.empty())
        {
            properties.m_content_md5 = get_header_value(headers, web::http::header_names::content_md5);
        }

        properties.m_server_encrypted = response_parsers::parse_boolean(get_header_value(headers, ms_header_server_encrypted));
        properties.m_is_incremental_copy = response_parsers::parse_boolean(get_header_value(headers, ms_header_incremental_copy));

        return properties;
    }
    utility::datetime parse_next_visible_time(const web::http::http_response& response)
    {
        utility::string_t value;
        if (response.headers().match(ms_header_time_next_visible, value))
        {
            return utility::datetime::from_string(value, utility::datetime::RFC_1123);
        }

        return utility::datetime();
    }
    utility::string_t parse_pop_receipt(const web::http::http_response& response)
    {
        utility::string_t value;
        if (response.headers().match(ms_header_pop_receipt, value))
        {
            return value;
        }

        return utility::string_t();
    }
    int parse_approximate_messages_count(const web::http::http_response& response)
    {
        utility::string_t value;
        if (response.headers().match(ms_header_approximate_messages_count, value))
        {
            return utility::conversions::scan_string<int>(value);
        }

        return -1;
    }
 utility::datetime parse_last_modified(const web::http::http_response& response)
 {
     utility::string_t value;
     if (response.headers().match(web::http::header_names::last_modified, value))
     {
         return parse_last_modified(value);
     }
     else
     {
         return utility::datetime();
     }
 }
 std::chrono::seconds parse_lease_time(const web::http::http_response& response)
 {
     utility::string_t value;
     if (response.headers().match(ms_header_lease_time, value))
     {
         int64_t seconds = utility::conversions::scan_string<int64_t>(value);
         return std::chrono::seconds(seconds);
     }
     else
     {
         return std::chrono::seconds();
     }
 }
    cloud_metadata parse_metadata(const web::http::http_response& response)
    {
        cloud_metadata metadata;

        auto& headers = response.headers();
        for (auto it = headers.begin(); it != headers.end(); ++it)
        {
            const utility::string_t& key = it->first;
            if ((key.size() > ms_header_metadata_prefix.size()) &&
                std::equal(ms_header_metadata_prefix.cbegin(), ms_header_metadata_prefix.cend(), key.cbegin()))
            {
                metadata.insert(std::make_pair(key.substr(ms_header_metadata_prefix.size()), it->second));
            }
        }

        return metadata;
    }
    utility::size64_t blob_response_parsers::parse_blob_size(const web::http::http_response& response)
    {
        auto& headers = response.headers();
        utility::string_t value;

        if (headers.match(web::http::header_names::content_range, value))
        {
            auto slash = value.find(_XPLATSTR('/'));
            value = value.substr(slash + 1);
            return utility::conversions::scan_string<utility::size64_t>(value);
        }

        if (headers.match(ms_header_blob_content_length, value))
        {
            return utility::conversions::scan_string<utility::size64_t>(value);
        }

        return headers.content_length();
    }
 utility::string_t get_header_value(const web::http::http_response& response, const utility::string_t& header)
 {
     return get_header_value(response.headers(), header);
 }