Quantcast
Channel: Postmanタグが付けられた新着記事 - Qiita
Viewing all 496 articles
Browse latest View live

[Amazon WorkSpaces]AmazonLinux2にPostmanインストール

$
0
0

Amazon Linux release 2 (Karoo)

# Postmanのインストール
$ sudo wget https://dl.pstmn.io/download/latest/linux64 -O postman.tar.gz
$ sudo tar -xzf postman.tar.gz -C /opt
$ sudo rm postman.tar.gz
$ sudo ln -s /opt/Postman/Postman /usr/bin/postman

# ランチャーに追加(アプリケーションープログラミングーPostMan)
mkdir -p ~/.local/share/applications
cat > ~/.local/share/applications/postman.desktop <<EOL
[Desktop Entry]
Encoding=UTF-8
Name=Postman
Exec=postman
Icon=/opt/Postman/app/resources/app/assets/icon.png
Terminal=false
Type=Application
Categories=Development;
EOL

設定後にログオフしてログインし直す必要があります


Twitter APIをPostmanで叩く方法

$
0
0

Twitter APIをPostmanで気軽に叩くための設定方法です。

  1. Authorizationタブを選択
  2. TypeをOAuth 1.0を選択
  3. Twitter APIキーを入力
  4. Add authorization data toにRequest Headersを選択

以上です。
後は実行したいエンドポイントを入れて叩くだけです😎

スクリーンショット 2019-05-16 21.13.34.png

Postmanでリクエスト情報を共有(シェア)する方法

$
0
0

はじめに

APIの確認にPostmanを使用しており、
クライアントにレスポンスを確認してもらう必要があった。

今回はGETのAPIだったので、URLを渡せばいいですが、
POSTのAPIや、複数のAPIを共有したい時に、困っていました。

解決法

※これから行う方法は、Postmanのアカウントが必要です。

下記APIを共有したいとします。
http://127.0.0.1/api?value1=one&value2=two

APIのパラメータ等を入力する画面で、
Saveボタンを選択し、保存するCollectionを選択します。
Collectionがない場合、Create Collectionで作成してください。
スクリーンショット 2019-05-20 10.01.00.jpg

無事に保存すると、画面左の枠のCollectionsの中に、
作成したCollectionとAPIの情報が保存されていると思います。
この画面で、Collectionの・・・をクリックし、Share Collectionを選択してください。
※ログイン完了していなければ、ログインを求められます。
スクリーンショット 2019-05-20 10.13.47.jpg

出現した、モーダルのGet linkというタブを選択すると、
共有用のURLが出力されるので、これを共有したい人に渡すことで、インポートできます。
スクリーンショット 2019-05-20 10.05.03.jpg

おわりに

クライアントによっては、POSTでのパラメータの設定など、説明が難しいこともあるので、
簡単に共有できて、便利でした。

[メモ] Postman の OAuth 1.0a ヘルパーの encoding でまたハマる (pre-request script で回避)

$
0
0

少し前に Runscope でも同じ問題に遭遇し、同様に Pre-request Scripts で回避する記事を書きました。
https://qiita.com/jrsyo/items/0fc6cc85e1af49dfbe21

今回はその Postman client 版です。よって説明はだいぶ省略しています。

Issue

概要は下記の issue の内容の通りです。
https://github.com/twitterdev/postman-twitter-ads-api/issues/2

Runscope と同様、POST の場合は代わりにリクエストボディを使うことで Postman でも回避できましたが、リクエストボディを使わない GET などの場合は Pre-request Script での対応が必要でした。

Pre-request Script (Postman)

下記に置いてます。これを対象のリクエストの Pre-request Script にまるっと貼り付けて使います (+ 当該リクエストの Authorization TYPE を Inherit => No Auth に変更)。
https://github.com/twitterdev/postman-twitter-ads-api/blob/master/scripts/pre-request.js

Runscope よりもデフォルトで使えるライブラリが限られていたので少し冗長になってます。
参考: Postman Sandbox | Commonly used libraries and utilities

その他 Postman pre-request script について

今回 Postman client の pre-request script を初めて利用しましたが、ドキュメントに記載がない独自の専用メソッドやそのオプションが多数あり、これらを使うことで面倒な処理を減らすことができました。
参考までに、下記の Postman Collection SDK のドキュメントが結構役に立ちました。
https://www.postmanlabs.com/postman-collection/index.html

上記のドキュメントは Node.js の SDK モジュールをベースに説明していますが、一部の Class は Postman client 単体からもアクセスが可能です。

意外だったのは、Postman では最近まで (prior to v7.0.9) pre-request を使った request header の改変が出来なかったようで、最新バージョンでは

pm.request.headers.add()
pm.request.headers.upsert()
pm.request.headers.remove()

を使って自由に request header を変更出来るようになっています。
参考: Cannot add headers with pm.request.headers.add #4631

今回は少なくとも Authorization: header を追加する必要があったため、上記の修正なしでは成り立ちません。

便利系

下記は現在定義されている Postman の Environment 変数一覧をオブジェクト形式で受け取る例です。
excludeDisabled: true を使うことで、disable になっている変数を除外することができます。
pm.environment.get("variable_key") で個別に値を取得することも可能ですが、毎回内部 API コールを行うよりは予めこのようにまとめて取得しておいた方がよいでしょう。

const env_variables = pm.environment.toObject({
    excludeDisabled: true
});

下記は現在リクエストに定義されている Query Params 一覧を受け取る例です。
前述同様、excludeDisabled: true を使うことで、disable になっているパラメーターを除外することができます。通常リクエストの params には required/optional 両方のパラメーターが混在していることが多いため、このオプションはとても役に立ちます。

* ただし受け取る値は単なる String なので、それぞれの parameter に何か処理を加えたい場合、SDK を読み込んで QueryParam.parse() を使うことで Array 形式で parameter を受け取れます (Array の各 index に paramter が key: パラメータ名, value: パラメータ値 の object が入っている)。

// 単純に query parameter を string で受け取る
const query_string = pm.request.url.getQueryString({
    ignoreDisabled: true
});

// query parameter を Array で受け取る
const sdk = require('postman-collection');
// https://www.postmanlabs.com/postman-collection/QueryParam.html#.parse
const query_string_array = sdk.QueryParam.parse(
    pm.request.url.getQueryString({
        ignoreDisabled: true
    })
);

その他にも、pm.request.* 系は頻繁に使われる定番系メソッドだと思います。リクエストの情報を取得(e.g., pm.request.method)するだけでなく、上書きも可能です (e.g., pm.request.url)。

宣伝

ということで、Twitter Ads API の Postman Collection を最近公開しました。下記からインポートできます。
https://github.com/twitterdev/postman-twitter-ads-api

自社 API の Postman Collection を外部公開して社内外の開発者の生産性をあげていく

$
0
0

Postman ってなに

https://www.getpostman.com/products
一言で言うとリッチなユーザインターフェイスを搭載している HTTP クライアントです。

HTTP クライアントというと、例えば curl は皆さん1度は使ったことがあるであろうお馴染みですが、
特に API のテストや開発フェーズにおいて、ダイナミックなパラメーターを持つ多くのエンドポイントを行ったり来たりする際には、CLI よりも Postman のようなリッチな HTTP クライアントが便利なケースがあります。

また、最近では単なる HTTP クライアントとしての役割を超えて、

  • Postman Collections
  • Workspaces
  • API Mock server
  • Automated tests
  • Monitoring
  • Documentation

などの機能を備え、API 開発を行う上での統合開発環境を目指しており、Postman 自身も "The Only Complete API Development Environment (ADE)" と表現しています。

Screen Shot 2019-06-17 at 15.09.42.png

Postman Client の基本について

基本的な部分については色々な方々が紹介されているので、下記などをご参考に確認いただけると。

Postman Collections を使う (& 外部公開する)

今回は先に紹介した色々な Postman の機能の中でも、最も基本的かつすぐに活用がしやすい Postman Collections についてです。上記に貼った Postman Client のスクリーンショットで、左ペインに見えるフォルダ構造になっている部分、ここがいわゆる Collections です。

Screen Shot 2019-06-17 at 13.04.37.png

この例だと、3つの Collections が存在していて、それぞれにいくつの API (endpoint) が含まれているのかが分かります。Collections はフォルダを作るのと同じ要領で自分で好きに追加・管理することができ、いわゆる API の 雛形 を登録しておくことができます。

これによって、毎回 API のドキュメントページを見に行って、パスをコピーしてパラメーターをコピーして、、、みたいな作業をすることなく、Postman を開くだけですぐに必要な API を実行することができるようになります。
Collections では URI や Query parameters に変数 variables を使えるので、例えば URI パスに含まれる アカウントID や バージョン番号 など、任意の部分は全て変数として登録しておくことで、一括管理・変更が可能になります。登録時にこれらを上手く使うことで Collections のメンテナンスを行う必要がなくなります。

そんな Collections ですが、色々な使い方があると思います。

自分用としての Collections

個人的に Postman を利用している場合、例えば頻繁に利用するサービスの API を Collections にポチポチ登録しておき、使いたい時にすぐに使えるようにしておく、といった使い方が最もイメージしやすいと思います。もちろんテストやモニタリングなど用途は人それぞれあると思います。

コレボレーション用としての Collections

チームとして Postman を使っているような場合、作成した Collections を共有することで全員が最新の Collections を使うことができます。

