Ph: 27964390

Saturday, December 10, 2011

Getting the command line arguments in Dart (vm)

Another hidden gem in the Dart library today, can you tell I am trying to write a command line thingy? Reading the command line options is really easy.
void main() {
  Options opts = new Options();
  for (String arg in opts.arguments) {
    print(arg);
  }
}
Let us play:
$ dart opts.dart a
a
$ dart opts.dart a b c d
a
b
c
d
Nothing to add, I think, except check the source.

Comments on Google+.

Friday, December 09, 2011

OAuth2.0 with Dart in a web browser

I was trying to access a Google GData API using Dart in a browser. More for fun than profit, but it posed a few challenges, so I thought I should document them.

The first step was to Authorize using OAuth2.0 which is the easiest way of Authorizing an application to use Google APIs. This is pretty trivial using server-side Dart, but I wanted to achieve the entire thing inside a web browser, and so this involves a different OAuth2.0 flow to the web-server flow that I am used to using, in this case the OAuth2.0 Client-side Application Flow.

The main difference with the web-server flow is that the entire OAuth2.0 dance occurs in a single step, i.e., there is no step to exchange a code for a token. This single step is performed by asking for a token in the initial redirect step with a response_type parameter of token.

Additionally, the client secret is not passed at any time, because this would not be safe information for the client application to give up to a web browser (since anyone could just read it).

The response is also different in that the token is returned in the URI fragment of the redirect, rather than as a URI parameter as would be returned in a web-server flow, so that after authorization the browser is redirected back to something like:

http://localhost:7890/DartOAuthTest.html#access_token=AHES6ZS2-t1ntxFsGsvfKbEFosG6nokTOrn9qwVysp_&token_type=Bearer&expires_in=3600

So, this is what we are aiming at:


Step 1: Generate the Authorization URI

String authEndpoint = 'https://accounts.google.com/o/oauth2/auth?';

String generateAuthUri(String client_id, String redirect_uri, String scope) {    
  List<List<String>> params = [
        ['client_id', client_id],
        ['redirect_uri', redirect_uri],
        ['scope', scope],
        ['response_type', 'token'],
        ['approval_prompt', 'force']
    ];
    return authEndpoint + generateQueryString(params);
}

// Hopefully, this will one day be handled in a library

String generateQueryString(List<List<String>> params) {
  List<String> parts = new List<String>();
  for (List<String> part in params) {
    String k = encodeComponent(part[0]);
    String v = encodeComponent(part[1]);
    parts.add(Strings.join([k, v], '='));
  }
  return Strings.join(parts, '&');
}

// Taken from Uri.dart

String encodeComponent(String component) {
   if (component == null) return component;
   return component.replaceAll(':', '%3A')
                    .replaceAll('/', '%2F')
                    .replaceAll('?', '%3F')
                    .replaceAll('=', '%3D')
                    .replaceAll('&', '%26')
                    .replaceAll(' ', '%20');
}

Ok, so I'm sorry about that as it's mostly doing things that a decent URI library will handle, volunteers anyone? But we can see the parameters we will pass, and the important ones are the client_id, the scope, and the redirect_uri. The client_id and the redirect_uri should be configured in the Google API Console, and the scope is specific to whichever API(s) you will be using. In our case, we are using the Google Documents List API, with a scope of

https://docs.google.com/feeds/

Step 2: Open a popup window and redirect to the Authorization URI

We are now firmly in the realm of the DOM, and so once we have our redirect_uri, we open a window and send the client to it:
void redirectAuth(String uri) {
  window.open(uri, 'authwin', 'width=600,height=400');
}
Very simple, but the key will be how we handle the redirect back to us in the next stage.

Step 3: Receive the redirect and extract the OAuth2.0 Authorization token

Once we have been redirected back to our application, we should use window.location to extract the Authorization token. Remember that this is in the fragment, and once again we would hope that Dart eventually has libraries to handle this extraction, but in our case, I did something nasty like:
String extractToken() {
  // eww
  return window.location.hash.split('&')[0].split('=')[1];
}

Which probably won't work for 1000 edge cases, but you get the idea.

Once we have this token we need to somehow message it back to the parent window, which I was slightly puzzled how to do. I got some advice on Google+ and that was to use window.postMessage. It is a pretty nifty way of handling it, as the child window can access the parent as window.opener, and so the call simply becomes:
void sendTokenAndClose(String token) {
  window.opener.postMessage(token, '*');
   window.close();
}
Which needs to be caught by the parent window by registering an event handler for the message event:
window.on.message.add(tokenReceived, false);

