Postmanで UiPath Orchestrator APIを操作する件 つづき

さてさて前回の記事 [UiPath Orchestrator のAPIを呼び出す件(Postman編)](https://qiita.com/masatomix/items/edafc217aec381762813) で

- Postmanのダウンロード・インストール・アカウント作成
- Hello World 的なGETリクエストを実施
- 最後に UiPath Orchestrator API へ認証リクエストを送る

までを行いましたが、今回はそのつづきです。
前回作成した「Request」も引き続き使いますので、前回の記事は終わらせておくことをおすすめします。
![prev](https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F73777%2F1fc25437-6783-b822-3d6d-1e8fd25c5735.png?ixlib=rb-1.2.2&auto=format&gif-q=60&q=75&s=d94239b5616061472f384af3715565ba)



##  概要

さてUiPath OrchestratorのAPIへのリクエストは Cloud 版でもOn-Premise版でも

- 認証リクエストで**トークンを取得**したのち
- その**トークンを毎回リクエストヘッダに**つけてリクエスト

するので、**認証リクエストの戻り電文に含まれるトークンをつかいまわし**できるようにしておくと便利です。
また認証情報(``userKey``,``clientId``など)は使うヒトによって当然異なる値なので、 **認証情報などは変数として外だし**で定義しておくのがよさそうです。

今回はこのへんをやってみましょう。最終的に**マシン一覧を取得するリクエスト投げるところまでやる**ので、これで一通り**PostmanをつかってUiPath Orchestrator APIを呼びだせる**ようになると思います。

## やってみる

###  認証情報などを変数として外だし

前回は、https://account.uipath.com/oauth/token へPOSTする「Request」を作りましたが、まだ手元にあるならそちらを開いてください。もしくは前回記事にしたがって作成しましょう。

さてその際、Body部には、下記のOC画面から取得した ``userKey``,``clientId`` の値を直接記述したと思います。
![05_](https://qiita-user-contents.imgix.net/https%3A%2F%2Fimgur.com%2FgLrvqgG.png?ixlib=rb-1.2.2&auto=format&gif-q=60&q=75&s=95413bb859a6b18478c01ea1f6d51030)

今回はそのBody部に、``{{clientId}}`` などとして**変数を埋め込んで** おきます。

```JSON
{
  "grant_type": "refresh_token",
  "client_id": "{{clientId}}",
  "refresh_token": "{{userKey}}"
}
```

ちなみにこの ``{{clientId}}`` などの記法は、中括弧を倒すと口ひげ(mustache) に似ていることから、**ムスタッシュ記法**とか言われたりします :-)


ということで「Request」は下記のようになったはずです。リクエストとして送信される電文に、変数を埋め込むことができました。
![01](https://imgur.com/FoBt37k.png)

埋め込んだ変数に実際の値を設定するために、Postman上で ``clientId``,``userKey`` という変数を定義します。
まずは右上の歯車アイコンをクリック。
![02](https://imgur.com/Zm54Dyy.png)

Manage Environmentsというポップアップが上がったと思います。これは**変数たちの定義を入れておくハコ「Environments」**の管理画面です。変数たちを定義する場所って考えればOKです。
というわけで「Add」をクリック。
![03](https://imgur.com/kVotOWR.png)

「Cloud」って名前の「Environment」をひとつ定義しました。そして「Add」をクリック。
![04](https://imgur.com/oRXAH79.png)

保存できたようです。
つづいて、CloudってEnvironmentに先の変数たちを定義していきますので、「Cloud」をクリックして中に入ります。
![05](https://imgur.com/8ytM5tY.png)

下記の通り「``clientId``,``userKey``」と入力してください。
また変数ごとの「Initial value(初期値)」が記述可能なので、**OC画面から取得したいつもの値を入力**しておきます。「Current Value(現在値)」の方にも同じ値がセットされるはずです。(ちなみに、明示的に初期値で現在値を上書きする場合は「Reset All」をクリックしてください。)


最後に「Update」をクリック。
![06](https://imgur.com/FLeUkKw.png)

保存できたようなので上部「×」ボタンでポップアップを閉じます。
![07](https://imgur.com/hB7LHsP.png)

さて、変数にセットした値を再度確認したり、値を実際に使ったりするには、右上のEnvironmentsのプルダウンをデフォルトの「No Environment」から「Cloud」へ変更します。
![08](https://imgur.com/dk0CLr1.png)

選択されたEnvironment に定義された変数たちの値を確認するために、**目玉のマークをクリック**すると、
![09](https://imgur.com/Iejraku.png)

ポップアップで値を確認することができます。Current ValueにOC画面上の文字列が設定されていることが確認できましたね。
ちなみに、この画面の右肩の「Edit」から、さきほどの変数定義画面に遷移することもできます。
![10](https://imgur.com/4MQUs6U.png)

ではこのリクエストを実行してみましょう。
といっても「Send」ボタンを押すだけです。前回同様、値が取れたのではないかと思います。

![11](https://imgur.com/OM5F6LI.png)

以上で、前回やったところにプラスして、**変数を定義できるようになりました**ね。

### ほかにも、いくつか変数を定義する

先ほどの認証リクエストの戻り電文

```JSON
{
  "access_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVxxx.eyJodHRwczovL3VpcGF0aC9lbxxxxx.B4u8jk4uK7Y39ug3jFlsGxyFnnKAfsMkNP3lEJdM57igJwm0DNE21yXXYjADt7wKeywHxxxx",
  "id_token": "-- 割愛 --",
  "scope": "openid profile email offline_access",
  "expires_in": 86400,
  "token_type": "Bearer"
}
```

のうち**``access_token`` の値は今後のリクエストでなんども使用**します。なので先と同様の方法(歯車 >>「Cloud」を選択する )で、**``token``という変数に上記の値を設定**してください。

また**APIを投げる先のURLも``url``という変数に定義**しておきましょう。APIのURLは認証リクエストのそれとは異なり、具体的には
``https://platform.uipath.com/[Account Name]/[Tenant Logical Name]`` となるのですが、``[Account Name],[Tenant Logical Name]`` は、何度か出てくるOCの画面の
![05_](https://qiita-user-contents.imgix.net/https%3A%2F%2Fimgur.com%2FgLrvqgG.png?ixlib=rb-1.2.2&auto=format&gif-q=60&q=75&s=95413bb859a6b18478c01ea1f6d51030)

- ``[Account Name]`` :  アカウントの論理名
- ``[Tenant Logical Name]``:テナントの論理名

に該当します[^1]。

**-- 2020/07/07追記 --**
APIのURLが、https://platform.uipath.com だったり https://cloud.uipath.com だったりするケースがあるようです(2020/07/07時点、どっちでも取れるっぽい)。
https://cloud.uipath.com へ移行している印象なので、適宜URLを変えてみてください。
**-- 2020/07/07追記 以上--**

[^1]: かつては``Tenant Logical Name`` でなくてサービス名だった気がするけど気にしない:-)

変数の定義でもう一つ。**この「テナントの論理名」もAPIに投げるパラメタとして必要**なので、``tenantName`` 変数を定義しておきます。


まとめると、最終的に「Cloud」のEnvironmentには下記の変数たちが定義されたと思います。

| 変数名         | 説明                                                         |
| -------------- | ------------------------------------------------------------ |
| ``clientId``   | OC画面の「クライアントID」                                   |
| ``userKey``    | OC画面の「ユーザーキー」                                     |
| ``tenantName`` | OC画面の「テナントの論理名」                                 |
| ``url``        | ``https://platform.uipath.com/[Account Name]/[Tenant Logical Name]`` |
| ``token``      | 認証リクエストの戻り値の``access_token``の値                 |


ちなみに ``tenantName`` は実際はURLの一部分( ``[Tenant Logical Name]``)と同一だし、``token``は認証を行うと更新されるので、**最終的にはそれらは自動更新されるようにします**。

画面上で変数を確認すると、こんな感じです。
![12](https://imgur.com/rtkzbsa.png)

あ、ちょっと前にも書きましたが**「Reset All 」をクリックすると、Initial ValueでCurrent Valueを更新**します。実際の**リクエストにはCurrent Value が使用される**ので、Initial Valueの値を変更した場合は、適宜**「Reset All」してCurrentに値を反映させる**ようにしてください。
(逆に「Persist All」 をクリックすると、Current Value で Initial Valueを更新します)

準備はここまでです。つかれましたね。


###  マシン一覧を取得してみる

さていよいよAPIを使ってリクエストを投げてみます。
メイン部分の「+」ボタンをクリックして、「Request」を新規作成。

![plus](https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F73777%2F74f8eecf-8acb-28d1-7325-21f1d3b92ef3.png?ixlib=rb-1.2.2&auto=format&gif-q=60&q=75&s=c6cbb931bc9d1f588c8f03c6d161e091)


Postman にセットするパラメタ値は以下の通り。

まずはURL。
URLは「``{{url}}/odata/Machines``」とします。すでに認識かとおもいますが **``{{url}}`` は「Cloud」Environment上にセットした値で置換**されます。またメソッドは「GET」で。
![100](https://imgur.com/Jgoam57.png)

つづいて認証情報。
 Authorizationタブ をクリックして、Typeプルダウンで「Bearer Token」を選択、右側のTokenに ``{{token}}`` と設定。**認証リクエストで取得した値がココにセットされる**って事ですね。
![102](https://imgur.com/MePQCTu.png)

最後にテナント名です。
Headersタブをクリックして、Key:「``X-UIPATH-TenantName``」,Value:「``{{tenantName}}``」と設定。
ちなみに小さく hidden と書いてあるところをクリックすると、その他のHeader 情報も確認することができます。
![103](https://imgur.com/kELowsE.png)

以上で完了。
さっそくリクエストを送信してみましょう。「Send」をクリックすると
![104](https://imgur.com/zV9Ywfi.png)

**マシンの一覧のJSONデータが取得できましたね！**JSONだとわかりにくいですが「``"@odata.count": 5``」なのでマシンが5台、valueの値がJSON配列になっていて、5台のマシンの情報( 例: ``"Name": "DESKTOP-6502OD6"``など) が取得できていることが分かります。

以上で「**認証リクエストを送信してトークンを取得して、そのトークンをつけてマシン一覧を取得する**」ことができました。

このリクエストは「Save」して適宜名前をつけて保存しておきましょう。



### 送信された電文を実際に確認する

ちなみに、いま実際にどんなHTTPリクエストが送信されたか、を確認したいときもありますよね。その場合は右上「code」をクリックすると、、、
![109](https://imgur.com/cdAihHJ.png)

左メニューから HTTPを選ぶと、HTTP電文が確認できます[^2]。
![http](https://imgur.com/TzdIdH4.png)

左メニューから cURLを選ぶと、cURLのコマンドが。
![curl](https://imgur.com/XC9BOtM.png)

おお。このように**HTTP電文**であったり**cURLlコマンドだとこう打てばイイよ**みたいな情報を確認することができます。便利ですね。

[^2]: 実際投げた電文ではなくて、こんなの投げるよ！っていうモノと思われる。


## TIPS

後回しにしていた内容をいくつかまとめておきます。

### 取得したTokenを別のリクエストで自動でつかいまわし(Testsタブの使い方)

``token`` 変数は、認証リクエストの戻り値のJSON:

```JSON
{
  "access_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVxxx.eyJodHRwczovL3VpcGF0aC9lbxxxxx.B4u8jk4uK7Y39ug3jFlsGxyFnnKAfsMkNP3lEJdM57igJwm0DNE21yXXYjADt7wKeywHxxxx",
  "id_token": "-- 割愛 --",
  "scope": "openid profile email offline_access",
  "expires_in": 86400,
  "token_type": "Bearer"
}
```

にある``access_token``の値を手動でセットしましたが、**認証リクエストを投げたら自動でその値をセットさせるように**してみます。

**Postmanはリクエストを投げてもどってきた後「Tests」タブのスクリプトが自動で実行される**ようになっているので、下記のように記述してみましょう。
![106](https://imgur.com/hVHefpI.png)

見にくいのでちゃんと書くとこうです。

```javascript:Tests
pm.test("Token Saved", () => {
    const jsonData = pm.response.json()
    pm.environment.set("token", jsonData.access_token)
})
```

やってることは

- ``response.json()`` メソッドで、戻り電文をJSONデータとして取得 (して、このスクリプト内の変数である``jsonData``へ代入)
- ``pm.environment.set("token", jsonData.access_token)``で Environmentの``token``変数へ、access_token の値を代入

などです。これでEnvironmentの``token``へ値が設定されます。

動作確認してみます。先のスクリプトを Testsタブに記載したら、``token`` 変数はいったん削除しましょう(Postmanが自動で作成してくれるので)。
削除は、何度か出てくる変数の編集画面より、該当変数の×を押せばOKです。

![105](https://imgur.com/Y4W6ULb.png)

準備ができました。認証リクエストメソッドを実行すると、上記のスクリプトが動き出し最終的に``access_token`` 値 が``token`` 変数に書き込まれると思います。

![107](https://imgur.com/KmS2FTz.png)

「戻り電文から値を取り出して次のリクエストで使用する」なんて事ができるようになりました。

### テナント名をURLから自動で取得して設定する(Pre-request Scriptタブの使い方)

つづいて「テナントの論理名」について。この値は、 ``url`` 変数の
``https://platform.uipath.com/[Account Name]/[Tenant Logical Name]``
の最後の値を取り出せばよいわけですよね。

さきほどのTestsタブに似た機能として、**Postmanはリクエストを投げる前に「Pre-request Script」タブのスクリプトを自動で実行する**ようになっているので、そこに

```javascript:Pre-requestScript
const GetTenant = (url) => {
    const pieces = url.split('/')
    // Check if user formatted the url correctly
    if (pieces.length < 5)
        throw "Detected an invalid Cloud URL. Your URL must be in the form 'https://platform.uipath.com/<account logical name>/<tenant logical name>";
    // Return the last slug, which will be the tenant name
    return pieces.pop()
}

// Get URL
const url = pm.environment.get("url")
const tenant = GetTenant(url)
pm.environment.set("tenantName", tenant)
```

と書いてみます。ゴニョゴニョやってますが、

- ``pm.environment.get("url")``で、Environment の``url``変数の値を取り出し
- 自分で定義した「URLの末尾を取り出すGetTenant関数」を呼び出して
- ``pm.environment.set("tenantName", tenant)``で、取得した値をEnvironmentの``tenantName`` 変数にセット

しているということですね。


さて動作確認です。スクリプトを記述したのち、先ほど同様、定義済みの``tenantName`` は削除してもOKです。さて実行すると、、、

![108](https://imgur.com/C9M9LI3.png)

``url``を``/``で区切ってから、末尾の文字列を取り出して``tenantName``にセットされていることが確認できました。



## まとめ

- 認証リクエストの戻り値の``access_token``を使うことで、UiPath Orchestrator APIを呼び出すことができることが分かりました
- マシン一覧を取得するリクエスト投げるところまでやったので、で一通りPostmanをつかってUiPath Orchestrator APIを呼びだせるようになりました
- ``access_token``やURLなど、横断的につかう情報をEnvironment の変数として外出しできる事を学びました
- 各リクエストの 「Tests」タブは、リクエストが戻ってきた後に実行したいスクリプトを記述できることが分かりました
- 各リクエストの「Pre-request Script」タブはリクエストを投げる前に実行したいスプリトを記述できることが分かりました

次回以降で、**具体的なAPIの利用シーン**や、**OC画面で表示している情報のAPIをつかった取得方法**、**[UiPath Orchestrator APIのPostman](https://postman.uipath.rocks/?version=latest)  などのご紹介**、などなどをしていこうと思います。

以上、お疲れ様でしたー。




## 関連リンク

- [UiPath Orchestrator のAPIを呼び出す件(Postman編)](https://qiita.com/masatomix/items/edafc217aec381762813) 前回の記事
- [UiPath Orchestrator APIのPostman](https://postman.uipath.rocks/?version=latest)