また特に自社サービスで外部の開発者に向けて API を公開しているような場合、Postman Collections を公開することで例えば:

  • 自社のセールスエンジニアが API を気軽に使うことができるになる (営業先でのデモ)
  • API の公開ドキュメントに Postman Collections へのリンクを入れることで、一般開発者も Postman Collections を使って効率的に API を使った開発を進められる。

などのメリットが考えられます。
実は上記で貼ったスクリーンショットに含まれる3つの Collections は全て一般開発者向けに公開されている Postman Collections を import したものなのです。

API を使う開発者の立場になって考えると、公式にこういうツールが提供されるのはとても嬉しいですよね。

Collections を公開するには

Collections を公開する方法として大きく2つあります。1つ目は 自分で作成した Collections をエクスポートして、生成される JSON ファイルを 共有、GitHub などで公開する方法、2つ目は Postman の機能を使って Collections を外部に公開し、誰でもアクセスができる共有用の URL を生成する方法です。

1. JSON ファイルを共有・公開する方法 (△)

対象の Collections を選択し、Export するだけです。
Screen Shot 2019-06-17 at 13.44.50.png

デメリットとして、Collections に何か新しい変更を加えた場合、再度ファイルを生成して共有・公開しないといけません。

2. Collections 用の共有リンクを発行する (◎)

もし作成した Collections を幅広いオーディエンスに向けて公開しようと考えている場合はこちらの方法の方がオススメです。

まず対象の Collections を選択し、Share Collection をクリックします。
Screen Shot 2019-06-17 at 13.49.14.png

次に Get link タブへ移動し、Get Link ボタンをクリックし、共有リンクを発行します。
Screen Shot 2019-06-17 at 13.49.23.png

正しく発行が終わると下記のように URL が表示されます。
Screen Shot 2019-06-17 at 13.49.54.png

この URL に直接アクセスすると、先程 1. の方法で生成した JSON ファイルと同じ内容が見えると思います。
つまりこの方法のメリットは、新しい変更を Push 型ではなく Pull 型でユーザーへ提供できる点でしょう。

注意点

この URL は一度発行されると、削除して再生成しない限り変わることはありません。
上記のスクリーンショットの Update Link は、URL を再生成するという意味ではなく、URL に紐づいている Collections の内容を最新のものに更新する、という意味です。

つまり何が言いたいかというと、URL が発行されると、この URL には "その時点" での Collection のスナップショットがコピーされ紐付けられます。リンクを発行後に Collection を更新しても、明示的にこの Update Link を実行しない限り変更は反映されません。分かりにくい。。。

Run in Postman ボタンを使う

これまで Collection を共有する方法を紹介してきました。URL での共有が可能なことが分かりましたが、これでは結局ユーザーが自分でファイルに保存して import という面倒なステップを踏むことになります。
Postman が提供している Embed 機能を使うと、Web ページ上に設置したボタンをユーザーが押すだけで当該 Collection をユーザーの Postman Client に直接 import でき、そうした煩わしさから解消されます。

※↓は実際に押せるボタンです。

Run in Postman

例えば Twitter Ads API の API リファレンスページには各ページにこの Run in Postman ボタンが設定されていて、ユーザーがここからすぐに Collection を import することができるようになっています。
https://developer.twitter.com/en/docs/ads/analytics/api-reference/active-entities
Screen Shot 2019-06-10 at 17.15.03.png

ボタンの作り方

先程のように、対象の Collection から Share Collection をクリックし、今回は Embed タブを開きます。

Screen Shot 2019-06-17 at 14.34.53.png

先程のステップで既に共有リンクは生成してあるので、上記のように、HTML or Markdown 形式を選択するだけで、すぐに設置できる Run in Postman ボタンのコードスニペットが表示されます。これを自社のサイト上で使うことができます。ここでも Update Link ボタンの意味は先程説明した通りです。

Collection を公開・管理する上での注意点、その他

Workspace を分けた方がいい

Collection を作って上記の手順で一般公開した後、例えば誤って Collection を手元の Postman client から削除してしまった場合、公開されている Collection やリンクも跡形もなく闇に葬られてしまいます。
普段使いの Workspaceは汚れがちです。公開用の Collection を管理するためだけの神聖な Workspace を別途作っておいて、公開した Collection はそのクリーンな Workspace 内でのみメンテナンスするべきでしょう。

参考: Intro to Workspaces

Fork / Merge 機能を積極的に使う

外部公開用の Collection のメンテナンス時に誤った変更が混入してしまうと大変です。
Postman では git のような感覚で、既存の Collection からまず Fork されたコピーの Collection を作成し、そこに対して変更を適用、Merge 前にブラウザ上で変更一覧をグラフィカルに表示した上で最終的に Merge する、というフローを取ることが可能です。

参考: Version Control for Collections

Environment を上手く使う

序盤に説明しましたが、Collections では URI や Query parameters に 変数 variables を使えるようになっています。Workspace 毎に設定可能な Environment には任意の変数を設定可能なので、ここに token などの認証情報はもちろん、URI に含まれる API のバージョン番号、アカウント ID などを変数として登録することで、Collection のメンテナンス性がグッと上がります。

参考: Intro to environments and globals

Collection データの更新は Postman API からも可能

これまでの例では全て Postman client を使って GUI 上から変更を加え、Collection を管理していくという方法についてでしたが、場合によってはとても手作業ではカバーできない量の変更が一度に必要になることがあるかもしれません (大量の文字列置換など)。
そういった場合に、1つのトリックとして、JSON 形式で export した Collection ファイルを使って一括変換を行い、それを POST body として Postman API から投げて、公開済み Collection の内容を GUI を経由することなくまるっと変更することができます。

参考: Postman API - Update Collection

Collection を複数人で共同管理するには有料プラン

Postman では作成した Workspace に他の人を invite して Collection を共同管理することができます。
ただし無料プランでは招待することができず、有料プランが必須となります。1人でやる分には一切課金なく、今回紹介した全ての作業を行えます。

一度 import した Collection を最新バージョンに "Update" する機能はない

公開された Collection を使うユーザー側の視点で考えます。管理者が新しい変更を加えて Collection を公開したとしても、Postman は特にアップデートの通知などをしてくれるわけではありません。ユーザーはもう一度 Collection を import する必要があります。

Run in Postman ボタンは、deep linking に対応していない

ボタンはとても便利ですが、特定のサブフォルダだけを import させる、といったことは出来ません。Collection 全体がインストールされます。また、ユーザーがボタンを押した際に既に Collection が import されているのかどうかを判断してくれないため、既に Collection を import 済みであっても毎回 import を問われます。

WordPress REST API oauth2 Authorization code を Postman で取得する方法

$
0
0

GUIで簡単に取得できるのですが、しょうもないことでドハマリしました。

正しい手順

oauth プラグインをダウンロード
https://ja.wordpress.org/plugins/oauth2-provider/
有効化する
image.png

settings

image.png

OAuth Server Enabled にチェック

サーバーステータス

サーバーステータスが全部正常かチェック
黄色の noticeで動かない場合があります。
image.png

Add New Client

image.png

以下のように設定したとしても、無理だった。
image.png

image.png

ハマりポイント

Client 名wordpress側と postman 側を同じにする。

image.png
Postman の Token name と WordPress の client id は同じにしてください。
同じにしなくても動くはずですが、エラーを起こす場合があります。

wordpressをRESTにする

image.png
正しくログインできるとこの画面が表示されますが、できませんでした。

原因は、
image.png

初期設定だとパーマリンク設定が基本でGETクエリで投稿を判定するので、RESTじゃないからRESTAPIが動かないという罠です。 投稿名で設定しましょう。

英語のyoutubeビデオを見つけるまでは、デフォルトでRESTAPIはWordPress core に統合されているから有効と聞いていたので、有効になってないとは露程にも思いませんでした。

curl コマンド よく使う時のオプションなどメモ

$
0
0

curlとは

  • httpプロトコルだけでなく、FTPやTELNETなど多くのプロトコルに対応している。 ### curl
  • オプションなしだとGETメソッドで取得する

curl -I

  • httpヘッダーのレスポンス情報を確認できる

curl -X POST -H 'hoge' -d 'foo'

  • httpのpostメソッドの場合は-Xオプションを使用する

  • httpのヘッダー情報を指定する場合は-Hオプションを使用する

  • httpのbodyのデータを指定する場合は-dataオプションを使用する
    例)“aaa=hoge&bbb=foo&ccc=bar”

  • json形式のデータを指定する場合は-dオプションを使用する
    例)'{"data":{"hoge":"aaaaaaaaaaa","foo":0,"bar":"123456789"}}'

おまけ

私はcurlの他にpostmanというツールをよく使います。
GUIで直感的なので分かりやすいです。
名前は「postman」と言っていますが
POSTだけでなく、GET,PUT,DELETEなどある程度のメソッドは対応しているので
httpプロトコルベースのWebアプリ系の確認には便利です。

chromeの拡張機能もあればアプリ版もあります。
https://chrome.google.com/webstore/detail/postman/fhbjgbiflinjbdggehcddcbncdddomop?hl=ja
https://www.getpostman.com/downloads/

postmanでPUT,DELETE送信したものを取得できない時

$
0
0

laravelでUpdate,destroyを行う時、送信形式を「form-data」にしていると、
php artisan route:listで表示されているルーティングには、

$ php artisan route:list

 PUT|PATCH | api/user/{app_user} | user.update  | App\Http\Controllers\UserController@update  | api 

このようにHTTPメソッドは、「PUT|PATCH」と書かれているが、PostManなどで、PUTリクエストを送信すると、リクエストの中身が取得できない。

