Skip to content

Commit

Permalink
Fixed URI encoding issue (Twitter API v1.1 is more stringent)
Browse files Browse the repository at this point in the history
Bug reporteb by Nick Andrew (@elronxenu) 2013-02-27 via Twitter.

We used to rely on HTTP::Requet::Common to encode arguments, but it
relies on URI which doesn't encode the full set of values required by
the OAuth spec.

We now use Net::OAuth::Message to encode paramters.
  • Loading branch information
semifor committed Feb 27, 2013
1 parent 8cecfc7 commit d9d9f30
Show file tree
Hide file tree
Showing 3 changed files with 62 additions and 2 deletions.
2 changes: 2 additions & 0 deletions Changes
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
- Fixed URI argument encoding (v1.1 is more stringent)

4.00002 2013-02-23
- Removed Test::NoWarnings to accommodate HTTP::Request::Common 6.03
- Added method twitter_error_code to Net::Twitter::Error
Expand Down
19 changes: 17 additions & 2 deletions lib/Net/Twitter/Core.pm
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ use Encode qw/encode_utf8/;
use DateTime;
use Data::Visitor::Callback;
use Try::Tiny;
use Net::OAuth::Message;


use namespace::autoclean;

Expand Down Expand Up @@ -155,7 +157,7 @@ sub _prepare_request {
$self->_encode_args(\%natural_args);

if ( $http_method =~ /^(?:GET|DELETE)$/ ) {
$uri->query_form(%natural_args);
$uri->query($self->_query_string_for(\%natural_args));
$msg = HTTP::Request->new($http_method, $uri);
}
elsif ( $http_method eq 'POST' ) {
Expand All @@ -165,7 +167,7 @@ sub _prepare_request {
Content_Type => 'form-data',
Content => \%natural_args,
)
: POST($uri, \%natural_args)
: POST($uri, Content => $self->_query_string_for(\%natural_args))
;
}
else {
Expand All @@ -177,6 +179,19 @@ sub _prepare_request {
return $msg;
}

# Make sure we encode arguments *exactly* the same way Net::OAuth does
# ...by letting Net::OAuth encode them.
sub _query_string_for {
my ( $self, $args ) = @_;

my @pairs;
while ( my ($k, $v) = each %$args ) {
push @pairs, join '=', map Net::OAuth::Message::encode($_), $k, $v;
}

return join '&', @pairs;
}

# Basic Auth, overridden by Role::OAuth, if included
sub _add_authorization_header {
my ( $self, $msg ) = @_;
Expand Down
43 changes: 43 additions & 0 deletions t/stringent-encoding.t
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
#!perl
use warnings;
use strict;
use URI;
use Net::Twitter;
use Net::OAuth::Message;
use Test::More;

plan tests => 2;

# Ensure post args are encoded per the OAuth spec
#
# We assume Net::OAuth does the right thing, here.
#
# Bug reported by Nick Andrew (@elronxenu) 2013-02-27

my $nt = Net::Twitter->new(
traits => [qw/API::RESTv1_1/],
consumer_key => 'mykey',
consumer_secret => 'mysecret',
access_token => 'mytoken',
access_token_secret => 'mytokensecret',
);

my $req;
$nt->ua->add_handler(request_send => sub {
$req = shift;
my $res = HTTP::Response->new(200, 'OK');
$res->content('{}');

return $res;
});

my $text = q[Bob's your !@##$%^&*(){}} uncle!];
$nt->new_direct_message({ screen_name => 'perl_api', text => $text });

my $encoded_text = Net::OAuth::Message::encode($text);
like $req->content, qr/\E$encoded_text/, 'properly encoded';

my $uri = URI->new($req->uri);
$uri->query($req->content);
my %params = $uri->query_form;
is $params{text}, $text, 'decoded text matches';

0 comments on commit d9d9f30

Please sign in to comment.