8 messages in com.googlegroups.bloggerdevRe: 411 Length Required
FromSent OnAttachments
Stephen Downes06 Apr 2007 12:04 
Pete Hopkins ☠06 Apr 2007 13:26 
Stephen Downes06 Apr 2007 14:53 
Pete Hopkins ☠06 Apr 2007 15:43 
Stephen Downes06 Apr 2007 17:43 
Stephen Downes08 Apr 2007 05:38 
Pete Hopkins ☠09 Apr 2007 15:13 
Stephen Downes10 Apr 2007 15:09 
Subject:Re: 411 Length Required
From:Stephen Downes (step@downes.ca)
Date:04/08/2007 05:38:52 AM
List:com.googlegroups.bloggerdev

Hiya,

I replied to this yesterday but it doesn't seem to have made it through (?).

I said something like: This will take me a few days, because I will have to install and learn Ethereal or Wireshark.

In the meantime, I'll post my code here, so anyone else who wants can have a shot at making it work.

### Code Starts

# Test of Google's Blogger API # by Stephen Downes # April 7, 2007 # Much borrowing from Simon Wistow > Net-Google-Calendar-0.6 # Released under the same license as Perl # Define the variables

use LWP::UserAgent;

my $username = 'step@downes.ca'; my $password = 'davidhume'; my $PostURI = 'http://www2.blogger.com/feeds/11679714/posts/default';

my $xml = qq|<?xml version="1.0" encoding="utf-8"?><entry xmlns='http://www.w3.org/2005/Atom'> <title type='text'>Marriage!</title> <content type='xhtml'> <div xmlns="http://www.w3.org/1999/xhtml"> <p>Mr. Darcy has <em>proposed marriage</em> to me!</p> <p>He is the last man on earth I would ever desire to marry.</p> <p>Whatever shall I do?</p> </div> </content> <author> <name>Stephen Downes</name> <email>$username</email> </author> </entry>|;

# First we authenticate

# Send the request

my $url = 'https://www.google.com/accounts/ClientLogin'; my $ua = LWP::UserAgent->new; $ua->timeout(10); $ua->env_proxy; my $response = $ua->post( $url, { Email => $username,Passwd => $password,service => 'blogger', source => 'Edu-RSS 0.2'});

# Extract the Authentication

my $auth = ""; if ($response->is_success) { my $resp = $response->content; if ($resp =~ /Auth=(.*?)\n/) { $auth = $1; } else { $auth = "failure"; } } else { $auth = "failure"; }

if ($auth eq "failure") { die "Authentication failure $response->errstring) "; }

my $authtoken = qq|AuthSub token="$auth"|;

# Set up request parameters

my $bua = LWP::UserAgent->new;

while (1) { # use while for redirects

my %params = {Authorization => $auth};

my $reqlength = length $xml; my $ct = 'Content-Type'; my $cl = 'Content-length';

$bua->default_header($ct => 'application/atom+xml'); $bua->default_header(Authorization => $authtoken); $bua->default_header(Content => $xml); $bua->default_header($cl => $reqlength); $bua->default_header(chunked => "false");

my $r = HTTP::Request->new( "POST", $PostURI );

# Yes there is some redundancy here - I haven't figured out which way is # best -- tried any number of combinations

$params{'Content-Type'} = 'application/atom+xml; charset=UTF-8'; $params{'Content-length'} = length $xml; $params{Content} = $xml;

# make the actual request

my $rq = $r, %params; $rq->header($cl => length $xml); my $resp = $bua->request( $rq );

# catch redirects if (302 == $resp->code) {

$PostURI = $resp->header('location'); next; }

if (!$resp->is_success) { print "Request Failed<br> ".$resp->status_line." - ".$resp-

content;

exit; }

my $c = $resp->content; if (defined $c && length($c)) { print "Yay!!".$c; exit; } else { print "???"; exit; } }

### Code Ends

On Apr 6, 7:43 pm, "Pete Hopkins ☠" <phop@google.com> wrote:

On 4/6/07, Stephen Downes <step@downes.ca> wrote:

The URL ishttp://www2.blogger.com/feeds/11679714/posts/default

Had lots of fun with the authentication and the redirect from http://www.blogger.com/feeds/11679714/posts/default

The authentication is in the header and not in the xml.

I am setting the headers with:

my $ct = 'Content-Type'; my $cl = 'Content-Length'; $bua->default_header($ct => 'application/atom+xml'); $bua->default_header(Authorization => $authtoken); $bua->default_header(Content => $xml); $bua->default_header($cl => length $xml);

The headers should be coming out like this (I am confident that they are, since I am authenticating OK, but if you know of a URL I can try to get the exact headers I am sending, that would be appreciated):

Hrm... nothing fishy there.

Can you look at what's actually going over the wire, using Ethereal or another TCP sniffing app?

It looks like we never got to the bottom of this the last time it came up, and I was never able to reproduce it. The Content-Length requirement comes from some infrastructure that sits in front of Blogger, so I don't have much control/insight into it.

Also, AFAIK we're not returning the 411 because of some other error, though I can't be 100% sure.

Do things work if you don't set the Content-Length header on your own? Some HTTP libraries will include it for you.

For reference, here are the headers that my test curl client sends. All but "Authorization" and "Content-type" are of curl's own accord.

POST /feeds/xxxxxx/posts/default HTTP/1.1 User-Agent: curl/7.13.1 (powerpc-apple-darwin8.0) libcurl/7.13.1 OpenSSL/0.9.7l zlib/1.2.3 Host: www2.blogger.com Pragma: no-cache Accept: */* Content-type: application/atom+xml Authorization: GoogleLogin auth=xxx Content-Length: 180

<?xml version='1.0' encoding='UTF-8'?><entry xmlns='http://www.w3.org/2005/Atom'><title type='text'>Test post</title><content type='html'>This is a test post!</content></entry>

-- Pete

POST /feeds/11679714/posts/default Host: www2.blogger.com Content-Type: application/atom+xml; charset=utf-8 Content-Length: 483 Authentication: AuthSub token="XXXXXXXXX"

<?xml version="1.0" encoding="utf-8"?> <entry xmlns='http://www.w3.org/2005/Atom'> <title type='text'>Marriage!</title> <content type='xhtml'> <div xmlns="http://www.w3.org/1999/xhtml"> <p>Mr. Darcy has <em>proposed marriage</em> to me!</p> <p>He is the last man on earth I would ever desire to marry.</p> <p>Whatever shall I do?</p> </div> </content> <author> <name>Stephen Downes</name> <email>$username</email> </author> </entry>

On Apr 6, 5:27 pm, "Pete Hopkins ☠" <phop@google.com> wrote:

Can you send the contents of the XML that you're POSTing to Blogger, along with the URL you're using? (Though please x out the auth token itself, for privacy)

-- Pete

On 4/6/07,StephenDownes<step@downes.ca> wrote:

I've seen this come up in other discussions, with no solution ever posted.

Like the others, I am receiving the '411 Length Required' error despite a Content-Length being properly placed in the headers.

I am attempting to create Blogger entries using a Perl script (Google's recent changes have rendered Net::Blogger and XML::Atom obsolete, and I haven't found anything else that works).

Anyhow - if anybody can solve the 411 problem for me (or can point to a working Perl client that works with Blogger) please let me know.