そろそろ前に進まないとと思いつつ
ここしばらく、Google の提供する API を扱うためのことやってきたんですが、やりつつ一つの疑念がありました。
途中で Web にアクセスして URL を貼り付けるところ、そのまま HTTP の GET で良いのでは?
いちいちブラウザに貼り付けなくても良さそうな・・・?
というか、最初からブラウザで動かしたら?
それって、 Perl 入学式 でやった Mojolicious::Lite で実装できそう・・・と言うことで実装してみました。
下準備としては、Google Compute Platform の API 設定の OAuth 同意画面で、アプリケーションのホームページを http://localhost:3000
にしておくことです。
言わずと知れた Mojolicious を morbo で起動した時の URL とデフォルトポートですね。
出来上がったもの
苦労したところ
Google の認証画面に遷移するところまでは割とすんなり行きました。
問題はそっから ACCESS_TOKEN と REFRESH_TOKEN つくるところで詰まりました。
結局、 Net::Google::OAuth のソースを参考にしつつ作ることに・・・
おかげで、メールアドレスやリダイレクトのURLをURLエスケープするとか、HTTP::Tiny の POST つかって JSON で送るとかを読み取ることができました。
コード
Google Drive API での利用を想定して SCOPE のところがそうなってます。
http://localhost:3000
-> (POST) -> Google の認証画面 -> (GET) -> http://localhost:3000/code
という感じで遷移します。
URL の組み立てのところが雑だなぁ・・・と思うんですが、まぁそこはそれってことで。
#!/usr/bin/env perl use Mojolicious::Lite; use HTTP::Tiny; use JSON; use URI::Escape; use URI; my ( $CLIENT_ID, $CLIENT_SECRET, ); get '/' => sub { my $c = shift; $c->render( template => 'index' ); }; get '/code' => sub { my $c = shift; my $code = $c->param('code'); # Exchange code to token my $param = { 'client_id' => $CLIENT_ID, 'client_secret' => $CLIENT_SECRET, 'redirect_uri' => 'http://localhost:3000/code/', 'code' => $code, 'grant_type' => 'authorization_code', 'access_type' => 'offline', }; my $json = encode_json($param); my $ht = HTTP::Tiny->new(); my $response = $ht->request( 'POST', 'https://accounts.google.com/o/oauth2/token', { headers => { 'Content-Type' => 'application/json; charset=utf-8', }, content => $json, }, ); $json = decode_json( $response->{content} ); $c->stash( access_token => $json->{access_token}, refresh_token => $json->{refresh_token} ); $c->render( template => 'code' ); }; post '/post' => sub { my $c = shift; $CLIENT_ID = $c->param('CLIENT_ID'); $CLIENT_SECRET = $c->param('CLIENT_SECRET'); my $MAIL = $c->param('MAIL'); my $SCOPE = $c->param('SCOPE'); my $redirect_url = uri_escape('http://localhost:3000/code/'); my $login_hint = uri_escape($MAIL); my $scope = uri_escape($SCOPE); # url組み立て my $url = "https://accounts.google.com/o/oauth2/v2/auth?client_id=$CLIENT_ID&redirect_uri=$redirect_url&scope=$scope&response_type=code&approval_prompt=force&access_type=offline"; $c->redirect_to($url); }; app->start; __DATA__ @@ index.html.ep % layout 'default'; % title 'Welcome'; <h1>Welcome to the Mojolicious real-time web framework!</h1> <form action="/post" method="post"> <ul> <li>CLIENT_ID: <input name="CLIENT_ID" size=80 type="text" value=""></li> <li>CLIENT_SECRET: <input name="CLIENT_SECRET" size=80 type="text" value=""></li> <li>MAIL: <input name="MAIL" size=20 type="text" value=""></li> <li>SCOPE: <input name="SCOPE" size=40 type="text" value="https://www.googleapis.com/auth/drive"></li> </ul> <input type="submit" value="POSTで投稿する"> </form> @@ code.html.ep % layout 'default'; % title 'Welcome'; <h1>Welcome to the Mojolicious real-time web framework!</h1> <ul> <% if ( stash('access_token') ) {%> <li>ACCESS TOKEN:<%= $access_token %></li> <% } %></textbox> <% if ( stash('refresh_token') ) {%> <li>REFRESH TOKEN:<%= $refresh_token %></li> <% } %> </ul> <a href="http://localhost:3000">トップページ</a> @@ layouts/default.html.ep <!DOCTYPE html> <html> <head><title><%= title %></title></head> <body><%= content %></body> </html>