(まあ、laravelだけに限らないかもしれないが、、、、)

原因

送信形式を「form-data」にしていることが原因。
HTMLのformがPUTとPATCHをサポートしていないため,form-dataでPUTやDELETEを送っても中身を取得できない。

対策

対策は二つ。
1,HTTPメソッドはPostで,bodyパラメーターで、[_method:PUT]を指定する
これは送信形式はform-dataのママでOK

2,内容をjsonで送る
そもそもform-dataでなければいいので、jsonで送信する。
そうすると、PUTやDELETEでも通る

スクリーンショット 2019-07-02 12.41.49.png


【Postman】Getメソッドで配列を渡す時にどう書くか

$
0
0

経緯

Postmanを使うとき、
Postする際は配列をそのままJSONで渡すだけでいいが、
Getの場合は配列をどう渡せばいいのかよくわからない。

方法

hoge: [10, 3] を渡す場合

  • KEYに hoge[] と書く
  • valueに配列内の要素を書く
  • 上記を配列内の要素数分繰り返す

画像

postman

連想配列

hoge: { piyo: [10, 3]} を渡す場合下記のようになる

KEY VALUE
hoge[piyo][] 10
hoge[piyo][] 3

参考

RailsでGETメソッドのクエリストリングで配列を渡したい時にどうするか

動的サイトを全力でcheerioでスクレイピングしてみた

$
0
0

はじめに

「なんかWebスクレイピングでPuppeteerばかり注目されてる気がするけどcheerioも使えるんだからな」
ということを伝えたくて今回は動的サイトをあえてPuppeteerやSeleniumを使わずにWebスクレイピングしてみた。

ただ結論から言えば今回のサイトのような場合はpuppeteerを使った方が圧倒的に簡単で確実である

また、本投稿で登場するサイトはあくまで例として実際にスクレイピングを行なったサイトの構成を元に作成しております。
本プログラムをコピペしても動作しませんのでご注意ください。

今回のチャレンジ

今回は以下のようなニュースサイトでWebスクレイピングを挑戦してみた。

website_image.png

ゴール

ゴールは本記事の趣旨を簡単に理解できるようにするため「2019年に出稿された記事全てを取得する」とする

事前調査

分析したところ、サイトの仕様は以下のようになっていることがわかった。
- トップページhttps://www.newsexample.comより検索を行うことができる
- 各セレクタがURLのパラメータとなり、Searchボタンを押すとhttps://www.newsexample.com/【Year】/【Month】/【Country】/【Category】といった感じでリクエストが送信される
- 条件に合致するニュースが検索結果に表示される。検索結果が0件の場合は「検索結果が見つかりませんでした」と表示される。今回はタイトル, 日付, 本文をここで取得する
- 各セレクタ内のデータはajax通信により選択肢が動的に変化する。また、ニュースが存在しない条件は選択肢に表示されない。例えばYearを2019に指定した際、12月のニュースが存在していなければMonthを12に指定することはできない。

ポイント:検索条件をどのように取得するか

検索結果を表示するページ自体は簡単にスクレイピングできそうだが、問題はその前のプロセスである。
どのようにして動的に変化する検索条件を取得するかである。

というのもcheerioはHTML形式でページを取得してjQueryのように要素を指定することができるライブラリであって、ページ上のDOM操作をすることはできない。
もしセレクタ内のアイテムが静的であればDOM要素を分析するだけで検索条件を取得することができたが、今回のサイトは左のセレクタから選択していくことでajax通信が発生し、次のセレクタ内のアイテムが決定される。

また、国やテーマにおいては実際に通信しないとどのような選択肢があるのか検討つかないので検索条件を推測することもできない。

つまり何らかの方法で選択肢のデータを取得しなければならない。

アプローチ

ざっくりまとめるとこんな感じ

scraping.js
const year = 2019

// Monthの選択肢を取得
const months = getMonths(year);
for(let month of months) {

    // Countryの選択肢を取得
    const countries = getCountries(year, month);
    for(let country of countries) {

        // Categoryの選択肢を取得
        const categories = getCategories(year, month, country);
        for(let category of categories) {

            // 検索結果(タイトル, 日付, 本文)を取得
            const result = getResults(year, month, country, category)
            console.log(result.title, result.date, result.body)
        }
    }
}

多重ループを繰り返して選択肢を取得し、実行結果をひとつずつ出力してやるといった感じ。
あとはそれぞれの関数を実装してやればいけるだろう。
そのためにまずは実際に行われているAjax通信を解析してやらねばならない。

手順1 : Ajax通信を解析する

まずは実際に行われる通信を解析して必要な情報を割り出す必要がある。
私は実際に以下の手順で行った。

Google Developer Toolsを使ってajax通信のリクエストを解析

まずはGoogle Developer ToolsのNetworkを開く。すると、通信履歴が表示される。
履歴をクリアしておき、ajax通信を発生させると、図のようにNetwork内にあらたに履歴が表示され、通信が行われたことがわかる。
今回はセレクタを開いて選択肢を選択することで発生する。
はじめはYearセレクタを選択してMonthが取得されるまでの通信を確認する。

network1.PNG

getMonthListをクリックしてHeader情報を開くと図のような情報が表示される。

network.PNG

…なるほど、POSTで通信しているのか。
他にもRequest URLやcookie情報、Request Payloadより送信したパラメータなどがわかる。

Postmanを使ってリクエスト送信に必要な情報を確認

手順1で得られた情報をもとにPostmanを使って通信に必要なパラメータを確認していく。
公式サイト https://www.getpostman.com/ よりダウンロードしたらpostmanを起動。

今回はPOSTで通信しているのでPOSTにする。
HeadersをクリックしてそこにContent-Type : application/jsonを追加。
BodyにはRequest Payloadの内容をそのままペーストすればいいのかな?
とりあえずこれでSendをクリックしてみる。

image.png

すると以下の実行結果が出力された。

[
    "January",
    "February",
    "March",
    "April",
    "May",
    "June",
    "July",
]

ひとまずこれでデータは取得できることが分かった。
パラメーター"field": "news_number"の意味がよくわかっていないが、固有パラメーターなのだろうと推測。
さすがにAPI側で定められている条件などはわからないので、具体的に何を意味しているのかまで把握することは難しい...
"field": "year"はセレクタより選択した年が代入されているので、このパラメータを変更すれば任意の年の情報が取得できる。

手順2: 同様に国、カテゴリーに対しても解析する

Monthを解析したときと同様の手順でCountryCategoryの取得に必要なパラメータを確認していく。

手順3: request-promiseを用いて実装

解析した情報をもとにそれぞれgetMonths(year), getCountries(year, month), getCategories(year, month, country)を実装する。
実装は以下のようになる。

scraping.js
const rp = require('request-promise');


const filterByNewsNumber = {
    filters: [{
       field: "news_number",
       value: 5,400,
       condition_type: "eq"
    }]
};

let filterByYear = [];
let filterByMonth = [];
let filterByCountry = [];

// Monthセレクタの選択肢を取得する
async function getMonths(year) {
   fileterByYear = {
        filters: [{
            field: "year",
            value: year,
            condition_type: "eq"
        }]
    };
    const filterGroups = [].concat(filterByNewsNumber, fileterByYear);
    // Request Payloadと同じパラメータになるようにする
    let newRequest = {
        "searchCriteria": {
            "filterGroups": filterGroups
        }
    };

    let option = {
        uri: baseUrl + "/rest/monthSearch/getMonthList",
        method : "post",
        body : newRequest,
        json : true
    }

    // Monthリストを返す
    return rp(option).catch( () => console.log("取得できませんでした"))
}

// Countryセレクタの選択肢を取得
async function getCountries(year, month) {
   fileterByMonth = {
        filters: [{
            field: "month",
            value: month,
            condition_type: "eq"
        }]
    };
    const filterGroups = [].concat(filterByNewsNumber, fileterByYear, fileterByMonth);
    // Request Payloadと同じパラメータになるようにする
    let newRequest = {
        "searchCriteria": {
            "filterGroups": filterGroups
        }
    };

    let option = {
        uri: baseUrl + "/rest/countrySearch/getCountryList",
        method : "post",
        body : newRequest,
        json : true
    }
    // Countryリストを返す
    return rp(option).catch( () => console.log("取得できませんでした"))
}

// Categoryセレクタの選択肢を取得
async function getCategories(year, month, country) {
   fileterByCountry = {
        filters: [{
            field: "country",
            value: country,
            condition_type: "eq"
        }]
    };
    const filterGroups = [].concat(filterByNewsNumber, fileterByYear, fileterByMonth, filterByCountry);
    // Request Payloadと同じパラメータになるようにする
    let newRequest = {
        "searchCriteria": {
            "filterGroups": filterGroups
        }
    };

    let option = {
        uri: baseUrl + "/rest/countrySearch/getCountryList",
        method : "post",
        body : newRequest,
        json : true
    }

    // Categoryリストを返す
    return rp(option).catch( () => console.log("取得できませんでした"))
}

手順4 : URLを生成してcheerioでスクレイピング

これであとはURLを生成してcheerioを使って検索結果の画面を取得しに行けばいいだけ。
そのためにgetResultsを実装する。

scraping.js
const cheerio = require('cheerio');

async function getResult(year, month, country, category) {
    const url = `https://www.newsexample.com/$(year)/$(Month)/$(Country)/$(Category)`;
    // 記事一覧画面のHTMLを取得する
    html = await rp(url);
    $ = cheerio.load(html);

    // 情報を取得するためにそれぞれのhtml要素を指定する
    const title = $('#title');
    const date = $('#date');
    const context = $('#context');

    const data = {
       "title" : title,
       "date" : date,
       "body" : context,
    }
    return data;  

}