void tokenReceived(MessageEvent e) {
  // the token is in e.data
}
We are now ready to use our token to make API calls, probably using JSONP which is the topic of another blog post, but you can see an idea on how to do it here in the Dart mailing list.

Thursday, December 08, 2011

Running a subprocess with Dart and reading its output

Starting a foreign program, and reading its standard output stream is useful, and here is an example of listing the root directory.
void main() {
  Process p = new Process('/bin/ls', ['/']);
  p.start();
  StringInputStream stdoutStream = new StringInputStream(p.stdout);
  print(stdoutStream.read());
  p.close();
}
Notes:

Argument list does not include the executable name like it usually does Use a StringInputStream to read an InputStream as a String Close the process or the script will hang forever
Comments on Google+.

Reading a file as a String in Dart

It took me a minute to work out how to read a file in Dart (vm), so here it is for posterity:

void main() {
  File f = new File('my_filename.txt');
  FileInputStream fileStream = f.openInputStream();
  StringInputStream stringStream = new StringInputStream(fileStream);
  print(stringStream.read());
  fileStream.close();
}

Notes:
A StringInputStream reads strings from an InputStream A FileInputStream is an implementor of InputStream that is opened from files Remember to close the FileInputStream
Comments on Google+

Thursday, November 24, 2011

Things I love about Dart (so far)

I've only been using Dart for a few hours in total, but already there are things to love about it. Forget the obvious "It's not JavaScript", because I don't hate JS, and if I did hate JS it would be because of the lack of decent structure (who decided prototypes were nice to use?). Certainly, I don't hate dynamically typed languages, and in fact, I quite like them, and have built my career on them. This article is about small things, I'll leave that huge stuff for the clever people.

1. I already know Dart without having learned a single thing:


Ever used Java or C#? Dart is essentially the same as those familiar languages that we learned at school. A class is defined like:

class Banana {
  String getColor() {
      return "yellow";
  }
}

See, this could be any language you already know, and to illustrate that nicely the syntax highlighter treats it as Java, and no one really cares.

2. Class members are public by default:


If you define an instance variable like this:

class Banana {
  int age;
}

then anyone using an instance of the Banana class is free to read and write to that variable. "OMG you just broke encapsulation!". No, I didn't, you are free to define private variables if you like by prefixing them with the _ (underscore) character (not sure how much I love that syntax, but still). Who in the Java world decided that exposing an attribute is a bad thing to do? It's just part of the external interface of a class, use it as such, and move on with life having escaped 1. writing setAge and getAge, and 2. feeling dirty about using public.

3. Initializing and defining instance variables:


class Banana {
  int age, length, width, ends = 2;
}

Look how I have defined the types of all those variables and actually initialized the value of one of them to 2 — a banana has two ends, usually. These can be assigned to something called "constant expressions", which I am a bit fuzzy about.

There is more; how annoying is the constructor pattern where you have a constructor that takes a number of variables, only to assign them to instance attributes: this.age = age or self.age = age etc.? It must account for something like 5% of all my code. Construct and assign, construct and assign. Dart does this nicely, look here:

class Banana {
  int age;

  Banana(this.age);
}

The above class will assign the passed age to the instance variable on construction.

4. Top-level attributes and multiple classes per file:


I love these in Dart, but mostly because I hate the lack of them in Java. C# somehow gets away with having namespaces, but Python does fine, and Dart follows the Python model. Want 27,000 classes in a single file? be my guest. Want to have some constants defined at the top level of a module instead of in a useless static class, also be my guest.

5. Factory constructors:


These are constructors that actually return new instances. Something like Python's __new__ although that is slightly painful to use in Python, and not something you would wish on someone you like. Dart does it properly with the use of the factory keyword to indicate that a constructor will return a new instance. It is still a constructor so when creating an instance, the new keyword is used; which differs from using a static method to achieve the same thing, as you would in Java, look how:

class Banana {
  Banana._internal();

  factory Banana() {
    return new Banana._internal();
  }
}

The _internal constructor here is a private named constructor which the Banana constructor calls. This is great for doing nasty things like caching instances transparently from the caller of the API.

6. It's not JavaScript:


Just kidding, you know I can't resist trolling! But anyway, try Dart, it's fun, refreshing, safe, and as I said, you already know it. Read more about idiomatic dart if you are interested in the advisable ways of doing things.

Comments on Google+


You are viewing a mobilized version of this site...
View original page here

Mobilized by Mowser Mowser