Вопрос

Before Twitter switched to OAuth2, I was using the following query:

string atomTweetSearchURL = string.Format("http://search.twitter.com/search.atom?q={0}", searchText);

This no longer works, so now I'm trying to switch to OAuth2. I manage to successfully retrieve a token, but once I've got this, I seem to be unable to actually perform the search. Here's the latest incarnation of what I've tried:

var searchUrl = string.Format("https://api.twitter.com/1.1/search/tweets.json?q={0}&access_token={1}&token_type={2}", srchStr, twitAuthResponse.access_token, twitAuthResponse.token_type);

WebRequest srchRequest = WebRequest.Create(searchUrl);
using (var response2 = await srchRequest.GetResponseAsync())
{
    Stream stream = response2.GetResponseStream();
    using (StreamReader sr = new StreamReader(stream))
    {
        string jsonResponse = await sr.ReadToEndAsync();
    }
}

This gives me a 400 - bad request.

I've also tried building the request like this:

System.Net.Http.HttpClient srchRequest = new System.Net.Http.HttpClient();            
string authHdr = string.Format(srchHeaderFormat, twitAuthResponse.token_type, twitAuthResponse.access_token);
srchRequest.DefaultRequestHeaders.Add("Authorization", authHdr);

There's a massive quantity of articles out there detailing how to do this, but none of them seem to work correctly with WinRT. Can anyone point me in the right direction?

EDIT

Here's my code to get the token:

var oAuthConsumerKey = key;
var oAuthConsumerSecret = secret;
var oAuthUri = new Uri("https://api.twitter.com/oauth2/token");
var authHeaderFormat = "Basic {0}";
var authHeader = string.Format(authHeaderFormat,
     Convert.ToBase64String(Encoding.UTF8.GetBytes(Uri.EscapeDataString(oAuthConsumerKey) 
+ ":" +
Uri.EscapeDataString((oAuthConsumerSecret)))
));

var req = new HttpClient();
req.DefaultRequestHeaders.Add("Authorization", authHeader);

HttpRequestMessage msg = new HttpRequestMessage(new HttpMethod("POST"), oAuthUri);
msg.Content = new HttpStringContent("grant_type=client_credentials");
msg.Content.Headers.ContentType = new Windows.Web.Http.Headers.HttpMediaTypeHeaderValue("application/x-www-form-urlencoded");

HttpResponseMessage response = await req.SendRequestAsync(msg);

TwitAuthenticateResponse twitAuthResponse;
using (response)
{
     string objectText = await response.Content.ReadAsStringAsync();
     twitAuthResponse = JSonSerialiserHelper.Deserialize<TwitAuthenticateResponse>(objectText);
}
Это было полезно?

Решение

With the 1.1 API you don't pass the access token as part of the url, you need to include it as the Authorization header as "Bearer access_token" so you were almost there!

EDIT

To do this in the Windows.Web.Http namespace the following works:

private static async Task SearchTweets(AuthenticationResponse twitAuthResponse)
        {
            string srchStr = "tweet";

            var client = new HttpClient();

            var searchUrl = string.Format("https://api.twitter.com/1.1/search/tweets.json?q={0}", srchStr);

            var uri = new Uri(searchUrl);

            client.DefaultRequestHeaders.Authorization = new HttpCredentialsHeaderValue("Bearer", twitAuthResponse.AccessToken);



            var response2 = await client.GetAsync(uri);

            string content = await response2.Content.ReadAsStringAsync();
        }

Or with System.Net.Http use the following:

This code will run the search for srchStr using the access token you already acquired as you showed in the first example:

var client = new HttpClient(); 

var searchUrl = string.Format("https://api.twitter.com/1.1/search/tweets.json?q={0}", srchStr);

var uri = new Uri(searchUrl); 

client.DefaultRequestHeaders.Add("Authorization", string.Format("Bearer {0}", twitAuthResponse.access_token)); 



HttpResponseMessage response = await client.GetAsync(uri); 

Task<string> content = response.Content.ReadAsStringAsync();

EDIT

This is a strange one, I tested your code and you're right it does throw an exception when attempting to add the Auth header, however the code I had used for grabbing the Access Token is almost identical but uses the System.Net.Http methods rather than the Windows.Web.Http ones that you use and it works, so I'll provide my code here, maybe this is a bug in the framework, or someone else can provide some more insight! This also uses the JSON.NET library which can be found on NuGet.

private static async Task SearchTweets(AuthenticationResponse twitAuthResponse)
    {
        string srchStr = "tweet";

        var client = new HttpClient();

        var searchUrl = string.Format("https://api.twitter.com/1.1/search/tweets.json?q={0}", srchStr);

        var uri = new Uri(searchUrl);

        client.DefaultRequestHeaders.Add("Authorization", string.Format("Bearer {0}", twitAuthResponse.AccessToken));



        HttpResponseMessage response2 = await client.GetAsync(uri);

        string content = await response2.Content.ReadAsStringAsync();
    }

    private async void GetAuthenticationToken()
    {
        var client = new HttpClient();

        var uri = new Uri("https://api.twitter.com/oauth2/token");



        var encodedConsumerKey = WebUtility.UrlEncode(TwitterConsumerKey);

        var encodedConsumerSecret = WebUtility.UrlEncode(TwitterConsumerSecret);

        var combinedKeys = String.Format("{0}:{1}", encodedConsumerKey, encodedConsumerSecret);



        var utfBytes = System.Text.Encoding.UTF8.GetBytes(combinedKeys);

        var encodedString = Convert.ToBase64String(utfBytes);

        client.DefaultRequestHeaders.Add("Authorization", string.Format("Basic {0}", encodedString));



        var data = new List<KeyValuePair<string, string>> 
        { 
            new KeyValuePair<string, string>("grant_type", "client_credentials") 
        };

        var postData = new FormUrlEncodedContent(data);



        var response = await client.PostAsync(uri, postData);
        AuthenticationResponse authenticationResponse;
        using (response)
        {
            if (response.StatusCode != System.Net.HttpStatusCode.OK)

                throw new Exception("Did not work!");



            var content = await response.Content.ReadAsStringAsync();

            authenticationResponse = JsonConvert.DeserializeObject<AuthenticationResponse>(content);

            if (authenticationResponse.TokenType != "bearer")

                throw new Exception("wrong result type");
        }



        await SearchTweets(authenticationResponse);
    }
}

class AuthenticationResponse
{
    [JsonProperty("token_type")]
    public string TokenType { get; set; }

    [JsonProperty("access_token")]
    public string AccessToken { get; set; }

}
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top