1

My asana oauth redirect URL is something like

https://testapp.appspot.com/api/redirect.asana#access_token=123456789

I am not sure how to fetch access_token now.

Note : if I am changing ? to # then its working fine by using r.FormValue("access_token").

Nikhil Maheshwari
  • 2,198
  • 18
  • 25

1 Answers1

1

The reason why r.FormValue() does not get it is because URL parameters are separated by ? but in your URL it is not.

The # is used to separate a fragment for references, so your access_token should be in r.URL.Fragment... but it won't.

You can't test it from the browser

Fragments are not sent over to the server, fragments are for the browsers. There was an issue covering this:

net/http: document fields set in Request.URL in handler #3805

It is also included in the doc of http.Request:

For server requests the URL is parsed from the URI supplied on the Request-Line as stored in RequestURI. For most requests, fields other than Path and RawQuery will be empty. (See RFC 2616, Section 5.1.2)

Code to get it from the request

If a non-browser client does send it as part of the request path, you can use simple string operations to get the token value: it is the part after the = character. You can use strings.Index() to find the "=":

raw := r.URL.Path
if idx := strings.Index(raw, "="); idx >= 0 && idx < len(raw)-1 {
    token := raw[idx+1:]
    fmt.Fprintln(w, "Token:", token)
}

Output:

Token: 123456789

As an alternative solution you can also use strings.Split() to split it by "=", 2nd element will be the value of the token:

parts := strings.Split(r.URL.Path, "=")
fmt.Fprintln(w, "Parts:", parts)
if len(parts) == 2 {
    fmt.Fprintln(w, "Token:", parts[1])
}

Output:

[/api/redirect.asana#access_token 123456789]
Token: 123456789

Code to test it

Here is a code using net/http to call your server that will send a path being "/api/redirect.asana#access_token=123456789", and it will print the response body to the standard output (console):

c := &http.Client{}
req, err := http.NewRequest("GET", "http://localhost:8080/", nil)
if err != nil {
    panic(err)
}
req.URL.Path = "/api/redirect.asana#access_token=123456789"
resp, err := c.Do(req)
if err != nil {
    panic(err)
}
defer resp.Body.Close()
io.Copy(os.Stdout, resp.Body)
icza
  • 389,944
  • 63
  • 907
  • 827
  • But raw := r.URL.String() is fetching only api/redirect.asana, I need complete url to be fetched for this code to work. – Nikhil Maheshwari Feb 23 '16 at 15:58
  • Your code is working only when I am changing # to ?. I think we are back to zero. In case of ? even r.FormValue("access_token") is sufficient. – Nikhil Maheshwari Feb 23 '16 at 16:04
  • Even r.URL.Fragment is blank so rest code will not work. – Nikhil Maheshwari Feb 23 '16 at 16:19
  • @NikhilMaheshwari Fragments are not sent over to the server. See edited answer. I also cleaned up my comments. – icza Feb 23 '16 at 16:49
  • I was doing it manually, just to test how my handler will behave if its a ? instead of #, no way to change otherwise. As long as I can't get URL parameters, I can not do it. Thanks for the informative link in the answer but I don't have control over the URL as it's a redirect URL from ASANA. – Nikhil Maheshwari Feb 23 '16 at 16:49
  • In that case, my very first answer stands. You can't test it from your browser, because the browser won't send the fragment. If it is coming from another server, you will most likely have it. Please test it in prod environment. – icza Feb 23 '16 at 16:51
  • I can only change the redirect URL in my app in ASANA but ASANA is sending the access token by appending #access_token=.... to it. – Nikhil Maheshwari Feb 23 '16 at 16:56
  • @NikhilMaheshwari I reworked the answer. I included my original parsing code, also included code that you can use to test it (since you can't test it from browsers). – icza Feb 23 '16 at 17:48