手順5 : 逐次的に実行されるように修正する

ここまでスクレイピングに必要な処理を記載してきたが、このまま実行しようとするとそれぞれの処理が非同期で行われてしまうため、エラーが発生する。
全ての処理が逐次的に行われるように以下のように修正してまとめる。

scraping.js
const cheerio = require('cheerio');
const rp = require('request-promise');

const filterByNewsNumber = {
    filters: [{
       field: "news_number",
       value: 5,400,
       condition_type: "eq"
    }]
};
let filterByYear = [];
let filterByMonth = [];
let filterByCountry = [];

const year = 2019;

async function main(){ 
   // Monthの選択肢を取得
   const months = getMonths(year);
   for(let month of months) {

        // Countryの選択肢を取得
        const countries = await getCountries(year, month);
        for(let country of countries) {

            // Categoryの選択肢を取得
            const categories = await getCategories(year, month, country);
            for(let category of categories) {

                // 検索結果(タイトル, 日付, 本文)を取得
                const result = await getResults(year, month, country, category)
                console.log(result.title, result.date, result.body)
            }
        }
    }
}

// Monthセレクタの選択肢を取得する
async function getMonths(year) {
   fileterByYear = {
        filters: [{
            field: "year",
            value: year,
            condition_type: "eq"
        }]
    };
    const filterGroups = [].concat(filterByNewsNumber, fileterByYear);
    // Request Payloadと同じパラメータになるようにする
    let newRequest = {
        "searchCriteria": {
            "filterGroups": filterGroups
        }
    };

    let option = {
        uri: baseUrl + "/rest/monthSearch/getMonthList",
        method : "post",
        body : newRequest,
        json : true
    }

    // Monthリストを返す
    return rp(option).catch( () => console.log("取得できませんでした"))
}

// Countryセレクタの選択肢を取得
async function getCountries(year, month) {
   fileterByMonth = {
        filters: [{
            field: "month",
            value: month,
            condition_type: "eq"
        }]
    };
    const filterGroups = [].concat(filterByNewsNumber, fileterByYear, fileterByMonth);
    // Request Payloadと同じパラメータになるようにする
    let newRequest = {
        "searchCriteria": {
            "filterGroups": filterGroups
        }
    };

    let option = {
        uri: baseUrl + "/rest/countrySearch/getCountryList",
        method : "post",
        body : newRequest,
        json : true
    }
    // Countryリストを返す
    return rp(option).catch( () => console.log("取得できませんでした"))
}

// Categoryセレクタの選択肢を取得
async function getCategories(year, month, country) {
   fileterByCountry = {
        filters: [{
            field: "country",
            value: country,
            condition_type: "eq"
        }]
    };
    const filterGroups = [].concat(filterByNewsNumber, fileterByYear, fileterByMonth, filterByCountry);
    // Request Payloadと同じパラメータになるようにする
    let newRequest = {
        "searchCriteria": {
            "filterGroups": filterGroups
        }
    };

    let option = {
        uri: baseUrl + "/rest/countrySearch/getCountryList",
        method : "post",
        body : newRequest,
        json : true
    }

    // Categoryリストを返す
    return rp(option).catch( () => console.log("取得できませんでした"))
}
async function getResult(year, month, country, category) {
    const url = `https://www.newsexample.com/$(year)/$(Month)/$(Country)/$(Category)`;
    // 記事一覧画面のHTMLを取得する
    html = await rp(url);
    $ = cheerio.load(html);

    // 情報を取得するためにそれぞれのhtml要素を指定する
    const title = $('#title');
    const date = $('#date');
    const context = $('#context');

    const data = {
       "title" : title,
       "date" : date,
       "body" : context,
    }
    return data;  

}

Asyncでmain関数を作成し、AwaitでgetMonths, getCountries, getCategories, getResultを順番に処理させることで正しく動作する。

まとめ

かなり荒技ではあったが動的サイトでもpuppeteerを使わずに、Networkからajaxを解析してWebスクレイピングすることができた。
また、HTTP通信を解析することにもなり非常に面白かった。
とはいえ非常に手間がかかるし、何より今回のようにPostリクエスト内に含まれているパラメータの意味がわからないということもあるので特に理由がなければ今後動的サイトをスクレイピングする際はpupeteerを採用しようと思う。

PostmanとNewmanを組み合わせて、CI/CDに組み込むREST APIの自動テストを作ろう!

$
0
0

はじめに

REST APIのテストツール、テストが書きやすくてCLIベースで動くものを探していたんですが、PostmanNewmanの組み合わせが神だったのでご紹介です。
これらを使うとざっくりこんなことが出来ます。

  1. REST API実行する
  2. 実行したAPIのresponseをチェックするテストスクリプトを作る
  3. 作ったテストスクリプトをjsonファイルにexport
  4. CI/CDでこのスクリプトを実行するようjenkinsジョブを作る

特徴で興味を持った方、ざっくり使い方を見ていってください。

Postman

