Send a federation query to a Stellar Federation service.

    For more info, see the `complete guide on Stellar Federation.
    <https://www.stellar.org/developers/guides/concepts/federation.html>`_.

    :param str address_or_id: The address which you expect te retrieve
        federation information about.
    :param str fed_type: The type of federation query that you are making. Must
        be 'name', 'id', 'forward', or 'txid'.
    :param str domain: The domain that corresponds to the address or ID;
        this is where the stellar.toml file lives (which ultimately points to
        the URL of the federation service).
    :param bool allow_http: Whether to allow for requests over plain HTTP over
        HTTPS. Note - you should *always* use HTTPS outside of testing.
    :return dict: The federation query response decoded from JSON as a dict.

def federation(address_or_id, fed_type='name', domain=None, allow_http=False):
    """Send a federation query to a Stellar Federation service.

    For more info, see the `complete guide on Stellar Federation.
    <https://www.stellar.org/developers/guides/concepts/federation.html>`_.

    :param str address_or_id: The address which you expect te retrieve
        federation information about.
    :param str fed_type: The type of federation query that you are making. Must
        be 'name', 'id', 'forward', or 'txid'.
    :param str domain: The domain that corresponds to the address or ID;
        this is where the stellar.toml file lives (which ultimately points to
        the URL of the federation service).
    :param bool allow_http: Whether to allow for requests over plain HTTP over
        HTTPS. Note - you should *always* use HTTPS outside of testing.
    :return dict: The federation query response decoded from JSON as a dict.

    """
    if fed_type == 'name':
        if '*' not in address_or_id:
            raise FederationError('Not a valid federation address.')

        param, domain = address_or_id.rsplit('*', 1)
        if param == '' or domain == '':
            raise FederationError('Not a valid federation address.')
    elif fed_type == 'id':
        try:
            assert is_valid_address(address_or_id)
        except StellarAddressInvalidError:
            raise FederationError('{} is not a valid account id.'.format(address_or_id))
    else:
        raise FederationError('Not a valid fed_type.')

    if '.' not in domain:
        raise FederationError('Not a valid domain name.')
    fed_service = get_federation_service(domain, allow_http)
    if not fed_service:
        raise FederationError('Not a valid federation server.')

    return _get_federation_info(address_or_id, fed_service, fed_type)