400 and 411 Server Responses for Ad Hoc in Python

259 views
Skip to first unread message

robert.m...@bigfishgames.com

unread,
Jun 24, 2013, 7:29:33 PM6/24/13
to adwor...@googlegroups.com
Since there is no library that supports Python 3, I've been hacking this together on my own using the ad hoc reporting service and some of the code samples given on various parts of the API developers section of the site.

My script (below) successfully retrieves the SID, LSID and Auth values. It then attempts to POST the report definition XML, including the appropriate headers.

However, with no discernible logic or pattern, it only returns either 400 or 411 ("Length required") responses. As you can see, I have included the 'Content-Length' header and have even reverted back to the 100% copy/paste version of the report definition XML. My XML validates against the XSD, but I still can't get anything other than 400 and 411.

I've tried a number of different configurations and I'm convinced I'm very close to a working script... but at this point, I can't take this to stackoverflow or anywhere else and ask them to troubleshoot Google's server responses.

Any ideas where I'm going wrong here?

import urllib.parse
import urllib.request
import pprint
import socket

data = [('Email', 'mye...@google.com'), ('Passwd', 'hidden'),
        ('accountType', 'GOOGLE'), ('service', 'adwords')]
auth = ''

testurl = url + "?" + urllib.parse.urlencode(data)

fh = urllib.request.urlopen(testurl)

equals = '='
eqenc = equals.encode('utf-8')

for msg in fh:
    number = 0
    block = msg.split(eqenc)
    for val in block:
##      print (number)
        msgitem = block[number]
        valdecoded = (msgitem.decode('utf-8'))
        if valdecoded == 'SID':
            number +=1
            SID = (block[number].decode('utf-8'))
            number -=1
        elif valdecoded == 'LSID':
            number +=1
            LSID = (block[number].decode('utf-8'))
            number -=1
        elif valdecoded == 'Auth':
            number +=1
            Auth = (block[number].decode('utf-8'))
            number -=1
        number += 1
        
number = 0
fh.close()

#report_definition_xml = '<reportDefinition xmlns="https://adwords.google.com/api/adwords/cm/v201302"><selector><fields>CampaignId</fields><fields>Impressions</fields><fields>Clicks</fields><fields>Cost</fields><predicates><field>Status</field><operator>IN</operator><values>ENABLED</values><values>PAUSED</values></predicates></selector><reportName>Search Query Performance eport</reportName><reportType>SEARCH_QUERY_PERFORMANCE_REPORT</reportType><dateRangeType>LAST_30_DAYS</dateRangeType><downloadFormat>CSV</downloadFormat><includeZeroImpressions>true</includeZeroImpressions></reportDefinition>'
report_definition_xml = '<reportDefinition xmlns="https://adwords.google.com/api/adwords/cm/v201302"><selector><fields>CampaignId</fields><fields>Id</fields><fields>Impressions</fields><fields>Clicks</fields><fields>Cost</fields><predicates><field>Status</field><operator>IN</operator><values>ENABLED</values><values>PAUSED</values></predicates></selector><reportName>Custom Adgroup Performance Report</reportName><reportType>ADGROUP_PERFORMANCE_REPORT</reportType><dateRangeType>LAST_7_DAYS</dateRangeType><downloadFormat>CSV</downloadFormat></reportDefinition>'


payload = urllib.parse.urlencode({'__rdxml': report_definition_xml})


payloadencode = payload.encode('utf-8')

loadlength = len(payloadencode)
print (loadlength)
print (url)

request = urllib.request.Request(url)
request.add_header('Content-Type', 'application/x-www-form-urlencoded')
request.add_header('clientCustomerId', '1234567890')
request.add_header('developerToken', 'abc123easyasdoeraymi')
request.add_header('Authorization', 'GoogleLogin auth=%s' % Auth)
request.add_header('Content-Length', loadlength)
f = urllib.request.urlopen(request, payloadencode, 60)
print(f.read().decode('utf-8'))

The second-to-last line is the one that fails, and returns:

Traceback (most recent call last):
  File "C:/Python33/apicaller3.py", line 71, in <module>
    f = urllib.request.urlopen(request, payloadencode, 60)
  File "C:\Python33\lib\urllib\request.py", line 156, in urlopen
    return opener.open(url, data, timeout)
  File "C:\Python33\lib\urllib\request.py", line 475, in open
    response = meth(req, response)
  File "C:\Python33\lib\urllib\request.py", line 587, in http_response
    'http', request, response, code, msg, hdrs)
  File "C:\Python33\lib\urllib\request.py", line 513, in error
    return self._call_chain(*args)
  File "C:\Python33\lib\urllib\request.py", line 447, in _call_chain
    result = func(*args)
  File "C:\Python33\lib\urllib\request.py", line 595, in http_error_default
    raise HTTPError(req.full_url, code, msg, hdrs, fp)
urllib.error.HTTPError: HTTP Error 400: Bad Request

Or

Traceback (most recent call last):
  File "C:/Python33/apicaller3.py", line 71, in <module>
    f = urllib.request.urlopen(request, payloadencode, 60)
  File "C:\Python33\lib\urllib\request.py", line 156, in urlopen
    return opener.open(url, data, timeout)
  File "C:\Python33\lib\urllib\request.py", line 475, in open
    response = meth(req, response)
  File "C:\Python33\lib\urllib\request.py", line 587, in http_response
    'http', request, response, code, msg, hdrs)
  File "C:\Python33\lib\urllib\request.py", line 513, in error
    return self._call_chain(*args)
  File "C:\Python33\lib\urllib\request.py", line 447, in _call_chain
    result = func(*args)
  File "C:\Python33\lib\urllib\request.py", line 595, in http_error_default
    raise HTTPError(req.full_url, code, msg, hdrs, fp)
urllib.error.HTTPError: HTTP Error 411: Length Required

Danial Klimkin

unread,
Jul 8, 2013, 4:46:43 PM7/8/13
to adwor...@googlegroups.com
This was resolved over email, the issue was the content encoding.


-Danial.
Reply all
Reply to author
Forward
0 new messages