Postmanは、APIを持つソフトウェアの開発を簡単にするためのツールです。アイコンかわいい(大事

postman

出来ること

  • APIテストを作ることができる
    • UIでREST APIの実行確認が出来る。
      • headerやbodyも入力可能。量が多いのでUIベースの方が楽だったりしますよね
    • 実行したAPIのresponseをチェックするテストを比較的簡単に書ける
      • テストコードの書き方に戸惑うもんですが、サンプルコードが出てくるのでまあやれるでしょう
  • 作ったテストをjsonファイルに出力できる
    • 共有らくちん

使い方

準備

まずはGet startedからインストーラーをダウンロードしてインストールしてください。Windows/Mac OS/Linuxサポートしてます。
インストールしたツールを起動したらまずはログイン。アカウントを作成するか、Googleアカウントを利用することが出来ます。

login.png

APIテストを作る

ログインしたらテストスクリプトを作成しましょう。スクリプトはCollectionと呼ばれる単位で作成し、そのCollectionの中にAPIを記載していきます。
Collection > APIsの構成。

APIDefine.png

Add requests もしくはNewからRequestを追加・選択した状態がこれ。Query, Header, Bodyや、Authorization等細かなパラメータを指定できるので、REST APIツールとしても満足できます。

API check.png

さて、テストスクリプトを作るには結果をチェックするテストスクリプトがいりますね。Testsタブで何やら書けそう。でもどうすればいいんだろう。。。
と困ったら右のボックスに試験から似たものをクリックしてみましょう。そのコードがTestsに反映されるので、後は編集するだけ。割と楽ちんですね
pushjson.png

このテスト、使い勝手を良くするためには例えば環境変数からIPを取ってきたり、レスポンスの内容を次のテストで利用したりなんていうことも出来るようです。安心
Postmanを使ってWeb APIにアクセスする その2

作り終えたら実行。Collection横の再生ボタンを押し、Runでテスト実行が出来ます。
run.png

環境変数を使って値を使いまわす

Postmanでは、環境変数を設定することで環境による切り替えが可能です。
また、TestScriptの中で環境設定の変更も可能なため、API実行結果を別のAPIで利用することが出来ます。

右側の歯車マークを押すとこのような画面が出てきて、環境変数を設定できます。こちらはテストケースと別にファイルをエクスポートすることが可能です。

環境変数.png

値はkey/value形式で保存。

permission.png

作成した環境変数は、右上のプルダウンによって指定することが可能で、Requestパラメータに対しては{{access_token}}のように{{}}でくくることで利用することが出来ます。

TestScriptsの中で使う場合は、pm.environment.get("XXX");, pm.environment.set("XXX", value);という使い方をします。

サンプルとしてQiitaAPIを叩くスクリプトを貼っておきます(テスト感はないですが)。興味がある方は開いてみてください。
Testcase.json
{
    "info": {
        "_postman_id": "f87211e1-edf5-4bce-9305-bfab5ce7e93b",
        "name": "QiitaTest",
        "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json"
    },
    "item": [
        {
            "name": "QiitaItemGet",
            "event": [
                {
                    "listen": "test",
                    "script": {
                        "id": "481d2d73-4dc5-4fd4-befb-6c3495bfc0af",
                        "exec": [
                            "",
                            "pm.test(\"Status code is 200\", function () {",
                            "    pm.response.to.have.status(200);",
                            "});",
                            "",
                            "pm.test(\"Reponse number check\", function () {",
                            "    //get data from env",
                            "    var value = pm.environment.get(\"env_val_result\");",
                            "",
                            "    //json parse",
                            "    var jsonData = pm.response.json();",
                            "    pm.expect(String(jsonData.length)).to.eql(value)",
                            "})",
                            "",
                            "pm.test(\"Reponse body check\", function () {",
                            "    var jsonData = pm.response.json();",
                            "    for (var i = 0; i < 2; i ++ ){",
                            "        pm.expect(jsonData[i][\"group\"] == null).to.true",
                            "    }",
                            "});",
                            ""
                        ],
                        "type": "text/javascript"
                    }
                }
            ],
            "request": {
                "auth": {
                    "type": "noauth"
                },
                "method": "GET",
                "header": [
                    {
                        "key": "Authorization",
                        "value": "Bearer {{access_token}}",
                        "type": "text"
                    }
                ],
                "url": {
                    "raw": "https://qiita.com/api/v2/authenticated_user/items?page=1&per_page={{env_val_result}}",
                    "protocol": "https",
                    "host": [
                        "qiita",
                        "com"
                    ],
                    "path": [
                        "api",
                        "v2",
                        "authenticated_user",
                        "items"
                    ],
                    "query": [
                        {
                            "key": "page",
                            "value": "1"
                        },
                        {
                            "key": "per_page",
                            "value": "{{env_val_result}}"
                        }
                    ]
                }
            },
            "response": []
        }
    ]
}

access_tokenを正しいものにしないとエラーとなります。

TestEnvironment.json
{
    "id": "df3993ba-1827-47a9-8ef3-b33530c9ff05",
    "name": "QiitaSample",
    "values": [
        {
            "key": "access_token",
            "value": "aaaaaaaa",
            "enabled": true
        },
        {
            "key": "env_val_result",
            "value": "2",
            "enabled": true
        }
    ],
    "_postman_variable_scope": "environment",
    "_postman_exported_at": "2019-08-08T14:48:36.520Z",
    "_postman_exported_using": "Postman/7.3.6"
}

作ったテストをjsonファイルに出力

Collectionの...をクリックし、Exportを選択するとjsonファイルが出力できます。

Export.png

同じく設定した環境変数ファイルもjsonファイルに出力することが出来ます。

Newman

出来ること

  • postmanで作ったjsonファイルをCLIで実行できる
    • UIベーステストの欠点、CI/CDに組み込みにくい問題を完全解決!

使い方

npmでnewmanをインストールします。

npm install -g newman

後はPostmanからexportしたjsonファイルを引数に指定するだけ。

newman run exported_json_file.json

Postmanで設定した環境変数ファイルは -e オプションで指定します。

newman run -e exported_environment.json exported_json_file.json

newman公式より

セットで出来ること

  1. PostmanでUIベースのAPIテスト(Collection)を作る。
  2. 作ったテストをjsonファイルで出力し保存
  3. newman run exported_json_file.json でテストを実行

というわけで、編集はUI、実行はCLIという形での運用が良さそうです。

追加の補足ツール

swagger2-to-postmanというツールで、Postmanにimport出来るjsonファイルを出力することが出来ます。
使い勝手が悪いので、swagger から postman の設定ファイルを作成し自動 API テストを行うという記事のコードをほぼそのまま流用。
npm install出来るようにする必要もあったのでswagger2-to-postman-sampleにリポジトリ化しました。
以下コマンドでファイル出力できます。

git clone https://github.com/developer-kikikaikai/swagger2-to-postman-sample.git
cd swagger2-to-postman-sample
npm install
./cli.js -i input.json  > output.json

Bodyのデータがjsonフォーマットではなく"Pet to add to the store"というDescriptionが書いてあるだけという状態だったりしますが、忘れやすいヘッダーも設定してくれてるのでそれなりに使い勝手は良さそうです。

最後に

API開発者の方には定番と思われる神ツールを紹介しました。UIのテストツールはCI/CDに組み込みにくいという思い込みがあったためスルーしてきたんですが、こんな組み合わせ方があったとは。
UIはこの辺が困るよな~っていうかゆい所に手が届く、素晴らしいツールでした。皆さん、これで楽しいテストライフを!

参考

公式:
Postman
Newman
swagger2-to-postman-sample
OpenAPI-Specification

メイン記事の参考:
PostmanとNewmanを使って複数のAPIを連続して実行させる
swagger から postman の設定ファイルを作成し自動 API テストを行う

PostmanでParamsに設定した+記号が空白になってしまう場合の対処法

Postman で HTML の要素値・属性値を取得する

$
0
0

概要

Postman の Tests タブで JavaScript を記述できます。
ここでアクセスしたWebページのHTMLから要素値・属性値を取得することができます。

例: example.com のページ要素の検証

Postman の URL を GET https://example.com に設定し、Tests タブに下記を入力します。

Testsタブ
const $html = cheerio(pm.response.text());

pm.test('Example.com is working.', function() {
  pm.expect($html.find('h1').text()).to.equal('Example Domain');
  pm.expect($html.find('a').attr('href')).to.equal('http://www.iana.org/domains/example');
});

cheerio は jQuery ライクにDOMを扱えるライブラリです。
 上の例では https://example.com<h1> の値の検証と <a>href 属性の値を検証しています。

Send ボタンを押すとレスポンスが帰ってきて、テスト結果が表示されます。
テスト結果はページした半分の Test Results タブに表示されます。

Postmanテストケースの書き方

$
0
0
  • Httpステータスコードの確認

    • tests["レスポンスコードが200であること"] = responseCode.code === 200;
  • レスポンスデータをJSONにパースする

    • var jsonData = JSON.parse(responseBody);
  • コンソールログ出力

    • console.log("ログコメント");
  • Postman環境変数に格納する

    • postman.setEnvironmentVariable("user_id", jsonData.userid);
  • レスポンスを丸ごと比較

    pm.test("レスポンス確認", function () {
        pm.expect(jsonData).to.eql(
        {
            "code": "ERROR",
            "message": "パラメータが不正です。",
            "message_detail": "user_idが未設定です。"
        }
            );
    });
    

便利なオンラインAPIリクエストビルダー、Postwomanの紹介

$
0
0

ついにAPI界にもジェンダーの波が!

というわけでも特になく、単にPostmanフォロアーだからだと思われます。

Postwomanってなに?

Liyas Thomasによって開発された、APIリクエストビルダーです。
平たく言うとオープンソース簡易版Postmanです。

Postmanってなに?

Postmanとは、Qiitaにも幾つか記事がありますが、開発中のAPIを叩いてテストしたりするのに便利な開発ツールです。
ただソースがクローズドだったり一部有料だったり、あとはなんといってもインストール形式なので導入が面倒です。
昔はChromeエクステンションもあったらしいのですが、現在はもう見つかりません。

本格的に重厚長大なアプリを作る際のテストには適しているかもしれませんが、ちょっと数個のAPIを試したいだけなんだ、なんてときにはもっと気軽に使いたいですね。
そんなときはPostwomanの出番です。

Postwomanを使ってみる

Webサイトにアクセス。
Method、URL、Pathを設定してSendボタン。
それだけでリクエストを送って、返ってきたレスポンスが表示されます。

01.png

すごい簡単。

リクエストメソッドはGET/HEAD/POST/PUT/DELETE/OPTIONS/PATCHと各種対応。
BASIC認証とAuthorization: Bearerによる認証にも対応しているので、開発中で閉じてるサイト内にもアクセス可能。
非常に簡単にテストが行えますね。

WebSocket

なぜかWebSocketも使えます。
デフォルトではあらゆるメッセージを鸚鵡返しにするwss://echo.websocket.orgが指定されているので簡単にお試しができます。
WebSocketサーバ実装する人がこのWebアプリを使う場面というのはあんまり想像できませんが。

見た目を変えよう

デフォルトだと昔のハッカー気取りサイトみたいな黒緑です。
というかなんでアイコンがこんな可愛くないグレイなんですかね。

右上の歯車ボタンをクリックすると、背景色と一部文字色を変更可能です。

02.png

残念ながら任意の文字色を入れたりはできないようですが、まあそこまでもカスタマイズが必要なサービスでもないでしょう。

何度も同じリクエストを送りたい

Historyに履歴が残ります。
鉛筆みたいなボタンを押すとその履歴が反映されるので、再送も簡単です。

オンラインだと機密情報が…

GitHubcloneしてnpm installしてnpm run devしてlocalhost:3000にアクセスするんだよ。

PWAもあるぞ

一番右下のボタンからインストールできます。

03.png

宗教上の理由でインストールしていないので詳細は不明。

感想

本格的にテストを書くならやはり専用テストツールの導入が必要になると思いますが、とりあえずちょっとAPIの動作を試してみたいだけなんだ的な用途には最適だと思います。
使い方も見たらわかるレベルですからね。

GitHubでは開発の手伝いを募集しているようです。
またコーヒーも求めているので、使って気に入った人はぜひ投げ銭を送ってあげましょう。


PostmanでAPIのレスポンスが正しいかテストする

$
0
0

Postman

Postman | The Collaboration Platform for API Development

そもそもPostmanとは?

APIの動作を確認するツール、、だけに留まらず今や認証、テスト、ドキュメント作成、バージョン管理など幅広く活用できる便利なツール&サービスです。:sparkles:

Postmanでテストする

Test examples | Postman Learning Center

Postmanではレスポンスの値をテストする事ができます。
Postmanを開いて Params, Authorization... などがあるタブの左端に Tests というタブがあるので
そちらにテストを書く事ができます。
2.png

試しに簡単なテストを書いてみる

試しに、GithubAPIを使ってリポジトリのブランチ一覧を取得してみます。
GitHub API v3 | GitHub Developer Guide

今回はrails/railsのブランチ一覧を取得するAPIをPostmanでリクエストしてみます。

https://api.github.com/repos/rails/rails/branches

↑をPostmanに設定し「Send」を押すとズラズラっとブランチが取得できるかと思います :ok_hand:
3.png

レスポンスとしては以下の様なフォーマットで返って来ます。(※ 2019年9月16日時点)

[
    {
        "name": "1-2-stable",
        "commit": {
            "sha": "5b3f7563ae1b4a7160fda7fe34240d40c5777dcd",
            "url": "https://api.github.com/repos/rails/rails/commits/5b3f7563ae1b4a7160fda7fe34240d40c5777dcd"
        },
        "protected": true
    },
    {
        "name": "2-0-stable",
        "commit": {
            "sha": "81d828a14c82b882e31612431a56f830bdc1076f",
            "url": "https://api.github.com/repos/rails/rails/commits/81d828a14c82b882e31612431a56f830bdc1076f"
        },
        "protected": true
    },
    ...
]

今回はテストとして
・ ステータス200でレスポンスが返ってくる事
・ ↑のjson schemaで返ってくる事
のテストを書いてみます。 :heavy_check_mark:

ステータス200でレスポンスが返ってくる事

こちらは簡単で以下の様に記述します。

pm.test("Status code is 200", function () {
    pm.response.to.have.status(200);
});

↑を「Tests」タブ内に書いて、「Send」を押すと下の「Test Results」に
テスト結果が表示されます。
4.png

失敗すると赤くなって、失敗理由が表示されます。
5.png

json schemaのチェック

Postmanではjosn schemaのチェックに「tv4」と「ajv」が使用できます。

今回は、「tv4」を使ってチェックを行いたいと思います。

let schema = {
    "title": "branches",
    "type": "array",
    "properties": {
        "name": {
            "type": "string"
        },
        "commit": {
            "type": "object",
            "properties": {
                "sha": {
                    "type": "string"
                },
                "url": {
                    "type": "string"
                }
            }
        },
        "protected": {
            "type": "boolean"
        }
    }
};

pm.test("Body matches", function () {
    var jsonData = pm.response.json();
    pm.expect(tv4.validate(jsonData, scheme)).to.be.true;
});

↑やっている事はレスポンスのjson schemaを事前に定義して let schema
実際のレスポンスと合っているかチェックしています。
※ 定義に関しての詳細はこちらを参照

「Tests」に追記し、「Send」を実行しテスト結果がグリーンであれば成功です :sparkles:

参考URL

「マッチングが成立しました!」通知を見てニタニタしたい。(FirebaseでAndroidアプリに通知を送るまで)

$
0
0

概要・作るもの

「マッチングが成立しました!」という通知が届くと、一瞬で幸福感に浸れますよね?
とはいえ、なかなか通知が来ないので、Androidアプリを作り、自分で自分に通知を送っちゃいましょう。
screen.png

【使用する技術】

  • Firebase Cloud Messaging (FCM)
  • Android Studio(Java : Androidアプリ開発)
  • Postman, cURLコマンド, Node.js

躓いた箇所の自分用メモとして、また、他の方の参考にもなれば幸いです。

1. Androidアプリの作成(前半)

Androidアプリを作成していきましょう。

1-1. Android Studio のダウンロード・インストール

事前に、Android Studio をダウンロード・インストールしておきましょう。
  https://developer.android.com/studio?hl=ja

1-2. 新しいプロジェクトの作成

Android Studio を開き、新しいプロジェクトを作っていきましょう。

画面上部[File] → [New] → [New Project...]を選択
screenshot_10.png

Choose your project 画面
Empty Activity を選択し、画面下「Next」を選択します。
screenshot_11.png

Configure your project 画面
screenshot_12.png

  • 「Name」には、任意のアプリの名前を記載しましょう。
    • ※これが画面に表示されるアプリ名とはならないため、名前を気にしすぎなくて構いません。
  • 「Package name」は、アプリの識別子となります。後ほど必要となるため、保存をしておきましょう。
  • 「Language」 は、今回はJavaを選びましょう。
  • 「Minimum API level」 は"API 21: Android 5.0 (Lolipop)"などを選択しましょう。
  • 最後に「Finish」を押します

初回のBuildが始まり、終わるとMainActivity.java の編集画面が開きます。

2.Firebase の設定

同時並行で、Firebaseの設定も進めていきましょう。

2-1. Firebaseへのログイン

Firebase の画面に進み、右上の「コンソールへ移動」をクリックし、Googleアカウントでログインします
screenshot_03.png

2-2. Firebaseプロジェクトの作成と、Androidアプリへの追加

「プロジェクトを追加」を選択
screenshot_04.png

プロジェクトの作成(手順 1/3)画面

任意の「プロジェクト名」をつけ「続行」を押します。
screenshot_05.png

プロジェクトの作成(手順 2/3)

Googleアナリティクスの設定は、「今は設定しない」を選びます。

プロジェクトの作成後
「続行」を押します。「Project Overview」の画面に遷移します

screenshot_07.png

2-3. AndroidアプリへのFirebaseプロジェクトの追加

「Project Overview」の画面
画面中央の「ドロイド君」のアイコンを選択します。
screenshot_09.png

「AndroidアプリへのFirebaseの追加」画面
screenshot_13.png

  • 「Androidパッケージ名」には、1-2.新しいプロジェクトの作成で設定したアプリ名を入力します。
  • 「アプリのニックネーム(省略可)」には、このアプリのわかりやすい名前をつけます。
  • 「デバッグ用の証明書 SHA-1(省略可)」は、今回は空欄のままで構いません。

最後に、「アプリを登録」ボタンを押します。

「②設定ファイルのダウンロード」画面
1. 画面中央の「google-services.jsonをダウンロード」を選択し、「google-services.json」 ファイルをダウンロードします。screenshot_14.png
2. Android Studio を開き、画面左上「Android」を選択し、「Project」ビューに変更します。screenshot_15.png
3. プロジェクトのフォルダを展開後、「app」フォルダを展開します。screenshot_16.png
4. ダウンロードしたgoogle-services.json ファイルを、 Android アプリ モジュールの ルート ディレクトリに移動します。
(ダウンロードフォルダから、Android Studioの「app」へ、ドラッグ・アンド・ドロップすることでできます。)screenshot_17.png
5. Moveのポップアップ画面が表示されるので、「OK」を選択します。screenshot_18.png
6. 「app」配下に'google-services.json'が追加されます。screenshot_19.png
7. Firebaseの画面に戻り、「次へ」を選択します。screenshot_20.png

「③Firebase SDKの追加」の項目になります。
1. まず、「プロジェクトレベルのbuild.gradle」に表示された項目を、
Android Studioにて、プロジェクトレベルのbuild.gradleに記載します。
screenshot_21.png

  1. プロジェクトレベルのbuild.gradle は、<プロジェクト名>/build.gradleなので、ダブルクリックして開きましょう
    screenshot_22.png

  2. コンソール画面の表示の通りに、項目を追記してください。(最初から記載されているものもあります。)
    screenshot_23.png

  3. なお、Android Studio は初期設定で自動保存がONなので、[Ctrl] + s などは不要です。

  4. 次に、「アプリレベルの build.gradle」に表示された項目を、
    Android Studioにて、アプリレベルの build.gradleに記載します。
    screenshot_24.png

  5. アプリレベルの build.gradle は、<プロジェクト名>/app/build.gradleなので、ダブルクリックして開きましょう
    screenshot_25.png

  6. コンソール画面の表示の通りに、項目を追記してください。(最初から記載されているものもあります。)
    screenshot_26.png

  7. 追加で、Firebase Cloud Messaging クライアント アプリを設定しましょう
    参考:https://firebase.google.com/docs/cloud-messaging/android/client?hl=ja

<プロジェクト名>/app/build.gradle
dependencies {
    // 以下の行を追記します
    implementation 'com.google.firebase:firebase-messaging:19.0.1'
    }
  1. 最終的に、3箇所記載されることとなります。(2019年9月現在)
    screenshot_47.png

  2. 最後に、IDE上部 に表示されるバーの [Sync now] をクリックします。
    screenshot_48.png

  3. そして、Firebaseの画面に戻り、ブラウザ下部の「次へ」を選択します。
    screenshot_28.png

「④Android 向けスタートガイドを読む」の画面

「コンソールに進む」を選択してください。
screenshot_29.png

3. Androidアプリの作成(後半)

Android Studioに戻り、アプリを作成します。

画面左上「Project」を「Android」ビューに変更

screenshot_30.png

3-1. アプリの表示名設定

Android画面上での、アプリの表示名を設定
res/values/strings.xml を開いて、Android画面上での、アプリの名前を設定します。
screenshot_31.png

通知が来た時に嬉しいように、マッチングアプリ風の名前にしておきましょう笑

strings.xml
<string name="app_name">Match!</string>

3-2. MainActivity の設定

メイン画面となる、MainActivity.java に、通知のために必要となるトークンを発行する機能を実装します。

参考ドキュメント:https://firebase.google.com/docs/cloud-messaging/android/client?hl=ja#%E7%8F%BE%E5%9C%A8%E3%81%AE%E7%99%BB%E9%8C%B2%E3%83%88%E3%83%BC%E3%82%AF%E3%83%B3%E3%81%AE%E5%8F%96%E5%BE%97

app / java / com.example.<プロジェクト名> / MainActivity を開く
screenshot_69.png

以下のコードを記載します

MainActivity.java
package com.example.motemoteapp;

import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;

import android.os.Bundle;
import android.util.Log;
import android.widget.Toast;

import com.google.android.gms.tasks.OnCompleteListener;
import com.google.android.gms.tasks.Task;
import com.google.firebase.iid.FirebaseInstanceId;
import com.google.firebase.iid.InstanceIdResult;

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        FirebaseInstanceId.getInstance().getInstanceId()
                .addOnCompleteListener(new OnCompleteListener<InstanceIdResult>() {
                    @Override
                    public void onComplete(@NonNull Task<InstanceIdResult> task) {
                        if (!task.isSuccessful()) {
                            Log.w("FIREBASE", "getInstanceId failed.", task.getException());
                            return;
                        }

                        // Get new Instance ID token
                        String token = task.getResult().getToken();

                        // Log and toast
                        Log.d("FIREBASE", " TOEKN = " + token);
                        Toast.makeText(MainActivity.this, token, Toast.LENGTH_SHORT).show();
                    }
                });
    }
}

