The Community is hosting an End of Summer sweepstakes! Participants must complete tasks to earn tickets that will enter them with a chance to win a free year of Constant Contact and other great prizes!*
*No Purchase Necessary. For Official Rules, visit here. Constant Contact’s End of Summer 2020 Sweepstakes ends on October, 20, 2020 at 11:50 PM EST.

400 error about missing colon in HTTP headers since API authentication change

Highlighted
Occasional Participant

400 error about missing colon in HTTP headers since API authentication change

We switched our code to basic auth as soon as we received a notification that digest auth was being discontinued. Unfortunately, since no method for testing the correctness of the new system was made available, we weren't able to confirm that it was correct. When the switch occurred on Friday, our ability to programmatically add new subscribers ceased working.


Attempts to use it now return the following:


<html><head>

<title>400 Bad Request</title>

</head><body>

<h1>Bad Request</h1>

<p>Your browser sent a request that this server could not understand.<br />

Request header field is missing ':' separator.<br />

<pre>

ZQ==</pre>

</p>

<hr />

<address>IBM_HTTP_Server Server at p2-ws575 Port 80</address>

</body></html>



This is a very strange error to be getting, as it implies a malformed HTTP request rather than a problem with the authentication mechanism. But the

HTTP request being made is exactly the same one that was working on Thursday. This makes me think that there is a problem with the API server.



The following is the python code that I am using to POST to the API:



xml = """<entry xmlns="http://www.w3.org/2005/Atom">

<title type="text"> </title>

<updated>2008-07-23T14:21:06.407Z</updated>

<author></author>

<id>data:,none</id>

<summary type="text">Contact</summary>

<content type="application/vnd.ctct+xml">

<Contact xmlns="http://ws.constantcontact.com/ns/1.0/">

<EmailAddress>%s</EmailAddress>

<OptInSource>ACTION_BY_CONTACT</OptInSource>

<ContactLists>

<ContactList id="

http://api.constantcontact.com/ws/customers/MYACCOUNT/lists/2" />

</ContactLists>

</Contact>

</content>

</entry>""" % recipient.email

user = '%s%%%s' % (CONSTANTCONTACT_API_KEY, CONSTANTCONTACT_LOGIN)

http = httplib2.Http()

http.add_credentials(user, CONSTANTCONTACT_PASSWORD)

response, content = http.request('

https://api.constantcontact.com/ws/customers/MYACCOUNT/contacts', 'POST',

body=xml, headers={'content-type': 'application/atom+xml'})



This code is known to have worked under your previous server configuration (it has been running in production ever since the switch to basic auth was announced).  To my knowledge there's no sample python code to compare it to, but it's a pretty simple use of httplib2.  I'm at a loss as to what the problem could be.

4 REPLIES 4
Highlighted
Moderator

HTTPS requests must be made

HTTPS requests must be made over port 443.  Since it appears you are trying to connect to port 80, you may need to configure your http_request to send over port 443.  I would recommend looking at the http_request documentation for the port changing options.

Dave Berard
Senior Product Manager, Constant Contact
Highlighted
Occasional Participant

I *am* using 443

Note the https in the URL.  I've also tried explicitly setting the port in the URL (":443").  The error is the same.  I can only assume that the service is redirecting to a port 80 service after successful authentication.


This looks to me very much like this bug:


http://code.google.com/p/httplib2/issues/detail?id=17


However, upgrading my copy of httplib2 has not resolved the issue.  And I'm not able to replicate the issue with curl to look for redirects (auth seems to invariably fail -- is there a restriction on user agents?).


I'll try reimplementing with urllib2, but this still looks like a server-side problem to me.

Highlighted
Occasional Participant

urllib2 attempt results in consistent 401

Here's another python attempt, this time using the relatively archaic urllib2 (on the off chance that that httplib2 patch from 2008 wasn't committed).  I've taken this pretty much verbatim from http://www.voidspace.org.uk/python/articles/authentication.shtml , but it's consistently returning a 401.


A working python example would be really useful.  I feel confident that one of the snippets I've posted can fill this void, but I think I still need a little help from you guys.


 


    xml = """<entry xmlns="http://www.w3.org/2005/Atom">

      <title type="text"> </title>

      <updated>2008-07-23T14:21:06.407Z</updated>

      <author></author>

      <id>data:,none</id>

      <summary type="text">Contact</summary>

      <content type="application/vnd.ctct+xml">

        <Contact xmlns="http://ws.constantcontact.com/ns/1.0/">

          <EmailAddress>%s</EmailAddress>

          <OptInSource>ACTION_BY_CONTACT</OptInSource>

          <ContactLists>

            <ContactList id="http://api.constantcontact.com/ws/customers/MY_ACCOUNT/lists/2" />

          </ContactLists>

        </Contact>

      </content>

    </entry>""" % recipient.email

   

    user = '%s%%%s' % (CONSTANTCONTACT_API_KEY, CONSTANTCONTACT_LOGIN)

   

    import urllib2

    url = "https://api.constantcontact.com/ws/customers/MY_ACCOUNT/contacts"

   

    passman = urllib2.HTTPPasswordMgrWithDefaultRealm()

    passman.add_password(None, url, user, CONSTANTCONTACT_PASSWORD)

    auth = urllib2.HTTPBasicAuthHandler(passman)

    opener = urllib2.build_opener(auth)

    urllib2.install_opener(opener)



    req = urllib2.Request(url)

    req.add_header('Content-Type', 'application/atom+xml')

    resp = urllib2.urlopen(req, data=xml)

Highlighted
Occasional Visitor

Re: urllib2 attempt results in consistent 401

Developer Portal

View API documentation, code samples, get your API key.

Visit Page

Constant Contact 2020 End of Summer Community Sweepstakes!

The Constant Contact User Community is hosting a sweepstakes. The more you participate, the more chances you have to win! Read on to learn more...

Read More
Featured