Top Banner
Data API 勉強会 Vol.1 2014.6.11 @ Co-Edo YUJI Takayama@Six Apart
56
Welcome message from author
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
Page 1: Data api workshop at Co-Edo

Data API 勉強会 Vol.12014.6.11 @ Co-Edo

YUJI Takayama@Six Apart

Page 2: Data api workshop at Co-Edo

About Me• 名前: 高山 裕司

• 会社: シックス・アパート

• 仕事: Movable Type 全般

• プロダクト・マネージャ

• リード・エンジニア

github.com/yuji

@yuji

Yuji Takayama

Page 3: Data api workshop at Co-Edo

Agenda• Data APIってなに?

• 初めての Data API

• JavaScript ライブラリ

• サインイン ~ 記事の投稿

• こんな使い方も・・・

Page 4: Data api workshop at Co-Edo

Data APIって何?

Page 5: Data api workshop at Co-Edo

• Movable Type 6 から搭載

• Movable Type に保存されているデータを操る

• REST API

• MT のユーザー管理、認証機構を利用

Page 6: Data api workshop at Co-Edo

• JavaScript のライブラリを提供

• プラグインで API 自体を拡張可能

• 公開サイトでも、管理サイトでも、別のアプリケーションとでも

• まだまだ発展途上

Page 7: Data api workshop at Co-Edo

なぜ、Data API を リリースしたのか

Page 8: Data api workshop at Co-Edo

• 様々なデバイスの登場

• ダイナミック・コンテンツ

• MT ≠ Perl

• ユーザーの役割に応じた画面作り

• “管理画面” は、管理する人が使う

• コンテンツの作成は、”管理画面”である必要はない

Page 9: Data api workshop at Co-Edo

初めての Data API

Page 10: Data api workshop at Co-Edo

Data API で出来ることCreate Read Update Delete

Entry ○ ○ ○ ○Comment ○ ○ ○ ○Trackback ○ ○ ○

User ○ ○Site(Blog, Website) ○

Category ○Site Statistics ○

Asset ○

Page 11: Data api workshop at Co-Edo

Data API の使い方

http://localhost/mt/mt-data-api.cgi/v1/sites/1

エンドポイント と呼ばれる URL を呼び出す

Data API のスクリプトへのパス

Data API のバージョン

呼び出すメソッドとパラメータ

Page 12: Data api workshop at Co-Edo

https://github.com/movabletype/Documentation/wiki/Quick-reference

Page 13: Data api workshop at Co-Edo

呼び出し方で処理が変わるPOST GET PUT DELETE

Entry ○ ○ ○ ○Comment ○ ○ ○ ○Trackback ○ ○ ○

User ○ ○Site(Blog, Website) ○

Category ○Site Statistics ○

Asset ○

同じエンドポイントへのリクエストで変わる

Page 14: Data api workshop at Co-Edo

結果は JSON 形式

{! "url" : "http://localhost/blog/20140609-1/",! "archiveUrl" : "http://localhost/blog/20140609-1/",! "name" : "First Website",! "class" : "website",! "id" : "1",! "description" : null!}

Page 15: Data api workshop at Co-Edo

https://github.com/movabletype/Documentation/wiki/Quick-reference

Page 16: Data api workshop at Co-Edo

• HTTP(s) を呼び出せれば呼び出し元はブラウザだろうが、アプリだろうが、コンソールだろうが、何でもいい

• 戻りは JSON 形式なので、JSON パーサがある方がラクと言えばラク

Page 17: Data api workshop at Co-Edo

サインイン から 記事のポストまで

実践

Page 18: Data api workshop at Co-Edo

ユーザー認証curl -i -d clientId=test -d username=takayama -d password=passwordhttp://localhost/cgi-bin/mt/mt-data-api.cgi/v1/authentication -X POST

リクエスト

応答HTTP/1.1 200 OKDate: Mon, 09 Jun 2014 07:01:38 GMTServer: Apache/2.2.26 (Unix) mod_ssl/2.2.26 OpenSSL/1.0.1e DAV/2 PHP/5.3.27X-content-type: nosniffCache-control: no-cacheTransfer-Encoding: chunkedContent-Type: application/json; charset=UTF-8X-Pad: avoid browser bug!{"sessionId":"vjqLFlFxEki5ElAHy9DyUe6k3jAuevXJyGdjXk8j","accessToken":"h8YOleAJoaBkNCJl3kmOgmlsocNo0J5LiwZljAV9","expiresIn":3600,"remember":false}