最初の起動時に発生するイベントである、onCreateメソッドの定義に、
トークンを取得してログに出力する処理が記載されています。

3-3. 補足情報

FCMを使う際、FirebaseMessagingServiceを継承したサービスを作成する必要があります。
このサービスを実装することで、フォアグラウンド(アプリが起動している状態)での通知の表示など、高度な通知の設定ができるようになります。
しかし、今回はこのサービスを用意しなくても、通知の受信ができるため、割愛します。

なお、「参考記事2」は、とても親切な記述で一読をおすすめしますが、
記事にて取り上げられている、FirebaseInstanceIdService の実装は、2019年9月現在、推奨されなくなっているため、
トークンの取得周りの処理については注意が必要です。
- 参考記事3:FirebaseInstanceIdServiceがDeprecatedになった件
- 参考記事4:Android で Firebase Cloud Messaging クライアント アプリを設定する - 現在の登録トークンの取得

3-4. アプリの実行

PCとAndroid端末をつなげ、アプリを実行します。

Android端末の「USBデバッグモード」をONにした上で、USBケーブルでPCと接続
参考URL:https://techacademy.jp/magazine/2433

画面右上で、該当端末を選択
screenshot_50.png

画面横の右向き三角ボタンを押して、実行
screenshot_51.png

問題がなければ、ビルドが成功し、Android端末でアプリが起動します
ビルドが終わってから、少し時間がかかります。焦らずに待ちましょう

