Getting "If-Match or If-None-Match header or entry etag attribute required" errors when batch deleting contacts

StackOverflow https://stackoverflow.com/questions/23576729

Pergunta

I'm using the gdata Python library to do batched deletes of contacts, and I just get the "If-Match or If-None-Match header or entry etag attribute required" error.

I think the problem started when I had to enable the Contacts API in the console (which until a few days ago wasn't required? *).

EDIT:

It's actually failing for both updating and deleting operations. Batched insert works fine.

Tried specifying the If-Match header, but it's still failing:

custom_headers = atom.client.CustomHeaders(**{'If-Match': '*'})
request_feed = gdata.contacts.data.ContactsFeed()
request_feed.AddDelete(entry=contact, batch_id_string='delete')
response_feed = self.gd_client.ExecuteBatch(
        request_feed,
        'https://www.google.com/m8/feeds/contacts/default/full/batch',
        custom_headers=custom_headers
)

Also created a ticket on the project page, but I doubt it will get any attention there.

EDIT 2:

Using the Batch method with force=True (which just adds the If-Match: * header) is the same result.

response_feed = self.gd_client.Batch(
    request_feed,
    uri='https://www.google.com/m8/feeds/contacts/default/full/batch',
    force=True
)

* Can someone verify this? I never had to enable it in the console before and my app was able to use the Contacts API without problem, and I believe it wasn't even available before. I was surprised to see it yesterday.

Foi útil?

Solução

Copying answer from the Google code ticket.

Basically, you need to patch the client's Post method to modify the request feed slightly. Here's one way to do it without directly modifying the library source:

def patched_post(client, entry, uri, auth_token=None, converter=None, desired_class=None, **kwargs):
    if converter is None and desired_class is None:
        desired_class = entry.__class__
    http_request = atom.http_core.HttpRequest()
    entry_string = entry.to_string(gdata.client.get_xml_version(client.api_version))
    entry_string = entry_string.replace('ns1', 'gd')  # where the magic happens
    http_request.add_body_part(
        entry_string,
        'application/atom+xml')
    return client.request(method='POST', uri=uri, auth_token=auth_token,
                          http_request=http_request, converter=converter,
                          desired_class=desired_class, **kwargs)

# when it comes time to do a batched delete/update,
# instead of calling client.ExecuteBatch, instead directly call patched_post
patched_post(client_instance, entry_feed, 'https://www.google.com/m8/feeds/contacts/default/full/batch')

Outras dicas

The ticket referenced in the original post has some updated information and a temporary work around that allows batch deletes to succeed. So far it's working for me!

http://code.google.com/p/gdata-python-client/issues/detail?id=700

You can also specify the etag attribute to get around it. This works in the batch request payload:

  <entry   gd:etag="*"  >
     <batch:id>delete</batch:id>
     <batch:operation type="delete"/>
     <id> urlAsId </id>
  </entry>
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top