Page 19: Data api workshop at Co-Edo

記事の投稿curl -i http://localhost/cgi-bin/mt/mt-data-api.cgi/v1/sites/1/entries -X POST-H "X-MT-Authorization: MTAuth accessToken=h8YOleAJoaBkNCJl3kmOgmlsocNo0J5LiwZljAV9”-d entry="{\"status\" : \"Publish\", \"title\" : \"This is test post\", \"body\" : \"Yeah\!\" }"

リクエスト

応答HTTP/1.1 200 OKDate: Mon, 09 Jun 2014 07:27:00 GMTServer: Apache/2.2.26 (Unix) mod_ssl/2.2.26 OpenSSL/1.0.1e DAV/2 PHP/5.3.27X-content-type: nosniffCache-control: no-cacheTransfer-Encoding: chunkedContent-Type: application/json; charset=UTF-8X-Pad: avoid browser bug!{"excerpt":"Yeah!...","date":"2014-06-09T16:27:01\u002b09:00","status":"Publish","updatable":true,"author":{"userpicUrl":null,"id":"1","displayName":"Yuji Takayama"},"comments":[],"allowComments":true,"permalink":"http://localhost/blog/20140609-1/2014/06/this-is-test-post.html","keywords":"","body":"Yeah!","trackbacks":[],"id":4,"allowTrackbacks":false,"modifiedDate":"2014-06-09T16:27:01\u002b09:00","trackbackCount":0,"blog":{"id":"1"},"categories":[],"tags":[],"commentCount":0,"assets":[],"basename":"this_is_test_post","createdDate":"2014-06-09T16:27:01\u002b09:00","class":"entry","title":"This is test post","pingsSentUrl":[],"more":"","customFields":[]}% /Users/takayama% curl -i http://localhost/cgi-bin/mt/mt-data-api.cgi/v1/sites/1/entries -X POST -H "X-MT-Authorization: MTAuth accessToken=h8YOleAJoaBkNCJl3kmOgmlsocNo0J5LiwZljAV9" -d entry="{\"status\" : \"Publish\", \"title\" : \"This is test post\", \"body\" : \"Yeah\!\" }"

Page 20: Data api workshop at Co-Edo

まぁ、無理ですよね

