file_get_contents and stream_context returns 400 bad request


#1

I have been working on some code which uses the following PHP:

$response = file_get_contents($url, false, stream_context_create($stream));

Which uses a stream context to send the applicable data to twitter. This was working fine a few months back, but I’ve come back to it now and I get the following error:

Warning: file_get_contents(https://api.twitter.com/1.1/statuses/user_timeline.json?count=200&exclude_replies=1): failed to open stream: HTTP request failed! HTTP/1.0 400 Bad Request
in D:\websites\version1\htdocs\apis\twitter\provider.php on line 464

Where 464 is the $response line. Has twitter stopped accepting streams_contexts for the standard GET functionality in the rest API? I can POST out to twitter with the same code absolutely fine, but try to GET and it fails with the error.


#2

streams_contexts are a PHP concept, there’s nothing specific in the Twitter API which accepts them or not. You’re talking to the Twitter REST API rather than the Streaming / realtime API here so there’s really nothing specific on the Twitter side which should affect what you’re trying to do.

Usually a 400 Bad Request means there’s an authentication issue, and there could be an additional error code that you are not printing out from the response body which explains in more detail. You’re saying you can POST successfully so I’m guessing your auth is fine.

I’d suggest trying to use curl or twurl against https://api.twitter.com/1.1/statuses/user_timeline.json?count=200&exclude_replies=1 with your credentials, checking the response, and seeing whether there’s anything different than what your code was seeing previously.


#3

I am still having problems with this - I’ve setup a test code which although it no longer gets the 400 error, it still doesn’t return anything at all. All you need to do to test it is amend the first 5 lines:

define('CONSUMER_KEY', '');
define('CONSUMER_SECRET', '');
define('OAUTH_TOKEN','');
define('OAUTH_SECRET','');
define('USER_ID','');

function generateSignature($oauth,$fullurl,$http_method){        

// Take params from url
$main_url = explode('?',$fullurl);        

$urls = explode('&',$main_url[1]);

foreach ($urls as $param){
$bits = explode('=',$param);
if (strlen($bits[0])){
$oauth[$bits[0]] = rawurlencode($bits[1]);
}    
}

ksort($oauth);

$string = http_build_query($oauth);

$new_string = strtoupper($http_method).'&'.urlencode($main_url[0]).'&'.urlencode(urldecode($string));           

$sign_str = CONSUMER_SECRET.'&'.OAUTH_SECRET;

return urlencode(base64_encode(hash_hmac('sha1',$new_string,$sign_str,true)));        
} 

function random($len,$use_chars = false,$numU = false){
$num = range(0,9);
$letu = range('A','Z');
$letl = range('a','z');
$chars = array("!","*","£","$","^","(",")","_","+");

if ($use_chars){
$arr = array_merge($num,$letu,$letl,$chars);
} else {
$arr = array_merge($num,$letu,$letl);
}

// Shuffling - new addition 11/9 to make order actually random!
shuffle($arr);

// Create a number only random string
if ($numU){ $arr = $num; }

$rand = array_rand($arr,$len);
foreach ($rand as $num){
$out[] = $arr[$num];
}

return implode('',$out);
}

$method = 'GET';

// Twitter still uses Oauth1 (which is a pain)
$oauth = array(
'oauth_consumer_key'=>CONSUMER_KEY,
'oauth_nonce'=>random(32),
'oauth_signature_method'=>'HMAC-SHA1',
'oauth_timestamp'=>time(),
'oauth_token'=>OAUTH_TOKEN,
'oauth_version'=>'1.0',
);                    

$url = "https://api.twitter.com/1.1/statuses/user_timeline.json?user_id=".USER_ID;

$oauth['oauth_signature'] = generateSignature($oauth,$url,$method,'');                                

ksort($oauth);

foreach ($oauth as $k=>$v){
$auths[] = $k.'="'.$v.'"';
}

$stream = array('http' =>
array(
'method' => $method,
// ignore_errors should be true
'ignore_errors'=>true, // http://php.net/manual/en/context.http.php - otherwise browser returns error not error content
'follow_location'=>false,
'max_redirects'=>0,
'header'=> array(
'Authorization: OAuth '.implode(', ',$auths),
'Connection: close'
)                                             
)
);                                                                                                                 

echo $url;                                                 
$response = file_get_contents($url, false, stream_context_create($stream));

print'<pre>';print_r($stream);print'</pre>';
print'<pre>[';print_r($reponse);print']</pre>';