Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

initial get.go commit

  • Loading branch information...
commit c100ff3e0e5547ed170a029cee1503475d12f477 1 parent 5c1df6c
Matt Armstrong authored
Showing with 167 additions and 0 deletions.
  1. +7 −0 Makefile
  2. +160 −0 get.go
7 Makefile
View
@@ -0,0 +1,7 @@
+include $(GOROOT)/src/Make.inc
+
+TARG=get
+GOFILES=\
+ get.go
+
+include $(GOROOT)/src/Make.cmd
160 get.go
View
@@ -0,0 +1,160 @@
+package main
+
+import (
+ "bufio"
+ "fmt"
+ "http"
+ "io/ioutil"
+ "json"
+ "os"
+ "strings"
+)
+
+// Go here to create client ids and secrets.
+//
+// http://code.google.com/apis/console
+const (
+ clientId = "3469431633.apps.googleusercontent.com"
+ clientSecret = "qeZvS6rsxIivC7gQn_JHuirn"
+ // Look into http://sites.google.com/site/oauthgoog/Home/emaildisplayscope
+ // to get the email address used.
+ //
+ // There is also a goog bug to allow the account to be forced
+ // in the auth request.
+ scope = "https://www.google.com/m8/feeds"
+)
+
+// TraceTransport is an http.RoundTripper that prints the request and
+// response to stdout while delegating the real work to another
+// http.RoundTripper.
+type TraceTransport struct {
+ delegate http.RoundTripper
+}
+
+// Print a dump of the request and response while delegating the round
+// trip to the delegate.
+func (t *TraceTransport) RoundTrip(req *http.Request) (resp *http.Response, err os.Error) {
+ dump, dump_err := http.DumpRequest(req, true)
+ if dump_err == nil {
+ fmt.Println(string(dump))
+ }
+ resp, err = t.delegate.RoundTrip(req)
+ if err == nil {
+ dump, dump_err = http.DumpResponse(resp, true)
+ if dump_err == nil {
+ fmt.Println(string(dump))
+ }
+ }
+ return resp, err
+}
+
+// Inject a TraceTransport into http.DefaultTransport
+func injectTraceTransport() {
+ http.DefaultTransport = &TraceTransport{http.DefaultTransport}
+}
+
+// draft-ietf-oauth-v2-15 4.1.4 Access Token Response
+type tokenResponse struct {
+ Access_token string
+ Token_type string
+ Expires_in int
+ Refresh_token string
+ Error string
+}
+
+type badStringError struct {
+ what string
+ str string
+}
+
+func (e *badStringError) String() string { return fmt.Sprintf("%s %q", e.what, e.str) }
+
+func tokenPost(authCode string) (resp tokenResponse, err os.Error) {
+ queryArgs := map[string][]string{
+ "grant_type": {"authorization_code"},
+ "code": {authCode},
+ "redirect_uri": {"urn:ietf:wg:oauth:2.0:oob"},
+ "client_id": {clientId},
+ "client_secret": {clientSecret},
+ }
+
+ body := strings.NewReader(http.EncodeQuery(queryArgs))
+
+ var r *http.Response
+ if r, err = http.Post(
+ "https://accounts.google.com/o/oauth2/token",
+ "application/x-www-form-urlencoded",
+ body); err != nil {
+ return
+ }
+ defer r.Body.Close()
+
+ ct := r.Header["Content-Type"][0]
+ if strings.Split(ct, ";", 2)[0] != "application/json" {
+ err = &badStringError{"unknown Content-Type", ct}
+ return
+ }
+
+ var data []byte
+ if data, err = ioutil.ReadAll(r.Body); err != nil {
+ return
+ }
+
+ if err = json.Unmarshal(data, &resp); err != nil {
+ return
+ }
+
+ if resp.Error != "" {
+ err = os.NewError(resp.Error)
+ return
+ }
+
+ if r.StatusCode != 200 {
+ err = os.NewError(fmt.Sprint("HTTP error on token request: ", r.Status))
+ return
+ }
+
+ return
+}
+
+func die(err os.Error) {
+ fmt.Println("Error:", err)
+ os.Exit(1)
+}
+
+func main() {
+ injectTraceTransport()
+
+ // TODO: investigate claim: You can use the user_id=<email
+ // address> query parameter to specify a
+ // user. https://groups.google.com/d/topic/oauth2-dev/ZU9rtEC8mcU/discussion
+ query_args := map[string][]string{
+ "client_id": {clientId},
+ "response_type": {"code"},
+ "redirect_uri": {"urn:ietf:wg:oauth:2.0:oob"},
+ "scope": {scope}}
+ query := http.EncodeQuery(query_args)
+ authBase := "https://accounts.google.com/o/oauth2/auth"
+
+ fmt.Println("You must authenticate this script to a google account")
+ fmt.Println("by visiting this URL:")
+ fmt.Printf("%s?%s", authBase, query)
+ fmt.Println("")
+ fmt.Print("Once you have an authorization code, enter it here\n: ")
+
+ reader := bufio.NewReader(os.Stdin)
+ bytes, _, err := reader.ReadLine()
+ if err != nil {
+ die(err)
+ }
+
+ code := strings.TrimSpace(string(bytes))
+ fmt.Printf("You entered code \"%s\"\n", code)
+
+ var token tokenResponse
+ if token, err = tokenPost(code); err != nil {
+ die(err)
+ }
+
+ fmt.Println(token)
+}
Please sign in to comment.
Something went wrong with that request. Please try again.