Androidアプリ上で、トークンがトースト表示される
Screenshot_20190916-191641.png

Android Studio上の「6:Logcat」に、トークンが表示される
このトークンは後ほど必要になるので、コピーしておきましょう。
screenshot_40.png

4. 通知のテストを行う

Firebaseのコンソール画面から、通知のテストが行えます。

FirebaseのCloud Messaging画面
画面左「Cloud Messaging」→「Send your first message」を選択します。
screenshot_41.png

「通知の作成」画面
「通知のタイトル」と「通知テキスト」に任意の名前をつけて、
画面右の「テスト メッセージを送信」を選択します。
screenshot_42.png

「デバイスでのテスト」ポップ画面
「FCM登録トークンを追加」のところに、先程Android Studio の、Logcatから取得したトークンをペーストし、右隣の「+」ボタンを押します。
screenshot_45.png

テストの実行
Android端末 がロック画面になっていることを確認したうえで、
画面右下の「テスト」を選択します。
screenshot_46.png

Androidに通知が飛んできます。
Screenshot_20190916-131243.png

やったね!!

今回は、FirebaseMessagingServiceを継承したサービスを作成していないため、
アプリがフォアグラウンドの時は通知が表示されない。そのため通知を受け取るためには、ロック画面にしておく必要がある。

5. APIを使って通知を送る

5-1.必要な情報の用意

APIを使って通知を送るにあたって、以下の2つの情報が必要になります。

  • トークン
  • APIキー

トークン

トークンは、3-4. アプリの実行 にて、Android Studio のLogcatからコピーしたトークンです。

APIキー

APIキーは、Firebaseのコンソール画面から取得します。

FIrebaseの画面から、作成したアンドロイドアプリの設定画面に進む
screenshot_58.png

「Settings」の画面が開いたら、「Cloud Messaging」のタブを選択
screenshot_59.png

「プロジェクト認証情報」の「サーバーキー」をコピー
screenshot_60.png

5-2. Postmanを使う方法

リクエストが簡単に送信できる、Postmanを使いましょう。

Postmanをダウンロード・インストール・そして初回のユーザー登録を行なう
  https://www.getpostman.com/

Postmanが開いたら、画面上部の「+」ボタンを押す
screenshot_57.png

新しいリクエストの作成画面

以下のように、入力してください。

  • 「リクエストの方法」 は POST
  • 「URL」は https://fcm.googleapis.com/fcm/send
    screenshot_61.png

  • 「Headers」は以下2つを記載

KEY VALUE 補足
Authorization key=<APIキー> <APIキー>は5-1.必要な情報の用意で確認をしたAPIキーとなります。
Content-Type application/json --
  • 「Body」は、rawを選択して、以下のjsonを貼り付けます。 screenshot_62.png
raw
{
    "notification" : { 
        "title": "マッチングが成立しました",
        "body": "メッセージを送りましょう!",
        "sound":"default",
        "icon":"@android:drawable/sym_action_chat",
        "color":"#FF8000"
    } , 
    "to" : "<トークン>", //<トークン>は、'5-1.必要な情報の用意' で確認をしたトークンとなります。
    "priority":"high"
} 

最後に、「Send」ボタンを押すことで、
画面下部のレスポンスが「"success":"1"」 になり、Androidに通知が来ます!
screenshot_63.png
Screenshot_20190916-141806.png

5-3. cURLコマンドを使う方法

curlコマンド
curl -X POST https://fcm.googleapis.com/fcm/send -H 'Authorization: key=<APIキー>' -H 'Content-Type: application/json' -d '{
"notification" : { 
"title": "マッチングが成立しました",
"body": "メッセージを送りましょう!",
"sound":"default",
"icon":"@android:drawable/sym_action_chat",
"color":"#FF8000"
} , 
"to" : "<トークン>",
"priority":"high"
}'

※Macからは動作確認済み
※Windows環境ではうまくいかないようです...(原因調査中)

Postmanから、cURLコマンドを作成する際の注意

Postmanを使うと、cURLコマンドが簡単に生成できます

Postmanの画面右上「Code」を選択。
screenshot_64.png

「言語選択」のところで、「cURL」を選択すると、cURLコマンドが一瞬で生成される
screenshot_65.png
screenshot_66.png

ただ、残念なことに、ここで生成されるcURLはインデントの関係で、そのままでは動きません。
不要な要素や、インデントを修正すると、上に記載したコマンドと同じ形になります。

5-4. Node.jsを使う方法

PCにNode.jsが入っている場合、
下記コードで、通知を送れます。(追加のパッケージ等は不要)

sendnotify.js
var http = require("https");

var options = {
  "method": "POST",
  "hostname": "fcm.googleapis.com",
  "path": "/fcm/send",
  "headers": {
    "Authorization": "key=<APIキー>",
    "Content-Type": "application/json",
  }
};

var req = http.request(options, function (res) {
  var chunks = [];

  res.on("data", function (chunk) {
    chunks.push(chunk);
  });

  res.on("end", function () {
    var body = Buffer.concat(chunks);
    console.log(body.toString());
  });
});

req.write(JSON.stringify({ notification: 
   { title: 'マッチングが成立しました',
     body: 'メッセージを送りましょう!',
     sound: 'default',
     icon: '@android:drawable/sym_action_chat',
     color: '#FF8000' },
  to: '<トークン>',
  priority: 'high' }));
req.end();

上記jsファイルを適当なディレクトリに作成し、コマンドプロンプト(ターミナル)から、実行することで、通知が送れます。

コマンド例
cd C:\Users\<ユーザー名>\Desktop\work_dir
node sendnotify.js

For文やWhile文と組み合わせて、通知の嵐を体験してみましょう。モテキが来たように錯覚します。

注:Postmanから、Node.jsコードを作成する際の注意。

PostmanからNode.jsのコードを簡単に作成できます。

Postmanの画面右上「Code」を選択
screenshot_64.png

「言語選択」のところで、「Node」→「Native」を選択すると、コードが一瞬で生成される
screenshot_67.png
screenshot_68.png

コードの修正
しかし残念なことに、ここで生成されるコードはいつくか修正が必要です。

  • まず"headers"から、リクエストに不要な項目を削除します。
    • 具体的には、"Authorization""Content-Type"以外は不要です。
  • つぎに、var options = {...} の中の"hostname""path"を以下のように修正します。
"hostname": "fcm.googleapis.com",
"path": "/fcm/send",

上記の修正を行うと、上に記載したコードと同じ形になります。

補足

参考記事

Firebase公式ドキュメント
Android プロジェクトに Firebase を追加する
Android で Firebase Cloud Messaging クライアント アプリを設定する

Qiita先行記事(おすすめ)
AndroidアプリにFirebase Cloud Messagingを実装する(2) - アプリでメッセージを受信する
AndroidのPush通知(FCM)をサーバー知識無しで試してみよう

本当は...

マッチングアプリをテーマにしましたが、
実は怖くて使ったことがないという... ・ω・

LINE WORKS のトーク Bot API を Postman でサクっと試してみる

$
0
0

手っ取り早く LINE WORKS のトーク Bot API を実行してみる

この記事では、LINE WORKS のトーク Bot API をとにかく実行して、LINE WORKS の利用者に Bot からチャットを送信してみる方法を説明します。

Postman の入手とインストール

ここでは Postman というツールを利用します。Postman は Web API を試してみたいといったときに、便利なクライアント アプリです。

TITLE: Postman | The Collaboration Platform for API Development
URL: https://www.getpostman.com/

Windows, macOS, Linux それぞれに対応しています。ダウンロード ページからインストーラーを入手して、インストールしましょう。

TITLE: ‎Download the App
URL: https://www.getpostman.com/downloads/

インストールが完了すると、Postman が起動します。サインインを求める表示が出る場合もありますが、これはスキップすることでサインインせずに使うこともできます。

スクリーンショットは Windows 版です。その他のプラットフォームもほぼ同様です。

image.png

