Laravel で Tumblr API の Access Token を取得
Laravel で Tumblr API のアクセストークンを取得するプログラムを動かしたときのメモ
検証環境
$ php --version PHP 7.1.4 (cli) (built: May 11 2017 17:22:31) ( NTS ) Copyright (c) 1997-2017 The PHP Group Zend Engine v3.1.0, Copyright (c) 1998-2017 Zend Technologies $ php artisan --version Laravel Framework 5.4.33
OAuth パッケージについて
今回は Laravel5 対応の以下のパッケージを使用します
github.com
oriceon/oauth-5-laravel のインストール
composer.json の require セクションに下記内容を追加
"require": { "oriceon/oauth-5-laravel": "dev-master" }
その後 composer update でインストール
$ composer update
config/app.php を下記のように変更してパッケージを登録
--- config/app.php.orig Fri Aug 18 12:25:23 2017 +++ config/app.php Wed Aug 16 16:55:38 2017 @@ -177,6 +177,11 @@ App\Providers\EventServiceProvider::class, App\Providers\RouteServiceProvider::class, + /* + * OAuth + */ + Artdarek\OAuth\OAuthServiceProvider::class, + ], /* @@ -212,6 +217,7 @@ 'Log' => Illuminate\Support\Facades\Log::class, 'Mail' => Illuminate\Support\Facades\Mail::class, 'Notification' => Illuminate\Support\Facades\Notification::class, + 'OAuth' => Artdarek\OAuth\Facade\OAuth::class, 'Password' => Illuminate\Support\Facades\Password::class, 'Queue' => Illuminate\Support\Facades\Queue::class, 'Redirect' => Illuminate\Support\Facades\Redirect::class,
以下の内容で config/oauth-5-laravel.php を作成
<?php return [ /* |-------------------------------------------------------------------------- | oAuth Config |-------------------------------------------------------------------------- */ /** * Storage */ 'storage' => '\\OAuth\\Common\\Storage\\Session', /** * Consumers */ 'consumers' => [ 'Tumblr' => [ 'client_id' => env('TUMBLR_CLIENT_ID'), 'client_secret' => env('TUMBLR_CLIENT_SECRET'), // No scope - oauth1 doesn't need scope ], ] ];
.env に Consumer Key, Consumer Secret を追加
TUMBLR_CLIENT_ID=Your-Consumer-Key TUMBLR_CLIENT_SECRET=Your-Consumer-Secret
OAuth 認証プログラム
app/Http/Controllers/TumblrAuthController.php
<?php namespace App\Http\Controllers; use Illuminate\Http\Request; class TumblrAuthController extends Controller { public function loginWithTumblr(Request $request) { // get data from request $token = $request->get('oauth_token'); $verify = $request->get('oauth_verifier'); // get tumblr service $tmb = \OAuth::consumer('Tumblr'); // check if code is valid // if code is provided get user data and sign in if ( ! is_null($token) && ! is_null($verify)) { // This was a callback request from tumblr, get the token $token = $tmb->requestAccessToken($token, $verify); //Var_dump //display whole array. dd($token); } // if not ask for permission first else { // get request token $reqToken = $tmb->requestRequestToken(); // get Authorization Uri sending the request token $url = $tmb->getAuthorizationUri(['oauth_token' => $reqToken->getRequestToken()]); // return to tumblr login url return redirect((string)$url); } } }
routes/web.php
<?php /* |-------------------------------------------------------------------------- | Web Routes |-------------------------------------------------------------------------- | | Here is where you can register web routes for your application. These | routes are loaded by the RouteServiceProvider within a group which | contains the "web" middleware group. Now create something great! | */ Route::get('/tumblr', 'TumblrAuthController@loginWithTumblr');
OAuth 認証プログラムの実行
以下のコマンドで開発用サーバーが起動します
$ php artisan serve
web ブラウザで http://127.0.0.1:8000/tumblr にアクセスします
途中、以下の画面が表示されたときは Allow をクリックします
web ブラウザに以下のような Access Token の表示が出れば成功です
StdOAuth1Token {#175 ▼ #requestToken: "xxxxx...." #requestTokenSecret: "xxxxx..." #accessTokenSecret: "xxxxx..." #accessToken: "xxxxx..." #refreshToken: null #endOfLife: -9002 #extraParams: [] }
glide で GAE/Go プロジェクトのパッケージ管理
Google App Engine for Go (GAE/Go) の開発環境に glide でパッケージをインストールする手順メモ
検証環境
Windows10 Home Edition VirtualBox 5.1.22 Docker version 17.05.0-ce, build 89658be docker-compose version 1.6.2, build 4d72027
GAE/Go 開発環境について
今回は下記サイトの手順で構築したものを使用します
takaya030.hatenablog.com
GAE/Go 環境での vendoring の注意点
ディレクトリ構成
上記を踏まえた上でのディレクトリ構成
+---gaego | | docker-compose.yml | | | +---config | | | +---data | | Dockerfile | | | +---glide | | | +---sdk | Dockerfile | +---logs | +---www | +---app | app.yaml | main.go | +---src | +---hello app.go app-engine.go app-standalone.go hello.go
各種ファイルの詳細
Echo を使って "Hello, World!" を表示するサンプルプログラムです
(前回記事から追加、変更のあるもののみ)
www/app/main.go
package main import ( _ "hello" ) func init() { }
www/src/hello/app.go
package hello var e = createMux()
www/src/hello/app-engine.go
// +build appengine package hello import ( "github.com/labstack/echo" "github.com/labstack/echo/engine/standard" "net/http" ) func createMux() *echo.Echo { e := echo.New() // note: we don't need to provide the middleware or static handlers, that's taken care of by the platform // app engine has it's own "main" wrapper - we just need to hook echo into the default handler s := standard.New("") s.SetHandler(e) http.Handle("/", s) return e } // main()は書かなくて良い
www/src/hello/app-standalone.go
// +build !appengine,!appenginevm package hello import ( "github.com/labstack/echo" "github.com/labstack/echo/engine/standard" "github.com/labstack/echo/middleware" ) // ログの設定や静的ファイルの場所指定などをしています func createMux() *echo.Echo { e := echo.New() e.Use(middleware.Recover()) e.Use(middleware.Logger()) e.Use(middleware.Gzip()) e.Use(middleware.Static("public")) return e } func main() { e.Run(standard.New(":8080")) }
www/src/hello/hello.go
package hello import ( "net/http" "github.com/labstack/echo" "github.com/labstack/echo/engine/standard" "github.com/rs/cors" ) func init() { g := e.Group("/hello") g.Use(standard.WrapMiddleware(cors.Default().Handler)) g.GET("", getWorld) g.GET("/:id", getUser) } func getWorld(c echo.Context) error { return c.String(http.StatusOK, "Hello, World!") } func getUser(c echo.Context) error { return c.String(http.StatusOK, "Hello, " + c.P(0) + "!") }
glide のインストール
$ cd gaego $ docker-compose run --rm sdk go get github.com/Masterminds/glide
glide.yaml の作成
$ cd gaego $ docker-compose run --rm sdk /bin/bash -c "cd src/hello;glide create" Starting gaego_data_1 [INFO] Generating a YAML configuration file and guessing the dependencies [INFO] Attempting to import from other package managers (use --skip-import to skip) [INFO] Scanning code to look for dependencies [INFO] --> Found reference to github.com/labstack/echo [INFO] --> Adding sub-package engine/standard to github.com/labstack/echo [INFO] --> Adding sub-package middleware to github.com/labstack/echo [INFO] --> Found reference to github.com/rs/cors [INFO] Writing configuration file (glide.yaml) [INFO] Would you like Glide to help you find ways to improve your glide.yaml configuration? [INFO] If you want to revisit this step you can use the config-wizard command at any time. [INFO] Yes (Y) or No (N)? N [INFO] You can now edit the glide.yaml file. Consider: [INFO] --> Using versions and ranges. See https://glide.sh/docs/versions/ [INFO] --> Adding additional metadata. See https://glide.sh/docs/glide.yaml/ [INFO] --> Running the config-wizard command to improve the versions in your configuration
glide によるパッケージインストール
上記操作で作成された glide.yaml では Echo の最新版がインストールされますが、go1.6 では動作しないので旧バージョンを指定するように変更します
(glide.yaml 4行目に "version: v2.2.0" を追加)
www/src/hello/glide.yaml
package: hello import: - package: github.com/labstack/echo version: v2.2.0 # この行を追加 subpackages: - engine/standard - middleware - package: github.com/rs/cors
その後、以下の操作でインストール
$ cd gaego $ docker-compose run --rm sdk /bin/bash -c "cd src/hello;glide up" Starting gaego_data_1 [INFO] Downloading dependencies. Please wait... [INFO] --> Fetching github.com/labstack/echo [INFO] --> Fetching github.com/rs/cors [INFO] --> Setting version for github.com/labstack/echo to v2.2.0. [INFO] Resolving imports [INFO] --> Fetching github.com/labstack/gommon [INFO] --> Fetching github.com/dgrijalva/jwt-go [INFO] --> Fetching github.com/mattn/go-isatty [INFO] --> Fetching github.com/valyala/fasttemplate [INFO] --> Fetching golang.org/x/net [INFO] --> Fetching github.com/mattn/go-colorable [INFO] --> Fetching golang.org/x/sys [INFO] --> Fetching github.com/valyala/bytebufferpool [INFO] Downloading dependencies. Please wait... [INFO] Setting references for remaining imports [INFO] Exporting resolved dependencies... [INFO] --> Exporting github.com/valyala/bytebufferpool [INFO] --> Exporting github.com/labstack/echo [INFO] --> Exporting github.com/dgrijalva/jwt-go [INFO] --> Exporting github.com/mattn/go-colorable [INFO] --> Exporting github.com/rs/cors [INFO] --> Exporting github.com/mattn/go-isatty [INFO] --> Exporting github.com/labstack/gommon [INFO] --> Exporting github.com/valyala/fasttemplate [INFO] --> Exporting golang.org/x/sys [INFO] --> Exporting golang.org/x/net [INFO] Replacing existing vendor dependencies [INFO] Project relies on 10 dependencies.
以上で www/src/hello/vendor 以下に Echo v2 がインストールされました
動作確認
以下のコマンドで開発用サーバーが起動します
$ docker-compose up -d
web ブラウザで http://192.168.99.100:8080/hello にアクセスして "Hello, world!" の文字が表示されれば成功です
http://192.168.99.100:8080/hello/takaya030 にアクセスすると "Hello, takaya030!" と表示されます
ローカルの Docker 環境で Cloud9 IDE を動かす
Cloud9 IDE を Docker コンテナで動作させたときの手順メモ
検証環境
Windows10 Home Edition VirtualBox 5.1.22 Docker version 17.05.0-ce, build 89658be docker-compose version 1.6.2, build 4d72027
インストールにあたっての注意点
ディレクトリ構成
+---c9 | docker-compose.yml | +---workspace | +---data | Dockerfile | +---ide Dockerfile
各種設定ファイル
c9/docker-compose.yml
version: "2" services: data: build: ./data volumes: - ./workspace:/workspace ide: build: ./ide volumes_from: - data volumes: - /etc/localtime:/etc/localtime:ro ports: - "8080:8080" command: node /home/docker/cloud9/server.js --port 8080 -w /workspace -l 0.0.0.0 --auth docker:tcuser
c9/data/Dockerfile
FROM busybox LABEL maintainer "takaya030" RUN mkdir -p /workspace VOLUME ["/workspace"] CMD ["true"]
c9/ide/Dockerfile
FROM ubuntu:16.04 LABEL maintainer "takaya030" RUN apt-get update -y \ && apt-get install -y nodejs npm curl git sudo \ && apt-get clean \ && rm -fr /var/lib/apt/lists/* RUN npm cache clean \ && npm install n -g RUN n 0.12.18 \ && ln -sf /usr/local/bin/node /usr/bin/node \ && apt-get purge -y nodejs npm # create docker user RUN useradd -d /home/docker -m -s /bin/bash -u 1000 -g 50 docker USER 1000 RUN git clone https://github.com/c9/core.git /home/docker/cloud9 \ && cd /home/docker/cloud9 \ && ./scripts/install-sdk.sh USER root RUN mkdir -p /workspace VOLUME ["/workspace"] WORKDIR /workspace USER 1000
動作確認
以下のコマンドで Cloud9 IDE が動作します
$ docker-compose up -d
web ブラウザで http://192.168.99.100:8080 にアクセスすると Basic 認証で UserId と Password の入力を求められるので次の通りに入力する
- UserId: docker
- Password: tcuser
その後、以下の画像のように表示されれば成功です
gcloud app deploy : This deployment has too many files
Laravel のプロジェクトを GAE にデプロイしたときに以下のエラーが発生したときの対処手順メモ
ERROR: (gcloud.app.deploy) Error Response: [400] This deployment has too many files. New versions are limited to 10000 files for this app.
エラー原因
Laravel のプロジェクトに Google APIs Client Library for PHP (google/apiclient) を追加したことでプロジェクトのファイル数が 10,000 を超えたため
(GAE は 1 バージョンあたり 10,000 ファイルまでしかアップロードできない)
# before installing google/apiclient $ cd laravel $ ls -FR | grep -v / | grep -v "^$" | wc -l 5688 # after installing google/apiclient $ cd laravel $ composer require google/apiclient:v2.1.3 $ ls -FR | grep -v / | grep -v "^$" | wc -l 10868
対処方法
調べたところ増加したファイルの大半は google/apiclient-services のファイルだった
これらは Google の各種サービスにアクセスするためのクラス群であるが、ソースを見たところ各サービスは独立していて互いに参照していないように見受けられた
今回は Gmail API のみ使えればよいので、それ以外のファイルは削除した
$ cd laravel $ mv vendor/google/apiclient-services/src/Google/Service/Gmail /tmp $ mv vendor/google/apiclient-services/src/Google/Service/Gmail.php /tmp $ rm -rf vendor/google/apiclient-services/src/Google/Service/* $ mv /tmp/Gmail vendor/google/apiclient-services/src/Google/Service/ $ mv /tmp/Gmail.php vendor/google/apiclient-services/src/Google/Service/ $ ls -FR | grep -v / | grep -v "^$" | wc -l 5832
再度 "gcloud app deploy" を実行したところデプロイが正常に完了し、GAE で Gmail API が動作していることを確認した
Lumen でお手軽に Google API を使う
以前、Laravel から Google API を使う記事を書きましたが、今回は Lumen からより簡単に使ってみます
検証環境
$ php --version PHP 5.5.34 (cli) (built: Jun 24 2017 00:40:52) Copyright (c) 1997-2015 The PHP Group Zend Engine v2.5.0, Copyright (c) 1998-2015 Zend Technologies $ php artisan --version Laravel Framework version Lumen (5.1.7) (Laravel Components 5.1.*)
OAuth クライアント ID、Refresh Token の取得
以下の記事を参考に Google API で使用する Client ID、Access Token を取得する
takaya030.hatenablog.com
Google APIs Client Library for PHP のインストール
前回 oauth2 ライブラリは oriceon/oauth-5-laravel を使用しましたが、今回は google/apiclient を使います
$ composer require google/apiclient:v2.1.3
サンプルコード
.env
.env に以下の内容を追加
# oauth GOOGLE_CLIENT_ID=Your-Clinet-Id GOOGLE_CLIENT_SECRET=Your-Clinet-Secret GOOGLE_REFRESH_TOKEN=Your-Refresh-Token
app/Http/Controllers/GmailController.php
<?php namespace App\Http\Controllers; class GmailController extends Controller { // show labels public function showLabels() { $client = new \Google_Client(); $client->setClientId( env('GOOGLE_CLIENT_ID') ); $client->setClientSecret( env('GOOGLE_CLIENT_SECRET') ); $client->setScopes([ "https://mail.google.com/" ]); $client->refreshToken( env('GOOGLE_REFRESH_TOKEN') ); $service = new \Google_Service_Gmail($client); // Print the labels in the user's account. $user = 'me'; $results = $service->users_labels->listUsersLabels($user); $labels = []; if (count($results->getLabels()) == 0) { $labels[] = "No labels found."; } else { $labels[] = "Labels:"; foreach ($results->getLabels() as $label) { $labels[] = sprintf("- %s", $label->getName()); } } return view( 'gmail.labels', ['labels' => $labels] ); } }
app/Http/routes.php
<?php /* |-------------------------------------------------------------------------- | Application Routes |-------------------------------------------------------------------------- | | Here is where you can register all of the routes for an application. | It is a breeze. Simply tell Lumen the URIs it should respond to | and give it the Closure to call when that URI is requested. | */ $app->get('/gmail/labels', 'GmailController@showLabels');
動作確認
テストサーバー起動
$ php artisan serve
WEBブラウザで http://localhost:8000/gmail/labels を開いて下の画像のように表示されれば成功です
まとめ
oriceon/oauth-5-laravel のときはエンドポイントの url を文字列で直接指定したり、レスポンスの json を自分でパースしなければならなかったりといろいろ手間がかかりましたが、google/apiclient ではそれらをライブラリ側で吸収してくれているので以前より簡潔なコードになっています
Go言語(golang)で Gmail の受信トレイにメールを追加してみる
Gmail API を使うとメール送信無しに Gmail の受信トレイに直接メールを追加することができます。その検証をしたときのメモ。
検証環境
Windows10 Home Edition C:\>go version go version go1.8 windows/amd64
Access Token の取得
以下の記事を参考に Gmail API で使用する Access Token を取得する
takaya030.hatenablog.com
oauth2 関連パッケージの取得
C:\>go get golang.org/x/oauth2 C:\>go get golang.org/x/oauth2/google C:\>go get google.golang.org/api/gmail/v1
ソースコード
insertmail.go
package main import ( "fmt" "time" "log" "encoding/base64" "golang.org/x/oauth2" "golang.org/x/oauth2/google" gmail "google.golang.org/api/gmail/v1" ) func main() { config := oauth2.Config{ ClientID: "Your Client ID", ClientSecret: "Your Client Secret", Endpoint: google.Endpoint, RedirectURL: "urn:ietf:wg:oauth:2.0:oob", //今回はリダイレクトしないためこれ Scopes: []string{"https://mail.google.com/"}, //必要なスコープを追加 } expiry,_ := time.Parse("2006-01-02", "2017-07-11") token := oauth2.Token{ AccessToken: "Your Access Token", TokenType: "Bearer", RefreshToken: "Your Refresh Token", Expiry: expiry, } client := config.Client(oauth2.NoContext, &token) srv, err := gmail.New(client) if err != nil { log.Fatalf("Unable to retrieve gmail Client %v", err) } // email date const rfc2822 = "Mon Jan 02 15:04:05 -0700 2006" email_date := time.Now().Format(rfc2822) // an email data message := gmail.Message{ Raw: base64.URLEncoding.EncodeToString([]byte("Date: " + email_date + "\r\n" + "From: hoge@example.com\r\n" + "To: fuga@gmail.com\r\n" + "Subject: test mail\r\n" + "Content-Type: text/html; charset=UTF-8\r\n" + "\r\n" + "<html><body>This is a test mail.</body></html>")), LabelIds: []string{"INBOX"}, } // insert message m, err := srv.Users.Messages.Insert("me", &message).Do() if err != nil { log.Fatalf("Unable to insert messages. %v", err) } fmt.Printf("Finish inserting message. id:%s", m.Id) }
ビルド
C:\go_src>go build insertmail.go
動作確認
C:\go_src>insertmail.exe
Finish inserting message. id:15d37199b2d9xxxx
Gmail の受信トレイ(INBOX)に以下のメールが追加されていれば成功です
参考サイト
- Google I/O 2014の裏でひっそり公開されたGmail APIを触ってみる - Qiita
- Users.messages: insert | Gmail API | Google Developers
- go言語でoauth2パッケージを使う | go | kido Tech Blog
- Go Quickstart | Gmail API | Google Developers
- oauth2 - GoDoc
- gmail - GoDoc
- go - golang RFC2822 conversion - Stack Overflow
- Golang: 文字列を base64 にエンコードする - Sarabande.jp
Go言語(golang)で Gmail API を使う
検証環境
Windows10 Home Edition C:\>go version go version go1.8 windows/amd64
Access Token の取得
以下の記事を参考に Gmail API で使用する Access Token を取得する
takaya030.hatenablog.com
oauth2 関連パッケージの取得
C:\>go get golang.org/x/oauth2 C:\>go get golang.org/x/oauth2/google C:\>go get google.golang.org/api/gmail/v1
ソースコード
gmailtest.go
package main import ( "fmt" "time" "log" "golang.org/x/oauth2" "golang.org/x/oauth2/google" gmail "google.golang.org/api/gmail/v1" ) func main() { config := oauth2.Config{ ClientID: "Your Client ID", ClientSecret: "Your Client Secret", Endpoint: google.Endpoint, RedirectURL: "urn:ietf:wg:oauth:2.0:oob", //今回はリダイレクトしないためこれ Scopes: []string{"https://mail.google.com/"}, //必要なスコープを追加 } expiry,_ := time.Parse("2006-01-02", "2017-07-11") token := oauth2.Token{ AccessToken: "Your Access Token", TokenType: "Bearer", RefreshToken: "Your Refresh Token", Expiry: expiry, } client := config.Client(oauth2.NoContext, &token) srv, err := gmail.New(client) if err != nil { log.Fatalf("Unable to retrieve gmail Client %v", err) } r, err := srv.Users.Labels.List("me").Do() if err != nil { log.Fatalf("Unable to get labels. %v", err) } if (len(r.Labels) > 0) { fmt.Print("Labels:\n") for _, l := range r.Labels { fmt.Printf("- %s\n", l.Name) } } else { fmt.Print("No label found.") } }
ビルド
C:\go_src>go build gmailtest.go
動作確認
C:\go_src>gmailtest.exe
Labels:
- CATEGORY_PERSONAL
- プライベート
- 旅行
- CATEGORY_SOCIAL
- 領収書
- IMPORTANT
- 仕事
- CATEGORY_UPDATES
- CATEGORY_FORUMS
- CHAT
- SENT
- INBOX
- TRASH
- CATEGORY_PROMOTIONS
- DRAFT
- SPAM
- STARRED
- UNREAD