(́・ω・`)

Page 21: Data api workshop at Co-Edo

JavaScript ライブラリ

Page 22: Data api workshop at Co-Edo

• REST API の呼び出しをラッピング

• シンプルな実装なので、他のライブラリと干渉しにくい

• 他の言語系も順次サポート予定

Page 23: Data api workshop at Co-Edo

使い方

var  api  =  new  MT.DataAPI({      baseUrl:    "https://your-­‐host/mt/mt-­‐data-­‐api.cgi",      clientId:  "your-­‐client-­‐id"  });  !api.listEntries(siteId,  function(response)  {      if  (response.error)  {          //  Handle  error          return;      }  !    for  (var  i  =  0;  i  <  response.items.length;  i++)  {              var  entry  =  response.items[i];              //  Render  an  entry      }  });

<script  type=“text/javascript”  src=“http://your-­‐host/path/to/mt-­‐static/data-­‐api/v1/js/mt-­‐data-­‐api.min.js”></script>

Page 24: Data api workshop at Co-Edo

var  api  =  new  MT.DataAPI({      baseUrl:    "https://your-­‐host/mt/mt-­‐data-­‐api.cgi",      clientId:  "your-­‐client-­‐id"  });  !api.getToken(function(response)  {      if  (response.error)  {          if  (response.error.code  ===  401)  {              //  You  have  not  been  authenticated  yet.              location.href  =  api.getAuthorizationUrl(location.href);          }  else  {  /*  Handle  error  */  }      }  else  {          //  You  have  been  authenticated.          api.listEntries(siteId,  {status:  'Draft'},  function(response)  {              if  (response.error)  {  /*  Handle  error  */  return;  }                  //  Fetched  a  list  of  drafts.              for  (var  i  =  0;  i  <  response.items.length;  i++)  {                      var  entry  =  response.items[i];                      //  Render  an  entry              }          });      }  });

Page 25: Data api workshop at Co-Edo

サインイン から 記事のポストまで

実践

Page 26: Data api workshop at Co-Edo

Movable Type Writer(仮)https://github.com/movabletype/MovableTypeWriter

Page 27: Data api workshop at Co-Edo

• Movable Type powered by JavaScript

• 記事の投稿に特化した Chrome アプリ

• Data API + jQuery + Bootstrap3

• MIT でフォーク自由

Page 28: Data api workshop at Co-Edo

使っているメソッド• authenticate(サインイン)

• getToken(トークン取得)

• listBlogForUser(権限を持っているサイトの一覧を取得)

• createEntry(記事の作成)

Page 29: Data api workshop at Co-Edo

初期化    jQuery(document).ready(  function()  {        getSettings().then(              function(settings)  {                  if  (!settings  ||  !settings.apipath)  {                      return  jQuery('#setting-­‐panel-­‐dialog').modal();                  }  !                api  =  new  MT.DataAPI({                      baseUrl:    settings.apipath,                      clientId:  "movabletype-­‐writer"                  });  !                doSignIn(settings.username,  settings.password)                  .then(  loadSiteList  );  

.  

.  

.

Page 30: Data api workshop at Co-Edo

初期化    jQuery(document).ready(  function()  {        getSettings().then(              function(settings)  {                  if  (!settings  ||  !settings.apipath)  {                      return  jQuery('#setting-­‐panel-­‐dialog').modal();                  }  !                api  =  new  MT.DataAPI({                      baseUrl:    settings.apipath,                      clientId:  "movabletype-­‐writer"                  });  !                doSignIn(settings.username,  settings.password)                  .then(  loadSiteList  );  

.  

.  

.ローカルストレージから、設定内容を読み込む。

設定されていなければ、設定用のダイアログを表示する

Page 31: Data api workshop at Co-Edo

初期化    jQuery(document).ready(  function()  {        getSettings().then(              function(settings)  {                  if  (!settings  ||  !settings.apipath)  {                      return  jQuery('#setting-­‐panel-­‐dialog').modal();                  }  !                api  =  new  MT.DataAPI({                      baseUrl:    settings.apipath,                      clientId:  "movabletype-­‐writer"                  });  !                doSignIn(settings.username,  settings.password)                  .then(  loadSiteList  );  

.  

.  

.Data API のインスタンスを生成する baseUrl には Data API へのURL

clientId は任意の文字列

Page 32: Data api workshop at Co-Edo

初期化    jQuery(document).ready(  function()  {        getSettings().then(              function(settings)  {                  if  (!settings  ||  !settings.apipath)  {                      return  jQuery('#setting-­‐panel-­‐dialog').modal();                  }  !                api  =  new  MT.DataAPI({                      baseUrl:    settings.apipath,                      clientId:  "movabletype-­‐writer"                  });  !                doSignIn(settings.username,  settings.password)                  .then(  loadSiteList  );  

.  

.  

.ユーザー認証を行う

その後、サイト一覧を更新する

Page 33: Data api workshop at Co-Edo

サインイン    var  doSignIn  =  function(user,  passwd)  {          var  def  =  new  jQuery.Deferred();  !        api.authenticate({  username:  user,  password:  passwd  },                function(response)  {              if  (response.error)  {                  var  code  =  response.error.code;                  var  msg;                  if  (code  ===  404  )  {                  }  else  if  (code  ===  401  )  {                  }  else  {                  }                  return  def.reject(msg);              }  else  {                  api.storeTokenData(response);                  return  def.resolve();              }          });  !        return  def.promise();      };

Page 34: Data api workshop at Co-Edo

サインイン    var  doSignIn  =  function(user,  passwd)  {          var  def  =  new  jQuery.Deferred();  !        api.authenticate({  username:  user,  password:  passwd  },                function(response)  {              if  (response.error)  {                  var  code  =  response.error.code;                  var  msg;                  if  (code  ===  404  )  {                  }  else  if  (code  ===  401  )  {                  }  else  {                  }                  return  def.reject(msg);              }  else  {                  api.storeTokenData(response);                  return  def.resolve();              }          });  !        return  def.promise();      };

認証用のエンドポイントを呼び出す。 認証エラーは、response.error の有無で判定

認証に成功したら、storeTokenData でセッションデータを保存

Page 35: Data api workshop at Co-Edo

サイト一覧の取得    var  loadSiteList  =  function()  {          var  def  =  new  jQuery.Deferred();  !        api.listBlogsForUser('me',  function(response)  {              if  (response.error)  {                  var  code  =  response.error.code;                  var  msg;                  if  (code  ===  404  )  {                  }  else  if  (code  ===  403  )  {                  }  else  {                  }                  return  def.reject(msg);              }  !            var  $blogListBox  =  jQuery('#form-­‐blog-­‐list');              response.items.forEach(  function(x,  i)  {                  $blogListBox.append($('<option>').html(x.name).val(x.id));              });              $blogListBox.removeAttr('disabled');          });  

Page 36: Data api workshop at Co-Edo

サイト一覧の取得    var  loadSiteList  =  function()  {          var  def  =  new  jQuery.Deferred();  !        api.listBlogsForUser('me',  function(response)  {              if  (response.error)  {                  var  code  =  response.error.code;                  var  msg;                  if  (code  ===  404  )  {                  }  else  if  (code  ===  403  )  {                  }  else  {                  }                  return  def.reject(msg);              }  !            var  $blogListBox  =  jQuery('#form-­‐blog-­‐list');              response.items.forEach(  function(x,  i)  {                  $blogListBox.append($('<option>').html(x.name).val(x.id));              });              $blogListBox.removeAttr('disabled');          });  

ユーザーが権限を持つサイトの一覧を取得する エラー 404: サイトが見つからない

エラー: 403: 認証エラー

Page 37: Data api workshop at Co-Edo

サイト一覧の取得    var  loadSiteList  =  function()  {          var  def  =  new  jQuery.Deferred();  !        api.listBlogsForUser('me',  function(response)  {              if  (response.error)  {                  var  code  =  response.error.code;                  var  msg;                  if  (code  ===  404  )  {                  }  else  if  (code  ===  403  )  {                  }  else  {                  }                  return  def.reject(msg);              }  !            var  $blogListBox  =  jQuery('#form-­‐blog-­‐list');              response.items.forEach(  function(x,  i)  {                  $blogListBox.append($('<option>').html(x.name).val(x.id));              });              $blogListBox.removeAttr('disabled');          });  

セレクトボックスに読み込んだサイトの一覧を追加

Page 38: Data api workshop at Co-Edo

記事の投稿    jQuery('#button-­‐post').click(  function()  {          var  entry  =  {};          entry['title']  =  jQuery('#entry-­‐title').val();          entry['body']  =  jQuery('#entry-­‐body').code();          entry['status']  =  'Publish';          var  siteId  =  jQuery('#form-­‐blog-­‐list  option:selected').val();          api.getToken(function(response)  {              if  (response.error)  {  }              api.createEntry(siteId,  entry,  function(response)  {                  if  (response.error)  {                      var  code  =  response.error.code;                      var  msg;                      if  (code  ===  404  )  {                  }  else  if  (code  ===  401  )  {                      }  else  if  (code  ===  403  )  {                      }  else  {                      }                  }              }          }      }

Page 39: Data api workshop at Co-Edo

記事の投稿    jQuery('#button-­‐post').click(  function()  {          var  entry  =  {};          entry['title']  =  jQuery('#entry-­‐title').val();          entry['body']  =  jQuery('#entry-­‐body').code();          entry['status']  =  'Publish';          var  siteId  =  jQuery('#form-­‐blog-­‐list  option:selected').val();          api.getToken(function(response)  {              if  (response.error)  {  }              api.createEntry(siteId,  entry,  function(response)  {                  if  (response.error)  {                      var  code  =  response.error.code;                      var  msg;                      if  (code  ===  404  )  {                  }  else  if  (code  ===  401  )  {                      }  else  if  (code  ===  403  )  {                      }  else  {                      }                  }              }          }      }

エントリーデータをハッシュで作成

Page 40: Data api workshop at Co-Edo

記事の投稿    jQuery('#button-­‐post').click(  function()  {          var  entry  =  {};          entry['title']  =  jQuery('#entry-­‐title').val();          entry['body']  =  jQuery('#entry-­‐body').code();          entry['status']  =  'Publish';          var  siteId  =  jQuery('#form-­‐blog-­‐list  option:selected').val();          api.getToken(function(response)  {              if  (response.error)  {  }              api.createEntry(siteId,  entry,  function(response)  {                  if  (response.error)  {                      var  code  =  response.error.code;                      var  msg;                      if  (code  ===  404  )  {                  }  else  if  (code  ===  401  )  {                      }  else  if  (code  ===  403  )  {                      }  else  {                      }                  }              }          }      }

トークンの有効期限が過ぎている場合は、再取得が必要

Page 41: Data api workshop at Co-Edo

記事の投稿    jQuery('#button-­‐post').click(  function()  {          var  entry  =  {};          entry['title']  =  jQuery('#entry-­‐title').val();          entry['body']  =  jQuery('#entry-­‐body').code();;          entry['status']  =  'Publish';          var  siteId  =  jQuery('#form-­‐blog-­‐list  option:selected').val();          api.getToken(function(response)  {              if  (response.error)  {  }              api.createEntry(siteId,  entry,  function(response)  {                  if  (response.error)  {                      var  code  =  response.error.code;                      var  msg;                      if  (code  ===  404  )  {                  }  else  if  (code  ===  401  )  {                      }  else  if  (code  ===  403  )  {                      }  else  {                      }                  }              }          }      }

エントリの作成をおこなう エラー 404: 投稿先のサイトが見つからない

エラー 403: 権限がない エラー 401: 認証エラー

Page 42: Data api workshop at Co-Edo

ユーザー専用 投稿ツール

Page 43: Data api workshop at Co-Edo

タイトル

カスタムフィールド

カスタムフィールド

本文

Page 44: Data api workshop at Co-Edo

JavaScript ライブラリ

勘所

Page 45: Data api workshop at Co-Edo

API の呼び出しは非同期

初期化パラメータで同期にすることも可能 !

var api = new MT.DataAPI({ clientId: ‘your-client-id’, baseUrl: ‘https://your-host/your-mt-api.cgi', async: false });

Page 46: Data api workshop at Co-Edo

認証URL vs 認証呼び出し

ブラウザからの利用であれば、authenticate ではなく、 getAuthorizationUrl を使って MT 標準のサインイン画面を利用する方がいい(セキュリティ、信頼性) !

var url = api.getAuthorizationUrl( “https://your-host/your-app/“) // リダイレクト先 );

Page 47: Data api workshop at Co-Edo

クロスドメインクロスドメイン間の通信は原則禁止されているので、 適宜 環境変数を設定する !

少なくとも DataAPICORSAllowOrigin * DataAPICORSAllowOrigin http://www.example.com, http://beta.example.com !

ついでに DataAPICORSAllowHeaders DataAPICORSExposeHeaders DataAPICORSAllowMethods

など

Page 48: Data api workshop at Co-Edo

Data API こんな使い方も

Page 49: Data api workshop at Co-Edo

スマートフォンアプリ

• スマフォサイトをウェブアプリとして

• ネイティブアプリから利用して

• Movable Type as Backend Service

Page 50: Data api workshop at Co-Edo

Ajax 検索

• インクリメンタルサーチ

• MT-Search.cgi よりも軽量

Page 51: Data api workshop at Co-Edo

ページネーション

• 画面のスクロールでインクリメンタルな読み込み

• 検索結果などページネーション

Page 52: Data api workshop at Co-Edo

社内システムなど

• 社内ポータルに、記事作成のインターフェイスを用意して、簡単に記事をポスト

• 一般ユーザーは、MTの画面を見る必要がない

Page 53: Data api workshop at Co-Edo

Google Analytics

• MTにGoogle Analyticsの設定があれば

• Data API から Google Analyticsのデータを読み込める

Page 54: Data api workshop at Co-Edo

Chrome

• タグ・環境変数の検索 by Omnibox

• 再構築の定期実行 by Alarm

• スニペット挿入 by BrowserAction

• 詳しくは、この後のお話で!

Page 55: Data api workshop at Co-Edo

Next Data API…

Page 56: Data api workshop at Co-Edo

• 色々まだ足りてないですよね?

• 次以降のリリースで含まれる Data API の機能をプラグインで随時リリース予定

• 震えて、待て!