LINE WORKS の API を利用する準備

LINE WORKS の API を利用するために、LINE WORKS の Developer Console で、いくつかの事前準備を行います。

Developer Console の説明はこちらにあります。

TITLE: LINE WORKS Developers
URL: https://developers.worksmobile.com/jp/document/13?lang=ja

Developers の権限が付与されたアカウントで次の URL から Developer Console にアクセスしましょう。LINE WORKS のサインアップ時に作成したアカウントは最高管理者の権限が付与されており、Developer の権限も含まれます。

https://developers.worksmobile.com/jp/console/openapi/main

最初のアクセスでは、利用規約の同意を求められます。
image.png

"同意" して [利用する] をクリックすると、コンソールが開きます。

Postman から トーク Bot API を使うために以下の発行と追加を行います。
- API ID
- Server API Consumer Key
- Server List (固定IPタイプ)

image.png

  • API ID

    [発行] ボタンをクリックすると生成されます。
    image.png

  • Server API Consumer Key

    [発行] ボタンをクリックすると、Server API Consumer Key 権限設定のサブ ウィンドウが開きます。
    image.png

image.png

"トークBotすべて" をチェックし [次へ] をクリックします。
image.png
"有効期限" と "自動延長" の設定を適宜行い、[保存] をクリックします。

image.png
Server API Consumer Key が生成されます。

  • Server List (固定IPタイプ)
    Postman を実行するコンピューターの利用しているグローバル IP アドレスを調べます。 アクセスすることで利用中のグローバル IP アドレスを表示する Web サービスがあるのでそれらを利用しましょう。

例: http://www.cman.jp/network/support/go_access.cgi
image.png
確認したグローバル IP アドレスはメモしておきましょう。

image.png

LINE WORKS Developer Console で Server List (固定IPタイプ) の [追加] ボタンをクリックします。

image.png

新しいウィンドウが開きます。次のように入力します。
サーバー名: 任意の名前
Keyの選択: プルダウンから先ほど作成した Server API Consumer Key を選択
IP: 先ほど調べたグローバル IP アドレス

[発行] ボタンをクリックします。
image.png
Token が生成されます。[同意して利用する] をクリック。

LINE WORKS に Bot を登録する

LINE WORKS の Developer Console から Bot を登録します。
image.png
Developer Console の Bot メニューで [登録] ボタンをクリックします。

Bot登録の画面で必要な項目をそれぞれ入力します。
image.png
Bot名: 任意の名前
「説明」: 任意の説明
管理者/主担当: 任意のメンバーを主担当に指定

その他の項目は今回は不要です。[保存] ボタンをクリックします。

image.png

Bot No. が生成されます。Bot No. はメモしておきましょう。

登録した Bot の利用設定

こちらの URL から LINE WORKS の管理者画面の Bot の利用設定ページにアクセスし、[+追加] ボタンをクリックします。
https://bot-admin.worksmobile.com/
image.png

先ほど登録した Bot を選択し、[追加] ボタンをクリックします。
image.png

Postman で LINE WORKS トーク Bot API を実行

トーク Bot API でテキスト メッセージを送信します。API の説明はこちらのページを参照してください。

TITLE: メッセージ送信 (text)
URL: https://developers.worksmobile.com/jp/document/100500801?lang=ja

こちらのドキュメントに記載のとおり Request URL は以下です。
https://apis.worksmobile.com/r/{API ID}/message/v1/bot/{botNo}/message/push
{API ID} と {botNo} は、前の作業で生成された値に置き換えます。

例えば次のようになります。
https://apis.worksmobile.com/r/jp1iDZPxBenMo/message/v1/bot/101578/message/push

HTTP Method は POST です。

ここまでの内容を Postman に設定します。
image.png

さらに Postman の Authorization タブを開いて、次の設定を行います。

TYPE をプルダウンから "Bearer Token" を選択。
Token に Server List(固定IPタイプ) で生成した Token を入力。
image.png

次に Headers タブを開いて、以下の内容を入力します。

Key: Content-Type Value: application/json; charset=UTF-8
Key: consumerKey Value: <前の手順で生成された Server API Consumer Key の値>
image.png

引き続き、Body タブを開いてドキュメントの Request Example の内容を基に、次のとおり入力します。入力形式は [raw] を指定します。"accountId" は書き換えてください。

image.png

以上で準備が整いました。

Bot からのメッセージを確認するために LINE WORKS のトーク画面を開きましょう。
ブラウザで確認する場合はこちらの URL です。
Https://talk.worksmobile.com/

またはモバイル アプリや PC/Mac のアプリでログインしてもよいです。

Postman の [Send] ボタンをクリックします。
image.png

200 OK の Status が返れば正常にメッセージが送られています。
image.png

ブラウザで Bot からのトークを受信した様子です。

image.png

ありがちなエラーと対処

Postman で [Send] ボタンをクリックしても、メッセージが届かず 200 OK のレスポンスも返らない場合は、Postman の Http Response の Body の内容を確認しましょう。

image.png
存在しない API ID を記述しているケース。API ID を修正しましょう。

image.png
Server API Consumer Key または Server List(固定IPタイプ) の Token の相違。正しく key や Token の Value を記述しましょう。

image.png
accountId の相違。存在しないメンバー宛に送ってしまっているなど。

image.png
Server List(固定IPタイプ) で登録したのとは異なる Global IP Address から実行している。

個人メモ:postmanでのテストコート作成&実行

$
0
0

postmanテストコート実行

■ Teamのworkspace作成

1. workspace作成:

​ My Workspace→Team→Create View で、名前を入力し、CreateWorkspaceボタンを押下

 追記:workspaceに招待する人は、emailを入力し招待(後からの招待も可能)

1_workspace作成.gif.gif

2. 初回作成時には、Team名とurlを設定が必要になる

2_team名とurl設定.gif.gif

■ 実行レクエスト作成

1. Collectionn作成

3_Collection作成.gif

2. レクエスト作成

作成した、Collectionに、必要なレクエストを作成する

4_req作成.gif

■ テストコード

1. テストコード作成

レクエストのTestsに実行結果に対するテストコードを記入する

5_テストコード作成.gif

例:戻りのステータス判断のテストコード

pm.test("HTTPステータスコードが200であること", () => {
    pm.response.to.have.status(200);
});

2. テスト実行

作成した、レクエストをSendボタンで、実行する。

自動的にTestsコードが実行され、テスト実行結果が確認出来る

6_テスト実施.gif

■ newmanコマンドでの実行

newman実行流れ

  • 1. apiKey取得
  • 2. Collectionsのuidを取得
  • 3. newman実行

1. apiKey取得

1.1 apiKey取得用のweb画面を開く

7_apiKey取得画面にGo.gif

1.2 名前を入力し、apiKeyを取得する

9_apiKey取得完了.gif

例:今回取得したapiKeyは、 PMAK-5da94b1745e63c003099522d-ca4770dae569f6431d15f5c6963b3f8ca2

2. Collectionsのuidを取得

取得url:https://api.getpostman.com/collections

ヘッダ情報: key=X-Api-Keyvalue= 取得したAPIKeyの値

10_getCollectionsUid.gif

3. newman実行

3.1 newmanインストール

npm install -g newman

3.2 newmanコマンド

newman run https://api.getpostman.com/collections/{{collectionsUid}}?apikey={{apikey}}  -r html,cli,junit

{{apiKey}} : PMAK-5da94b1745e63c003099522d-ca4770dae569f6431d15f5c6963b3f8ca2

{{collectionsUid}} : 9187044-2e8c39c6-702b-470d-8e8e-781b123b4f0c

代入後のコマンド

newman run https://api.getpostman.com/collections/9187044-2e8c39c6-702b-470d-8e8e-781b123b4f0c?apikey=PMAK-5da94b1745e63c003099522d-ca4770dae569f6431d15f5c6963b3f8ca2 -r html,cli,junit

3.3 実行

newman コマンドを実行すると、対象Collectionsの全レクエストが実行され、テスト実行結果が表示される

11_newman実行.gif

PostmanでAPI

$
0
0

なにやらPostmanが超絶便利そうなので使ってみる。

ネイティブアプリ版(?)を使っている。

モックサーバーを使う

Postmanにはモックサーバーがある。

APIキーが必要
Headersにx-api-keyを設定する必要がある。

APIキーの場所は「Account Settings > Postman API Keys」で発行する。
https://xxxxxx.postman.co/settings/me/api-keys

PostmanのAPIキー

リクエストURLで変数を使う

スクリーンショット 2019-10-25 16.11.45.png
{{url}}のようなマスタッシュ構文で変数が使える。

NewからEnvironmentを選択するとモーダルで下記ウィンドウが出る。

スクリーンショット 2019-10-25 16.14.46.png

VARIABLEが変数名なので{{url}}という変数を作りたい場合は「url」と書く。

INITIAL VALUEに置き換えたいURLを書く。
例えば「 https://api.test.com 」など。

CURRENT VALUEはいまいちよくわからないのでINITIAL VALUEと同じものを入れておく。APIのパラメーターとして使うときに活きてくるものだと思われる。

スクリーンショット 2019-10-25 16.16.19.png

設定しただけでは適用されないので、
ウィンドウ右上にあるプルダウンで、作成したEnvironmentを選択する。

APIキーも変数として扱う

スクリーンショット 2019-10-25 16.26.10.png
Environmentでx-api-keyという変数を作って格納しておけば、
上記のようにVALUEに{{x-api-key}}と記述するだけでよくなる。

Viewing all 496 articles
Browse latest View live