Archive

Posts Tagged ‘Rest’

Introduction to the dropbox api version 1.0

02/11/2011 2 comments

In this post i will explore some of the basic functionality of the new Dropbox Api, you can read more about here https://www.dropbox.com/developers/reference/api. As you can see in the description you talk to dropbox using rest, and OAuth as authentication method. I could of course buil my own OAuth helper instead i will use this OAuth base utility found at https://www.dropbox.com/developers/reference/api  not that i that think it written as clean “clean code”  I like it does the job, but i will give some trouble writting clean crisp method of some of the classes in this post. As a restclient  I will use the client from  http://restsharp.org/.
Some of the code in this post is also done very naive with no error handling so of course if you want to use the code one should deffently address this issue.

Before you start coding anything you first need to go to dropbox and create an app
https://www.dropbox.com/developers/apps

The app key and app secret should be replaced where necessary  through out this post.

The authentication process at dropbox consist of three steps

  1. Get a request token
  2. Authorize the request token from step 1
  3. Upgrade the access token from step 1 to an Access token. The Access token should nt be stored and can be used in all future interaction with dropbox.

First a Token from dropbox i delivered from a rest response in form given below

oauth_token_secret=b9q1n5il4lcc&oauth_token=mh7an9dkrg59

So i made this simple yet  NOT VERY CLEAN CODE CLASS

public class OAuthToken
    {
        public OAuthToken()
        {
        }

        public OAuthToken(string tokenString)
        {
            string[] urlParts = tokenString.Split('&');
            string[] secretParts = urlParts[0].Split('=');
            string[] tokenParts = urlParts[1].Split('=');
            TokenSecret = secretParts[1];
            Token = tokenParts[1];
        }

        public string TokenSecret { get; set; }
        public string Token { get; set; }
    }

Most of the other restquest a response with Json and the restsharp can deserialize them in datacontainers.

Now with token class in place we can create the firs rest call to supply us with at instance of a request token.

We first need some dropbox OAuth settings stored in this datacontainer

public class DropBoxSettings
    {
        public string ApplicationKey { get; set; }
        public string ApplicationSecret { get; set; }
        public string AccessTokenPath { get; set; }
    }

With this we can create a new OAuthrestClient

public class OAuthRestClient
    {
        private OAuthBase _oAuth;
        private RestClient _restClient;

        public OAuthRestClient(string restHost)
        {
            _oAuth = new OAuthBase();
            _restClient = new RestClient(restHost);
        }

        public string GetRequestToken(string resource)
        {
            RestRequest request = AddOAuthParameters(resource);
            RestResponse response = _restClient.Execute(request);
            return response.Content;
        }

        public string GetAccesToken(string resource,OAuthToken token)
        {
            RestRequest request = AddOAuthParameters(resource,token);
            RestResponse response = _restClient.Execute(request);
            return response.Content;
        }

        public T QueryServer<T>(string resource, OAuthToken token) where T : new()
        {
            RestRequest request = AddOAuthParameters(resource, token);
            RestResponse<T> restResponse = _restClient.Execute<T>(request);
            return restResponse.Data;
        }

        public byte[] GetStream(string resource, OAuthToken token)
        {
            RestRequest request = AddOAuthParameters(resource, token,false);
            RestResponse restResponse = _restClient.Execute(request);
            return restResponse.RawBytes;
        }

        private RestRequest AddOAuthParameters(string resource, OAuthToken token=null,bool encodeSignatur=true)
        {
            RestRequest request = new RestRequest(Method.GET);
            string nonce = _oAuth.GenerateNonce();
            string timeStamp = _oAuth.GenerateTimeStamp();
            request.Resource = resource;

            request.AddParameter("oauth_consumer_key", ConsumerKey);
            request.AddParameter("oauth_nonce", nonce);
            request.AddParameter("oauth_signature_method", "HMAC-SHA1");
            request.AddParameter("oauth_timestamp", timeStamp);
            if(token != null)
                request.AddParameter("oauth_token", token.Token);
            request.AddParameter("oauth_version", "1.0");
            request.AddParameter("oauth_signature", BuildSignatureWithToken(resource, nonce, timeStamp, token, encodeSignatur));
            return request;
        }

        private string BuildSignatureWithToken(string resource, string nonce, string timeStamp, OAuthToken token,bool encodeSignature)
        {
            string normalizedUrl;
            string normalizedRequestParameters;
            string sig;
            if(token == null)
             sig = _oAuth.GenerateSignature(new Uri(string.Format("{0}/{1}", _restClient.BaseUrl, resource)), ConsumerKey, ConsumerSecret, "", "", "GET", timeStamp, nonce, out normalizedUrl, out normalizedRequestParameters);
            else
             sig = _oAuth.GenerateSignature(new Uri(string.Format("{0}/{1}", _restClient.BaseUrl,resource)),ConsumerKey, ConsumerSecret,token.Token, token.TokenSecret,"GET", timeStamp, nonce, out normalizedUrl, out normalizedRequestParameters);

            if(encodeSignature)
                sig = HttpUtility.UrlEncode(sig);
            return sig;
        }

        public string Version { get; set; }
        public string ConsumerKey { get; set; }
        public string ConsumerSecret { get; set; }
    }

There are som input parameters that are bool which i due some restriction bugs in the OAuth base where a token not should be added in the requesttoken call. And the dropbox api where the signature shouldn’t be urlencode when querying api-content.dropbox.com. We can now use this to get a request token.

  public OAuthToken GetRequestToken()
        {
            OAuthRestClient apiRestClient = new OAuthRestClient("https://api.dropbox.com");
            apiRestClient.ConsumerKey = YOUR APP KEY;
            apiRestClient.ConsumerSecret = YOUR APP SECRET;
            apiRestClient.Version = "1.0";
            return new OAuthToken(_apiRestClient.GetRequestToken("1/oauth/request_token"));
        }

Now with request token we can prompt the user for access to his or hers dropbox account this can for now only be done in a browser

private void AuthorizeToken(OAuthToken token)
        {
            Process.Start("https://www.dropbox.com/1/oauth/authorize?oauth_token=" + token.Token);
        }

Now with application authorized we ca upgrade the requesttoken to an accestoken, and store it in a secure place for now we store it as a string in a plaintext file.

 private OAuthToken UpgradeRequsetTokenToAccesToken(OAuthToken requestToken)
        {
 OAuthRestClient apiRestClient = new OAuthRestClient("https://api.dropbox.com");
            apiRestClient.ConsumerKey = YOUR APP KEY;
            apiRestClient.ConsumerSecret = YOUR APP SECRET;
            apiRestClient.Version = "1.0";
            string tokenString = apiRestClient.GetAccesToken("1/oauth/access_token", requestToken);
            OAuthToken token = new OAuthToken(tokenString);
            StoreAccessToken(tokenString);
            return token;
        }

        private void StoreAccessToken(string tokenString)
        {
            FileStream fs = File.Open(_accessTokenPath, FileMode.OpenOrCreate, FileAccess.ReadWrite);
            StreamWriter sw = new StreamWriter(fs);
            sw.WriteLine(tokenString );
            sw.Close();
            fs.Close();

        }

        private OAuthToken GetAccesTokenFromStore()
        {
            OAuthToken token = null;
            string tokenString = TokenStringFromFile();
            if(!string.IsNullOrEmpty(tokenString))
             token = new OAuthToken(tokenString);

            return token;
        }

        private string TokenStringFromFile()
        {
            FileStream fs = File.Open(_accessTokenPath, FileMode.OpenOrCreate, FileAccess.ReadWrite);
            StreamReader sw = new StreamReader(fs);

            string tokenString =  sw.ReadToEnd();
            sw.Close();
            fs.Close();
            return tokenString;
        }

Now with an accestoken we can start talking to dropbox to the more fun stuff for example the userinformation

public class AccountInfo
    {
        public string Uid { get; set; }
        public string Display_Name { get; set; }
        public string Country { get; set; }
        public QuotaInfo Quota_Info { get; set; }
    }
 public class QuotaInfo
    {
        public string Shared { get; set; }
        public string Quota { get; set; }
        public string Normal { get; set; }
    }

or metadata for a a given path in the users dropbox

 public class FileEntry
    {
        public string Size { get; set; }
        public string Rev { get; set; }
        public string Thumb_Exists { get; set; }
        public string Bytes { get; set; }
        public string Modified { get; set; }
        public string Path { get; set; }
        public bool Is_Dir { get; set; }
        public string Icon { get; set; }
        public string Root { get; set; }
        public string Mime_Type { get; set; }

        public string Revision { get; set; }
        public List<FileEntry> Contents { get; set; }

        public string Name
        {
            get
            {

                if (String.IsNullOrEmpty(Path)) return String.Empty;
                if (Path == "/") return "dropbox";
                    return Path.Substring(Path.LastIndexOf("/") + 1);
            }
        }

        public string Parent
        {
            get
            {
                if (String.IsNullOrEmpty(Path)) return String.Empty;
                if (Path.LastIndexOf("/") == 0) return "dropbox";
                return Path.Substring(0,Path.LastIndexOf("/"));

            }
        }

    }
public AccountInfo AccountInfo()
        {
            OAuthRestClient apiRestClient = new OAuthRestClient("https://api.dropbox.com");
            apiRestClient.ConsumerKey = YOUR APP KEY;
            apiRestClient.ConsumerSecret = YOUR APP SECRET;
            apiRestClient.Version = "1.0";
            var response = apiRestClient.QueryServer<AccountInfo>("1/account/info", YOUR ACCES TOKEN);
            return response;
        }</pre>
&nbsp;
<pre>


Now we could can the byte[]  for a dropbox entry if it is not a folder, note when calling the api-content.dropbox.com the SIGNATURE PASSED TO DROPBOX SHOULD NOT BE URL -ENCRYPTED why i have no clue

public byte[] GetFile(string path)
        {
          OAuthRestClient apiRestClient = new OAuthRestClient("https://api-content.dropbox.com");
            apiRestClient.ConsumerKey = YOUR APP KEY;
            apiRestClient.ConsumerSecret = YOUR APP SECRET;
            apiRestClient.Version = "1.0";
            var response = apiRestclient.GetStream("1/files/dropbox/" + HttpUtility.UrlEncode(path), YOURRACCESTOKEN);
            return response;
        }

I’ve gathered all the functions in a simple Dropbox context.

So this wraps it up for now. in future post I will look into uploading files, but in the next post I will integrate this into the sitecore media library, for now only with download only and always overwrite. Coming soon so stay tuned.

Categories: .Net, C# Tags: , , ,