Quantcast
Browsing Latest Articles All 69 Live
Mark channel Not-Safe-For-Work? (0 votes)
Are you the publisher? or about this channel.
No ratings yet.
Articles:

Postmanでjsonの配列とファイルを同時に送りたい

Postmanでファイルとjsonの配列を同時に送りたいときに詰まったので…
特にjsonの配列の書き方…

jsonだけの場合

jsonだけだったら、Bodyのrawを選択し、形式をJSONに設定して

{"image":"foo.png","people":[{"name":"tom","email":"foo@foo.com"},{"name":"john","email":"bar@bar.com"}]}

こんな感じで入力するだけ!

分かりやすい!

画像やPDF、CSVなどのファイルを送る場合

Bodyからform-dataを選択して、KEY入力欄のプルダウンから、Text → Fileに変更。
Select Filesをクリックして、送りたいファイルを選択すればOK!

JSONの配列とファイルを同時に送りたい

Fileは上記と同様に設定して、

KEYVALUE
people[][name]tom
people[][email]foo@foo.com
people[][name]john
people[][email]bar@bar.com

JSONはこんな感じで入力。

postman-body-screenshot

順番に注意

KEYVALUE
people[][name]tom
people[][name]john
people[][email]foo@foo.com
people[][email]bar@bar.com

順番がこんな感じになると、最後に読み込んだ方の値で上書きされるので注意。

配列の場合の書き方に苦戦したので投稿。
もっとスマートな書き方あれば教えて欲しいです!

自己証明書(オレオレ証明書)を使うとPostmanで接続エラーとなる問題への対応

概要

HTTPの接続テストをするときは Postmanが便利ですが、自己証明書(オレオレ証明書)を使った接続テストでは接続エラーとなってしまいました。ちなみに、Postman を使わずに Web ブラウザーからアクセスした場合は問題なく接続テストができています。
調べたところ、Postman のSSL証明書の検証によって接続エラーが発生していましたので対応方法について記載します。

対応方法

  1. Postman の File -> Settingsを開きます。

  2. General タブにある SSL certificate verificationOFFにします。

これでSSL証明書の検証が行われなくなります。

postman.png

Postman のデフォルト設定ではSSL証明書の検証が行われるため、自己証明書はブロックされてしまうようです。
自己証明書で接続エラーとなる場合は設定を確認してみてください。

IntelliJ+JerseyとPostmanでRESTfulAPIサンプル(JSON)

目的

IntelliJ IDEAで、JerseyでRESTfulAPIのサンプルを作る覚書。

ゴール

  • Tomcat起動してブラウザでAPIを呼び出す(GETまで)
  • Postmanを使ってAPIの動作確認
  • とりあえずJSONで返す

環境など

ツールなどバージョンなど
MacbookPromacOS Mojave 10.14.5
IntelliJ IDEAUltimate 2019.3.3
JavaAdoptOpenJDK 11
apache maven3.6.3
Jersey2.30.1
JUnit5.6.0
Tomcatapache-tomcat-8.5.51
Postman7.19.1

jdkやmaven、Tomcatのインストールは済んでいるものとします。
※コマンドラインでmavenコマンドを使わない場合は、mavenのインストールは不要です。(IntelliJにバンドルされています)

Postmanはこちらからインストールできます。
かつてはChromeの拡張機能で入れられたのですが、スタンドアロンアプリに変わっています。
同様の拡張機能はまだあるので、それらでも構わないと思います。

mavenプロジェクトの作成

mavenのJerseyを使ったWebアプリをまず作成します。
こちらを参考に、コマンドで作成します。
https://docs.huihoo.com/jersey/2.13/getting-started.html#new-webapp

$mvn archetype:generate -DarchetypeArtifactId=jersey-quickstart-webapp \-DarchetypeGroupId=org.glassfish.jersey.archetypes \-DinteractiveMode=false\-DgroupId=com.example \-DartifactId=simple-service-webapp -Dpackage=com.example \-DarchetypeVersion=2.30.1

groupIdartifacgtIdpackageは任意に変えてください。
TomcatではなくてGrizzlyで動かすので十分な場合は、#new-from-archetypeの項にあるコマンドで十分かと思います。

IntelliJ IDEAで開く

IntelliJ IDEAにプロジェクトをインポートします。

  • 起動画面で[Import Project]を選ぶ

project-import.png

  • プロジェクトフォルダを選び、[Open]をクリック
  • Mavenを選ぶ

project-type-maven.png

  • [Finish]をクリック

プロジェクトが開きます。

pom.xmlを編集する

pom.xmlを開いたら、Enable Auto Importをクリックしておきましょう。

1. javaバージョン

まず、javaバージョンが1.7になっているのを11に変更します。

pom.xml
<build><finalName>simple-webapp</finalName><plugins><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-compiler-plugin</artifactId><version>2.5.1</version><inherited>true</inherited><configuration><source>11</source><!-- ここ --><target>11</target><!-- ここ --></configuration></plugin></plugins></build>

2. 依存ライブラリの追加

(1)Json

Jsonを使いたいので、コメントアウトされている以下のコメントを外します。

pom.xml
<dependency><groupId>org.glassfish.jersey.media</groupId><artifactId>jersey-media-json-binding</artifactId></dependency>

(2)JUnit5

JUnit5を<dependencies>タグ下に追加します。

pom.mxl
<!-- https://mvnrepository.com/artifact/org.junit.jupiter/junit-jupiter-api --><dependency><groupId>org.junit.jupiter</groupId><artifactId>junit-jupiter-api</artifactId><version>5.6.0</version><scope>test</scope></dependency>

※JUnitは、juint.junitから移動した模様です。

3. MyResourceクラスを眺める

Jerseyでどのように書くのか全く見たことがない、などの場合は、MyResouce.javaを開いて、眺めてみるとよいでしょう。

親切にコメントで何をやっているか説明してくれているので、それほど難しいことではないと思います。
ここでは、以下のことが読み取れれば問題ないかと思います。

  • @Path("myresource")で、サーバーのルートからのパスを指定している
  • getIt()メソッドは、
    • @GETなのでGETメソッドで呼び出される
    • @Produces(MediaType.TEXT_PLAIN)なので、text/plainな文字列として提供される

POST@Postだろうなとか、そういうことが想像できれば十分です。

あ、あとでcurlで動かす時の為に、"Got It!"の後に改行を入れておいたほうがいいかもしれません。
二つぐらい入れておいたほうが見やすいかもです。

MyResource.java
publicStringgetIt(){return"Got it!\n\n";}

4. 動かしてみる

(1)Tomcatから起動

Tomcatで起動する設定をし、(前記事参照)、実行します。

  • [Jersey resource]のリンクをクリック
launch_index.png
  • 下記のようなページが表示されればOK
gotit.png

(2)curlコマンドで実行

APIなので、curlコマンドでも叩けないとね。

urlは、Tomcat版でブラウザを開いた時のをコピーしてくると楽です。

$curl http://localhost:8080/simple_webapp_war_exploded/webapi/myresource
Got it!

$

改行を入れとかないと出力を見つけるのが大変です(汗)

-iオプションを入れると、詳細が見られます。

$curl -i http://localhost:8080/simple_webapp_war_exploded/webapi/myresource
HTTP/1.1 200 
Content-Type: text/plain
Content-Length: 9
Date: Tue, 10 Mar 2020 06:53:25 GMT

Got it!

(3) Postmanで実行

Postmanも使ってみます。
Tomcatでアプリを起動しておく必要があります。(サーバーが動いてないと当然反応はできませんので)

  • Request URLに、APIへのパスを入力
    • ブラウザからコピーするのが早いです
  • メソッドはGETを選択
postman.png
  • [Send]ボタンをクリック

下の欄に結果が表示されているはずです。

postman_get_result.png

サンプルAPIを作る

1. モデルクラス

こんなモデルクラスでデータを登録して、読み書きするAPIを作ることを考えます。

publicclassEmployee{privateintid;privateStringfirstName;publicEmployee(){}publicEmployee(intid,StringfirstName){this.id=id;this.firstName=firstName;}publicintgetId(){returnid;}publicvoidsetId(intid){this.id=id;}publicStringgetFirstName(){returnfirstName;}publicvoidsetFirstName(StringfirstName){this.firstName=firstName;}}

(独り言)Kotlinならdata classで簡単なのになー

追記
空のコンストラクタは必須なので、忘れないでください。
(無いと500エラーになります。内部的には、JSON Binding deserialization error: javax.json.bind.JsonbException: Internal error: nullという例外で落ちています。)

2. リポジトリクラス

データの読み書きは以下のクラスを介して行います。
本来はデータベースなどから読み出すべきですが、ここではそれは重要ではないので、とりあえずリストを持っておいて使うことにします。

EmployeeRepository.java
publicclassEmployeeRepository{privatestaticEmployeeRepositoryinstance=newEmployeeRepository();privateList<Employee>employeeList;privateEmployeeRepository(){employeeList=newArrayList<>();}publicEmployeeRepositorygetInstance(){returninstance;}publicList<Employee>selectAll(){returnemployeeList;}publicEmployeeselect(intid){for(Employeeemployee:employeeList){if(employee.getId()==id){returnemployee;}}thrownewEmployeeNotFoundException();}publicsynchronizedvoidinsert(intid,StringfirstName){try{select(id);}catch(EmployeeNotFoundExceptione){// いなければ追加できるemployeeList.add(newEmployee(id,firstName));return;}// 同じIDが存在したら追加できないthrownewDuplicateIdException();}publicsynchronizedvoidupdate(intid,StringfirstName){Employeeemployee=select(id);employee.setFirstName(firstName);}publicsynchronizedvoiddelete(intid){Employeeemployee=select(id);employeeList.remove(employee);}}

EmployeeNotFoundExceptionDuplicateIdExceptionはそれぞれこんなクラスです。

EmployeeNotFoundException.java
publicclassEmployeeNotFoundExceptionextendsRuntimeException{publicEmployeeNotFoundException(){super("そのIDのEmployeeは見つかりません。");}}
DuplicateIdException.java
publicclassDuplicateIdExceptionextendsRuntimeException{publicDuplicateIdException(){super("そのIDのEmployeeはすでに登録されています。");}}

3. リソースクラス

いよいよAPIの部分です。MyResourceの改造ではなくて、新たにリソースクラスを作っていきます。
(別に改造でもいいんですが)

(1)初期データ

まずは簡単に初期データを登録しておいて、GETできるようにしましょう。
先ほどのリポジトリクラスの初期化処理に、初期データを入れておきます。

EmployeeRepository.java
privateEmployeeRepository(){employeeList=newArrayList<>();employeeList.add(newEmployee(3,"Cupcake"));employeeList.add(newEmployee(4,"Donuts"));employeeList.add(newEmployee(5,"Eclair"));employeeList.add(newEmployee(8,"Froyo"));employeeList.add(newEmployee(9,"Gingerbread"));}

名前に「ピン」ときたあなたは、ほくそ笑んでおいてください(笑)
Eclipseで頑張っていたあの時代・・・

(2)GETメソッドの作成

一番簡単なGETメソッド、さらにその中でもselectAllなAPIを作ります。

EmployeeResource.java
@Path("/employees")publicclassEmployeeResource{@GET@Path("/all")@Produces({MediaType.APPLICATION_JSON,MediaType.APPLICATION_XML})publicList<Employee>getAll(){returnEmployeeRepository.getInstance().selectAll();}}
  • @Path("/employees")
    • /employeesパスでアクセス
  • @GET
    • GETメソッド
  • @Path("/all")
    • 追加のパス。つまり、/employees/allでアクセスします
  • @Produces({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
    • JSONとXMLで返します。
    • 将来のためにXMLも返すように指定していますが、今回はまだJSONしか返しません。
  • EmployeeRepositoryのシングルトンからリストを取得

(3)index.jspを編集する

ブラウザからAPIにアクセスできるよう、index.jspにリンクを追加します。
お好みで見栄えを整えてください。

index.jsp
<p><a href="webapi/employees/all">All Employee List</a>

(4)リデプロイ

実行ボタンを押すと、以下のポップアップが表示されます。

redeploy.png

  • [Redeply]を選択
  • [OK]をクリック
  • ブラウザをリロード

これで変更が反映されるはずです。

reload.png

(5)動作確認

新しく作ったリンクをクリックしてみましょう。

get_all_json.png

JSONの配列が返ってきていますね。
Postmanやcurlでも確認できます。

4. パスパラーメータ付きGET

(1)リソースクラスにAPIメソッドを追加

今度は、idをパラメーターとして受け取って単独オブジェクトを返すAPIを作ってみましょう。

EmployeeResource.java
@GET@Path("/{id}")@Produces({MediaType.APPLICATION_JSON,MediaType.APPLICATION_XML})publicEmployeegetEmployee(@PathParam("id")intid){returnEmployeeRepository.getInstance().select(id);}

新しいのは@Path("/{id}")@PathParam()ですね。

  • @Path("/{id}")
    • 先ほど出てきた@Pathと同じで、アクセスパスの指定です。{id}は任意の値が入ることを示しています。つまり、APIを使う側は、xxxx/employee/3などのurlでアクセスすることになります。
  • @PathParam("id")
    • パス"{id}"に指定された値を受け取る変数を宣言しています。xxxx/employee/3でアクセスされると、id=3のEmployeeオブジェクトが渡ってきます。

(2)index.jspにリンクを追加

先ほどと同じく、index.jspにリンクを追加します。

index.jsp
<p><a href="webapi/employees/3">get id=3 employee</a>

(3)実行

リデプロイして、ブラウザを再読み込みし、追加したリンクをクリックしてみてください。

deploy_pathparam.png

ちゃんと返ってきました。
Postmanやcurlでも同様に確認できます。

5. クエリーパラメーター検索

今度はパスパラメーターではなく、クエリーパラメーターもやってみましょう。
/searchに対して、特定の文字(or文字列)を含むものだけ返すというのを作ってみます。

(1)検索メソッド

まずはリポジトリクラスです。
nameを受け取って、その文字列を含む名前のリストを作成して返します。

EmployeeRepository.java
publicList<Employee>search(Stringname){List<Employee>list=newArrayList<>();for(Employeeemployee:employeeList){if(employee.getFirstName().contains(name)){list.add(employee);}}if(list.size()>0)returnlist;thrownewEmployeeNameNotFoundException(name);}

EmployeeNameNotFoundExceptionは次のようなものです。

EmployeeNameNotFoundException.java
publicclassEmployeeNameNotFoundExceptionextendsRuntimeException{publicEmployeeNameNotFoundException(Stringname){super("文字列{"+name+"}を含む名前のEmployeeは存在しません。");}}

(2)リソースクラスにAPIメソッドを追加

EmployeeResource.java
@GET@Path("/all")@Produces({MediaType.APPLICATION_JSON,MediaType.APPLICATION_XML})publicList<Employee>searchEmployee(@QueryParam("name")Stringname){returnEmployeeRepository.getInstance().search(name);}

@QueryParamを使います。これはなんとなく予想がついたんじゃないでしょうか^^;

(3) 実行

index.jspにリンクを追加してもいいですが、もう面倒なのでPostmanを使いました(笑)
あるいは、ブラウザのURLに直打ちでもいいですね。

postman_query_param.png

JUnitテスト

先に動作テストをしてしまっていますが、JUnitテストも書いてみます。

1.依存関係の設定

Jerseyのテストフレームワークを使います。ただ、JUnit5に対応していないようなので、ちょっとしたハックが必要です。

以下の依存関係をtestスコープに追加します。

  • Jerseyのテストフレームワーク(grizzly)
    • サーバーを仮で立てるのにgrizzlyを使います。
  • AssertJ
    • アサーションを書くのに使います。お好みで他でもいいですし、JUnitの標準を使っても構いません。

以下のようにpom.xml<dependencies>タグ内に追加します。
JUnitの下が良いでしょうね。

pom.xml
<!-- https://mvnrepository.com/artifact/org.glassfish.jersey.test-framework.providers/jersey-test-framework-provider-grizzly2 --><dependency><groupId>org.glassfish.jersey.test-framework.providers</groupId><artifactId>jersey-test-framework-provider-grizzly2</artifactId><version>2.30.1</version><scope>test</scope></dependency><!-- https://mvnrepository.com/artifact/org.assertj/assertj-core --><dependency><groupId>org.assertj</groupId><artifactId>assertj-core</artifactId><version>3.15.0</version><scope>test</scope></dependency>

2. MyResourceのテスト

まずは簡単に、Myrecourceクラスのテストを書いてみます。
私はimportで悩んだのでimport文まで全て載せます。

MyResourceTest.java
packagecom.example;importorg.glassfish.jersey.server.ResourceConfig;importorg.glassfish.jersey.test.JerseyTest;importorg.junit.jupiter.api.AfterEach;importorg.junit.jupiter.api.BeforeEach;importorg.junit.jupiter.api.Test;importjavax.ws.rs.core.Application;importjavax.ws.rs.core.Response;importstaticorg.assertj.core.api.Assertions.assertThat;classMyResourceTestextendsJerseyTest{@OverrideprotectedApplicationconfigure(){returnnewResourceConfig(MyResource.class);}@BeforeEach@OverridepublicvoidsetUp()throwsException{super.setUp();}@AfterEach@OverridepublicvoidtearDown()throwsException{super.tearDown();}@TestpublicvoidgetIt(){finalResponseresponse=target("/myresource").request().get();Stringcontent=response.readEntity(String.class);assertThat(content).isEqualTo("Got it!\n\n");}}

テストは基本的に以下のステップで書いていけば良いかと思います。

  • JerseyTestを継承したテストクラスを作る
  • configureメソッドをオーバーライドする
  • @BeforeEach@AfterEachメソッドを作る
    • ここがJUnit5に対応させるための苦肉の策部分になります。JerseyTestクラスでは、JUnit4用の@Before@Afterが使われているのですが、JUnit5ではこれが呼び出されません。なので、わざわざラップしてやっています。面倒な場合は、エクステンションを作ってくださってる方などがいらっしゃるようなので、それを使うのも手かもしれません。
  • テストメソッドを作る
    • target("パス").request().get()でリクエストを投げてレスポンスを受け取る
    • response.readEntity(クラス名)で戻り値を取得する
    • アサーションで結果確認

実行してみましょう。

run_junit.png

ログを見ると、ポート番号が"9998"などで動いているのがわかりますね。

通過したら、残りのテストも書いていきましょう。

3. EmployeeResourceのテスト

MyResourceのテストを参考に書けると思います。

EmployeeResourceTest.java
packagecom.example;importorg.glassfish.jersey.server.ResourceConfig;importorg.glassfish.jersey.test.JerseyTest;importorg.junit.jupiter.api.AfterEach;importorg.junit.jupiter.api.BeforeEach;importorg.junit.jupiter.api.Test;importjavax.ws.rs.core.Application;importjavax.ws.rs.core.GenericType;importjavax.ws.rs.core.Response;importjava.util.List;importstaticorg.assertj.core.api.Assertions.assertThat;importstaticorg.junit.jupiter.api.Assertions.*;classEmployeeResourceTestextendsJerseyTest{@OverrideprotectedApplicationconfigure(){returnnewResourceConfig(EmployeeResource.class);}@BeforeEach@OverridepublicvoidsetUp()throwsException{super.setUp();}@AfterEach@OverridepublicvoidtearDown()throwsException{super.tearDown();}@TestvoidgetAll(){finalResponseresponse=target("/employees/all").request().get();List<Employee>content=response.readEntity(newGenericType<>(){});assertThat(content.size()).isEqualTo(5);assertThat(content.get(0)).isEqualToComparingFieldByField(newEmployee(3,"Cupcake"));assertThat(content.get(1)).isEqualToComparingFieldByField(newEmployee(4,"Donuts"));assertThat(content.get(2)).isEqualToComparingFieldByField(newEmployee(5,"Eclair"));assertThat(content.get(3)).isEqualToComparingFieldByField(newEmployee(8,"Froyo"));assertThat(content.get(4)).isEqualToComparingFieldByField(newEmployee(9,"Gingerbread"));}@TestvoidgetEmployee(){Employeeemployee=target("/employees/3").request().get(Employee.class);assertThat(employee).isEqualToComparingFieldByField(newEmployee(3,"Cupcake"));employee=target("/employees/4").request().get(Employee.class);assertThat(employee).isEqualToComparingFieldByField(newEmployee(4,"Donuts"));employee=target("/employees/5").request().get(Employee.class);assertThat(employee).isEqualToComparingFieldByField(newEmployee(5,"Eclair"));employee=target("/employees/8").request().get(Employee.class);assertThat(employee).isEqualToComparingFieldByField(newEmployee(8,"Froyo"));employee=target("/employees/9").request().get(Employee.class);assertThat(employee).isEqualToComparingFieldByField(newEmployee(9,"Gingerbread"));}@Testvoidsearch(){finalList<Employee>content=target("/employees/search").queryParam("name","a").request().get(newGenericType<>(){});assertThat(content.size()).isEqualTo(3);assertThat(content.get(0)).isEqualToComparingFieldByField(newEmployee(3,"Cupcake"));assertThat(content.get(1)).isEqualToComparingFieldByField(newEmployee(5,"Eclair"));assertThat(content.get(2)).isEqualToComparingFieldByField(newEmployee(9,"Gingerbread"));}}

getEmployeeのテストで、

Employeeemployee=target("/employees/3").request().get(Employee.class);

としています。get()に型を指定すると、readEntityをその型で処理した値を直接受け取れます。

また、searchのテストでは、queryParamを使って、クエリーパラメーターを指定しています。

感想

GET系は、たぶん、簡単です。まあ色々ハマりはしましたが。JerseyテストフレームワークがJUnit5に対応していないせいでテストが動かないとか。。。対処法はごく簡単なのに、何時間悩んだことか・・・(泣)

でも、XMLを返そうとしたり、POSTをやろうとしたらもっとハマったので、それを次回にします。
あと、例外系も次回やります。
今は存在しないidを指定して検索すると、500エラーになりますが、これを変えていきます。

参考ページ

いっぱい見たなあ・・・

IntelliJ+JerseyとPostmanでRESTfulAPIサンプル(POST/UPDATE/DELETE,例外処理,XML)

以下の記事の続きです。

目的

GET以外のAPI、例外ハンドリング、XMLでの応答が出来るようにします。
もうあんまりIntelliJ関係ないですけど。

各APIでセットしているステータスコードは、以下のサイトにある推奨のものにしています。

https://restfulapi.net/http-methods/

GOAL

  • POST/PUT(UPDATE)/DELETEが出来る
  • 例外ハンドリングが出来る
    • 500エラーではなくて404(Not Found)や309(Conflict)を返すようにする
  • XMLで応答が出来る

POSTメソッド

1.リソースクラスにAPIメソッドを追加

GETメソッドが@GETだったのだから、当然、POSTメソッドは@POSTを付けます。

EmployeeResource.java
@ContextUriInfouriInfo;@POST@Consumes({MediaType.APPLICATION_JSON,MediaType.APPLICATION_XML})publicResponseaddEmployee(Employeeemployee){EmployeeRepository.getInstance().insert(employee.getId(),employee.getFirstName());UriBuilderbuilder=uriInfo.getAbsolutePathBuilder();builder.path(String.valueOf(employee.getId()));returnResponse.created(builder.build()).build();}

@Contextで、実行環境に関する情報(コンテキスト)を取得できます。
ここでは、(参考にしたページのサンプルのままなのですが)ヘッダーに、追加したデータのアクセスURLを返してあげています。そのため、UriInfoが必要なので使っているようです。

2.動作確認

ここからはPostmanで確認していきます。

  • メソッドタイプを[POST]にする
  • [BODY]タブを選ぶ
  • [raw]を選ぶ
  • ドロップダウンから、[JSON]を選ぶ
  • 下記の文字列を設定する
    • {"firstName":"Honeycomb","id":11}
postman_post_json.png

実行してみてください。

postman_created.png

Statusが201 Createdになっていれば成功です。
また、[Headers]タブをクリックすると、レスポンスヘッダーが見られます。この中に、Locationという項目があり、Urlが入っているはずです。

post_header_location.png

Urlをコピペしてブラウザに貼り付ければ、新しいデータにアクセスできることが分かります。

3.余談

お急ぎの方は飛ばしてドウゾ。

Locationを返している部分ですが、参考にしたサイトは、String.formatを使って次のようにしていました。

String.format("%s/%s",uriInfo.getAbsolutePath().toString()

UnitTestは、これでlocalhost:xxxx/employees/11みたいに返ってくるのですが、ところが、これをPostmanやターミナルからcurlコマンドで実行すると、localhost:xxxx/empoloyees//11みたいに最後のパスセパレータ(/)がなぜか重複してしまい、当然そのままURLをコピペしたのではアクセス出来ません。

URLEncodeがらみと思って調査&試しましたが、どうやら違うようでした。
色々試行錯誤して、結局、上記の通り、UriBuilderを使うことで解決しました。

というお話でした(笑)

あとは、これまではブラウザアクセスしかしていなくて、「POSTするにはどうするんだ?クライアントアプリ作らなきゃならんの?」と思っていました。絶対ツールがあるはずだと思って探し、Postmanを知ったのは実はこの時でした(笑)

PUT(UPDATE)メソッド

1.リソースクラスにAPIメソッドを追加

GETメソッドが~~略

EmployeeResource.java
@PUT@Consumes({MediaType.APPLICATION_JSON,MediaType.APPLICATION_XML})publicResponseupdateEmployee(Employeeemployee){EmployeeRepository.getInstance().update(employee.getId(),employee.getFirstName());// 新規作成した場合はcreatedを返す必要があるが、このサンプルではエラーとするため、常にokを返すreturnResponse.ok().build();}

2.動作確認

  • Postmanで、メソッドタイプを[PUT]を選んで、jsonを入力
    • {"firstName":"Frozen yogurt","id":8}

Statusは200になればOKです。
続いて/allなどを叩いてみれば、該当のデータが変更されているのがわかります。

DELETEメソッド

1.リソースクラスにAPIメソッドを追加

GETメソッドが~~略

EmployeeResource.java
@DELETE@Path("/{id}")@Consumes({MediaType.APPLICATION_JSON,MediaType.APPLICATION_XML})publicResponsedeleteEmployee(@PathParam("id")intid){EmployeeRepository.getInstance().delete(id);// Entityの状態を返す場合はokを返す。// 受け付けたが処理が終わっていない場合は(キューに乗っただけなど)acceptedを返す// このサンプルでは削除が完了して該当コンテントがなくなったことだけ返すreturnResponse.noContent().build();}

2.動作確認

  • Postmanで、メソッドタイプを[DELETE]を選んで、パスを入力
postman_delete.png

Statusは204になればOKです。
続けて/allを叩いてみると、id=3が無くなっているはずです。

例外ハンドリング

さて、例外クラスをたくさん作ってきましたが、全く使われていません。いや、使われてはいるのですが、例外が起こると、500(Internal Server Error)が起きてしまいます。これだと、サーバー側でクラッシュしてしまっているかのようです。そうではなくて、単にデータが無いだけなので、404(Not Found)を返すようにしたいです。

これには、ExceptionMapperというのを使います。
次のようなクラスを作ります。

NotFoundExceptionHandler.java
@ProviderpublicclassNotFoundExceptionHandlerimplementsExceptionMapper<EmployeeNotFoundException>{publicResponsetoResponse(EmployeeNotFoundExceptionex){returnResponse.status(Response.Status.NOT_FOUND).build();}}

これは、EmployeeNotFoundExceptionが投げられたのを検知したら、ステータスコード404を返す、というハンドラーになります。

これで実行し、存在しないパスにアクセスしてみてください。
例えば、/employee/1ですね。

404が表示されましたか?以前は、500エラーが返っていたはずです。

これを、例外クラスごとに量産します。
(ああ、kotlinなら同じファイルに全部書けるのに・・・ファイルが無駄に増えなくていいのに・・・)

EmployeeNameNotFoundExceptionの場合も、404エラーでいいでしょう。
DuplicateIdExceptionの時は、409(conflict)を返しましょう。

DuplicateExceptionHandler.java
@ProviderpublicclassDuplicateExceptionHandlerimplementsExceptionMapper<DuplicateIdException>{publicResponsetoResponse(DuplicateIdExceptionex){returnResponse.status(Response.Status.CONFLICT).build();}}

存在するidに対して、POSTをしてみてください。

Statusが409になっていれば正常です。

conflict.png

XMLでの応答

1. どうでもいい愚痴

お急ぎの方は2へドウゾ(笑)

これがむちゃくちゃハマりました。
たぶん、JDKを8以下で実行してきていたら、ハマらなかったことでしょう。
大人の事情で11を使わないといけないので、そこでハマってしまっていました。

Jersey公式のサンプルや、他の解説ページをいくつも見ても、「XMLで応答を返すには、モデルクラス(Entity)に、@XmlRootElementって書いてAcceptapplication/xmlを指定すればいいんだよ」という情報しかなくて、でもそれだけだと、「500 Internal Server Error」になってしまい、何時間もさまよいました(T_T)

最終的に、こちらのページにたどり着いて、ようやく原因が分かりました。

JDKのバージョン別に何が変わったのか、そういえば調べていたのに、全く気づきませんでした(トホホ)
資料に書いたら忘れちゃうの、ダメですねえ。。。

ということで、JAXB関連の依存関係を追加し、モデルクラスに@XmlRootElementを付けるだけです。

2. 依存関係の追加

pom.xml<dependencies>下に次のように追加します。

pom.xml
<!-- https://mvnrepository.com/artifact/javax.xml.bind/jaxb-api --><dependency><groupId>javax.xml.bind</groupId><artifactId>jaxb-api</artifactId><version>2.3.1</version></dependency><!-- https://mvnrepository.com/artifact/javax.activation/activation --><dependency><groupId>javax.activation</groupId><artifactId>activation</artifactId><version>1.1.1</version></dependency><!-- https://mvnrepository.com/artifact/org.glassfish.jaxb/jaxb-runtime --><dependency><groupId>org.glassfish.jaxb</groupId><artifactId>jaxb-runtime</artifactId><version>2.3.2</version></dependency>

3. XMLエレメントを示すアノテーションの追加

Employeeクラスにアノテーションを付けます。

Employee.java
@XmlRootElementpublicclassEmployee{...

これだけです。

4. 動作確認

PostmanでAcceptタイプを指定して試してみましょう。

(1)application/jsonを指定

postman-accept-json.png

(2)application/xmlを指定

postman-accept-xml.png

なお、ブラウザ(Chrome)だと、xmlがデフォルトで返ってくるようですが、PostmanはAcceptタイプを指定しない場合はjsonで返ってくるようです。

他のメソッドについても試してみてください。

JUnitテスト

ここまでのJUnitテストも書いておきます。
それと、せっかくJUnit5を使っているので、GETのテストをパラメタライズテストにしてみようと思います。
さらに、xmlも受け取れるようになったので、そのテストを追加します。

1. パラメタライズテスト

パラメタライズテストとは、パラメータの配列を渡して、パラメータ違いのテストを繰り返し行える機能のことを言います。
書き方は簡単。

  • @Testから@ParameterizedTestにアノテーションを変える
  • @ValueSourceでパラメータの配列を渡す

簡単ですね。もう少し色々複雑なこともできるのですが、とりあえずこれができれば十分かと思います。

EmployeeResourceTest.java
@ParameterizedTest@ValueSource(ints={3,4,5,8,9})publicvoidgetEmployee(intid){StringurlPath=String.format("/employees/%d",id);Employeeemployee=target(urlPath).request().get(Employee.class);Employeeexpect=EmployeeRepository.getInstance().select(id);assertThat(employee).isEqualToComparingFieldByField(expect);}

これで、引数id{3,4,5,8,9}という値を順番に使って繰り返しテストをしてくれます。
実行すると、こんな結果表示がされます。
リストが見えない場合は、チェックアイコンをクリックしてみてください。
parametrize_test.png

繰り返しのテストを書くのが楽になりました。

2. XMLのテスト

(1)GET系

GET系は、Accept別にちゃんと通過するかテストを追加します。これもまた、パラメタライズテストで出来ます。

EmployeeResourceTest.java
@ParameterizedTest@ValueSource(strings={MediaType.APPLICATION_JSON,MediaType.APPLICATION_XML})publicvoidgetAll(StringmediaType){finalResponseresponse=target("/employees/all").request().accept(mediaType).get();assertThat(response.getHeaderString("Content-Type")).isEqualTo(mediaType);...}

そうしたら、getEmployeeのテストも、jsonの時とxmlの時で分けたいですね。
すると、複数のテストパラメーターが必要になってきます。

こういう時には、MethodSourceを使ってパラメータを作って渡します。

EmployeeResourceTest.java
@ParameterizedTest@MethodSource("getParamProvider")publicvoidgetEmployee(intid,StringmediaType){StringurlPath=String.format("/employees/%d",id);finalResponseresponse=target(urlPath).request().accept(mediaType).get();assertThat(response.getHeaderString("Content-Type")).isEqualTo(mediaType);Employeeemployee=response.readEntity(Employee.class);Employeeexpect=EmployeeRepository.getInstance().select(id);assertThat(employee).isEqualToComparingFieldByField(expect);}staticStream<Arguments>getParamProvider(){returnStream.of(Arguments.of(3,MediaType.APPLICATION_JSON),Arguments.of(4,MediaType.APPLICATION_JSON),Arguments.of(5,MediaType.APPLICATION_JSON),Arguments.of(8,MediaType.APPLICATION_JSON),Arguments.of(9,MediaType.APPLICATION_JSON),Arguments.of(3,MediaType.APPLICATION_XML),Arguments.of(4,MediaType.APPLICATION_XML),Arguments.of(5,MediaType.APPLICATION_XML),Arguments.of(8,MediaType.APPLICATION_XML),Arguments.of(9,MediaType.APPLICATION_XML));}

parameterized_matrix.png

まあこんなに必要はないですが、MethodSourceのサンプルということで。

(2)POST

POSTのテストも、jsonをPOSTした場合とxmlをPOSTした場合のテストが必要ですが、これもパラメタライズで出来てしまいます。
ただ、気をつけないといけないのは、セッションが切れていないようなので、staticなEmployeeRepositoryには追加されたデータが残ります。重複追加はエラーになる仕様にしているので、同じ物を追加はできないということに注意して、プロバイダーを作る必要があります。

EmployeeResourceTest.java
@ParameterizedTest@MethodSource("postRawProvider")publicvoidaddEmployee(intid,StringbodyRaw,StringmediaType){finalResponseresponse=target("/employees").request().post(Entity.entity(bodyRaw,mediaType));assertThat(response.getStatus()).isEqualTo(201);assertThat(response.getHeaderString("Location")).isEqualTo("http://localhost:9998/employees/"+id);}staticStream<Arguments>postRawProvider(){finalStringjson="{\"firstName\":\"Honeycomb\",\"id\":11}";finalStringxml="<?xml version=\"1.0\" encoding=\"UTF-8\"?>"+"<employee><firstName>KitKat</firstName><id>19</id></employee>";returnStream.of(Arguments.of(11,json,MediaType.APPLICATION_JSON),Arguments.of(19,xml,MediaType.APPLICATION_XML));}

追加するid,jsonまたはxmlの文字列,MediaTypeを引数で渡しています。

3. PUT/DELETEのテスト

PUT, DELETEのテストを追加します。PUTはjsonとxmlの両方をテストします。

該当箇所は全部でこうなります。

EmployeeResourceTest.java
@ParameterizedTest@MethodSource("putRawProvider")publicvoidupdateEmployee(intid,StringbodyRaw,StringmediaType){finalResponseresponse=target("/employees").request().put(Entity.entity(bodyRaw,mediaType));assertThat(response.getStatus()).isEqualTo(200);Employeeemployee=target("/employees/"+id).request().get(Employee.class);Employeeexpected=EmployeeRepository.getInstance().select(id);assertThat(employee).isEqualToComparingFieldByField(expected);}staticStream<Arguments>putRawProvider(){finalStringjson="{\"firstName\":\"Frozen yogurt\",\"id\":8}";finalStringxml="<?xml version=\"1.0\" encoding=\"UTF-8\"?>"+"<employee><firstName>Cup Cake</firstName><id>3</id></employee>";returnStream.of(Arguments.of(8,json,MediaType.APPLICATION_JSON),Arguments.of(3,xml,MediaType.APPLICATION_XML));}@TestpublicvoiddeleteEmployee(){finalResponseresponse=target("/employees/9").request().delete();assertThat(response.getStatus()).isEqualTo(204);}

3. 例外系

例外をハンドリング出来るようになったので、これもテストしましょう。

(1)コンフィグを追加

何もしないと、ExceptionMapperはテスト中には実行されません。
次のようにテストのコンフィグに追加します。

EmployeeResourceTest.java
@OverrideprotectedApplicationconfigure(){returnnewResourceConfig(EmployeeResource.class)// 以下を追加.register(DuplicateExceptionHandler.class).register(NameNotFoundExceptionHandler.class).register(NotFoundExceptionHandler.class);}

(2)例外系テストメソッドの作成

  • selectに存在しないidを指定した時
  • searchに存在しない文字列を指定した時
  • postに既存のidを指定した時
  • putに存在しないidを指定した時
  • deleteに存在しないidを指定した時

これくらいでしょうか。
該当テストコードは以下のようになります。

EmployeeResourceTest.java
@Testpublicvoidexception_selectEmployee(){finalResponseresponse=target("/employees/1").request().get();assertThat(response.getStatus()).isEqualTo(404);}@Testpublicvoidexception_searchEmployee(){finalResponseresponse=target("/employees/search?name=android").request().get();assertThat(response.getStatus()).isEqualTo(404);}@ParameterizedTest@MethodSource("putRawProvider")publicvoidexception_addEmployee(intid,StringbodyRaw,StringmediaType){finalResponseresponse=target("/employees").request().post(Entity.entity(bodyRaw,mediaType));assertThat(response.getStatus()).isEqualTo(409);}@ParameterizedTest@MethodSource("putExceptionProvider")publicvoidexception_updateEmployee(intid,StringbodyRaw,StringmediaType){finalResponseresponse=target("/employees").request().put(Entity.entity(bodyRaw,mediaType));assertThat(response.getStatus()).isEqualTo(404);}staticStream<Arguments>putExceptionProvider(){finalStringjson="{\"firstName\":\"Lollipop\",\"id\":21}";finalStringxml="<?xml version=\"1.0\" encoding=\"UTF-8\"?>"+"<employee><firstName>Jelly Bean</firstName><id>17</id></employee>";returnStream.of(Arguments.of(21,json,MediaType.APPLICATION_JSON),Arguments.of(3,xml,MediaType.APPLICATION_XML));}@Testpublicvoidexception_deleteEmployee(){finalResponseresponse=target("/employees/1").request().get();assertThat(response.getStatus()).isEqualTo(404);}

putRawProvider(PUTテスト用)をちょうどいいので使い回しています。
ただし使っているのはexception_addEmployee(POSTの例外テスト)です。

感想

なかなかハマりどころの多い箇所でした。わかってしまえば単純なことだったりするのですが・・・

ここまでのコードを、Githubにアップしました。
https://github.com/le-kamba/JerseySample

次はAPI部分をモジュール分割してみます。
こんな形が理想ですね。

jerseysample
  |- pom.xml
  |- src/main/java/package/xxx/sampleapp
  |- serverapi
  |    |- pom.xml
  |    |- src/main/java/package/yyy/server
  |- repository
       |- pom.xml
       |- src/main/java/package/zzz/repository

依存関係の書き方や実行方法の実験を兼ねているため、リポジトリ層も分けてみます。

参考

Postmanでログイン状態を維持する

この記事でやること

  1. アクセストークンをもらうためのAPIをPostmanで叩き、帰ってきたアクセストークンをPostmanの環境変数を利用して永続的に保存する。

  2. 保存した値を、認証が必要なリクエストを送る前に動的にヘッダーにセットする。

なにが嬉しいか

Postman1がアクセストークンを保持できるので、ブラウザでいういわゆる「ログイン状態」を維持することができる。

手順

1. ログインAPI(アクセストークンをもらうためのAPI)のタブを開く

2. Testsの項目で、レスポンスヘッダーの値を受け取る。

Testsという項目は、APIのレスポンスが帰ってきたあとの処理をNode.jsベースでランタイムに書けるところ。一言で言えば、JavaScriptが書ける。

ヘッダーの値をPostmanの環境変数にセットする処理の例が以下。

スクリーンショット 2020-03-14 19.30.10.png

tests.js
constheaders=responseHeadersconstok=responseCode.code===200if(ok){pm.globals.set('uid',headers.uid)pm.globals.set('client',headers.client)pm.globals.set('access-token',headers['access-token'])}

このコードは、APIから帰ってきたレスポンスのヘッダーを取得し、それをPostman上の環境変数にセットするための記述です。

素直な処理なのでわかりやすいとは思いますが、以下だけ、PostmanSandboxAPI2を利用している特殊な処理なので注意です。

pm.globals.set('uid',headers.uid)

これは一言でいえば、「Postmanの環境変数として、uidというプロパティ名で、レスポンスヘッダーのuidの値をセットします」ということです。

認証のために「uid」「client」「access-token」の三種類を利用しているアプリケーションの場合は、以下のように三種類に対する処理が必要となります。

pm.globals.set('uid',headers.uid)pm.globals.set('client',headers.client)pm.globals.set('access-token',headers['access-token'])

3. Testsに記述後、APIをPostmanで叩く

リクエストボディに、ログインのための認証情報を入力して、Postする。

スクリーンショット 2020-03-14 19.32.32![スクリーンショット 2020-03-14 19.34.47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/324456/4ace0e09-73bd-2f3a-40ad-bdce1bbf1f2e.png)<br>
.png

4. レスポンスを受け取ったあと、環境変数としてアクセストークン等が保存されているかチェック

画面右上の歯車(画像でいう右側)をクリックして、
スクリーンショット 2020-03-14 19.34.47.png

「Globals」に値が保存されていたらOK。

スクリーンショット 2020-03-14 19.33.47.png

5. Postmanの環境変数を、リクエスト前に送る

先程は、Testsという項目を利用して、レスポンス後にJavaScriptで処理を走らせたが、次は「Pre-request Scripts」という項目を利用し、リクエスト前にJavaScriptを走らせるよう記述する。

Pre-request Scriptsは、コレクション単位で設定できるので、コレクションの編集をしよう。コレクションというのは、複数のリクエストタブを一つにグルーピングしているものである。

まずは、「Edit」でコレクションの編集画面に移動する。

スクリーンショット 2020-03-14 19.19.29.png

その後、Pre-request Scriptsのタブに移動し、リクエスト前に行ってほしい必要な処理を記述する。

スクリーンショット 2020-03-14 19.19.59.png

// pm.globals.getで、引数に与えたプロパティ名の環境変数を取得するconstuid=pm.globals.get('uid')constaccess_token=pm.globals.get('access-token')constclient=pm.globals.get('client')// pm.request.headers.add で、リクエストのヘッダーに、任意のプロパティ名と値をセットできる。pm.request.headers.add({key:'uid',value:uid})pm.request.headers.add({key:'access-token',value:access_token})pm.request.headers.add({key:'client',value:client})

これで、実質的にログイン状態を維持したまま、Postmanを利用することが出来る。


  1. Postmanとは? → API開発のさいに便利なデスクトップアプリケーション。詳しくは公式へ: https://www.postman.com/ 

  2. PostmanSandboxAPIとは? → Postman上で利用できるAPI。 詳しくは公式リファレンスへ。https://learning.postman.com/docs/postman/scripts/postman-sandbox-api-reference/ 

Postmanとバイナリと脆弱性

Postmanとバイナリと脆弱性(部屋とワイシャツと私)、愛するあなたのため〜♪

ぶち当たった問題

Postmanのパラメータに、%82または0x82というバイナリの文字列をどうやって渡せばよいのか?

これはダメだ

0x82を適当にエディタで開くと

と表示される。

お!これが、バイナリかー。よし、これをコピペして、
スクリーンショット 2020-03-28 11.48.55.png
VALUEに貼り付けて送ってもバイナリで送信されていない。。
何かしらの文字として送信されている。
バイナリエディタでを調べてみると、
EFBFBD
という、文字になっている。
これはダメだ。

どうしようか

スクリーンショット 2020-03-28 16.54.39.png

ここのbinaryを選択。
そうするとファイルを選択できる。
スクリーンショット 2020-03-28 16.56.05.png

ファイルにPOSTデータを記述できればOKだ。
例えば、
binary=0x82
となればよい。

バイナリエディタには
Hex Fiend
を使用した。

エディターを立ち上げて
62696E61 72793D82
と記述すればOKだ。

62696E61 72793Dbinary=
82が渡したいパラメータになる。

このファイルをテキストで保存する。

このファイルを開くと(開き方にもよるが)、
binary=�となる。例のひし形の?を確認できる。

出来上がったファイルを先ほどのselect fileで指定する。
そしてSendボタンを押せば送信できる。

しかし思い通りにはならない

Sendボタンを押しても想定通りの動きをしていない。
どうやらパラメータが渡っていないようだ。

原因はPostman経由で送信すると自動で
Content-Type: text/plain
が付与されてしまう。

こいつを消すには
スクリーンショット 2020-03-28 17.15.53.png

右にあるCodeを選択。
メニューから好きな項目を選んで
スクリーンショット 2020-03-28 17.17.51.png

右のコードをテキストファイルに貼り付ける。
cURLの例だが--header 'Content-Type: text/plain' \
を削除する。
そして残ったコードをコマンドに流せばOKである。

すると、、

私の開発環境の話ではあるが、今までは正常にjsonを返していたレスポンスに
Fatal Error
という文言を確認することができた。想定通りである。(正気か?)

Redfishを使ってサーバーの状態監視

Redfishを使ってサーバーの状態監視

Redfish、何それ美味しいの?

従来サーバー監視はIPMIToolやベンダー固有の管理ツールを使うのが定番でしたが、
最近APIを通して共通化しようという試みも出てきているようです。
サーバー屋さん的にはどうなのかね?という感じもありますが、まずはお試し。

今回は2つの方法で基本情報の取得。
1,Postmanを使う
2,Curlを使う

1,Postmanを使う

PostmanをノートPCにインストール
https://www.postman.com/downloads/

デスクトップのアイコンをクリックしてPostmanを開き、
アドレスバーにIPアドレスと/redfish/v1/Systems/1/くらいまで入れて
authorizationをBasic AuthにしてIPMIのユーザーとパスワードを入れるとサーバーと繋がります。

GET IPアドレス/redfish/v1/Systems/1/
postman02.JPG

Body内になるリンク/redfish/v1/System/1をクリックすると、下の画像のようなサーバーのFRU項目が出てきます。
postman03.JPG

IPMIではなかなか取れないNICの情報も取れる。
GET IPアドレス/redfish/v1/Systems/1/EthernetInterfaces/1
postman04.JPG

Memoryのスピードや型番、状態も取得可能。
GET IPアドレス/redfish/v1/Systems/1/Memory/1
postman05.JPG

各項目ごとに掘り下げていくと情報が色々と確認出来、JSONだけでなく色々な形式で出力できるので
独自に作成した管理ツールがある人にはに便利かも。知らんけど。

2,Curlを使う

ノートPCではなく、管理用のLinux端末からRedfish経由で情報を見たい場合は
curlを使用するとコマンドラインでできるのでスクリプト化してもいいかも。

curlは色々できるようですが、とりあえず監視だけなら
curl -u ユーザー:パスワード -X GET 'https://IPアドレス/redfish/v1/Systems/1/項目'
で情報取得は可能。
curl00.JPG

ただ、これだと非常に見辛いので、|(パイプ)とjqを使ってJSON形式で見やすく変換した方が良さげです。
jqのインストールはいたって簡単。
$sudo yum -y install epel-release
$sudo yum -y install jq

jqで必要な情報だけ.ドット+項目を,で羅列すると見やすくなりました。(前後はシングルクォーテーション)

ネットワークの常態とMACアドレス調べ
curl -k -u ADMIN:ADMIN -X GET 'https://IPアドレス/redfish/v1/Systems/1/EthernetInterfaces/1' |jq '.Description, .Status, .MACAddress'

Memoryのスロットごとの容量と状態調べ
curl -k -u ADMIN:ADMIN -X GET 'https://IPアドレス/redfish/v1/Systems/1/Memory/1' |jq '.Name, .CapacityMiB, .Status'
curl01.JPG


掘り下げれば色々出来そうな感じはありますが、まずはRedfishで情報を取る方法はこれで良しとする!

FirebaseとPostmanを使って短縮URLを複数取得する方法

はじめに

短縮URLサービスは、一般的に1つのURLの短縮を想定されていることが多い。
(例)https://bitly.com

今回、パラメータが異なる複数のURLを短縮したいと思ったが、そういうサービスはぱっと探した感じなかったので、FirebasePostmanを使って実現した。

動機

GoogleFormでアンケートに回答してもらう際、あらかじめ回答を事前に入力できる機能がある。
(例)https://docs.google.com/forms/d/e/1FAIpQLSdVnE7pHvFJ6-9Y5XZDy8Yz6MdBFEkj9QTR_qwNuDnSTNaQXw/viewform?usp=pp_url&entry.1563907928=1
上のURL中、entry.1563907928=1で回答値を設定している。entry.1563907928は設問項目名、1の値を変えることで事前入力値を設定できる。

目的としては、上記機能を使って、異なる事前入力値を持つ複数のURLを発行することだが、だいぶ長いので短縮したいなと思ったのがきっかけ。

Firebaseとは

少し前まで「Google URL Shortener」があったがサービス終了し、今はFirebaseのDynamic Linksで発行できる。
独自ドメインでの発行もできることから、今回はFirebaseを使う。
Firebaseの詳細は別記事を参照。

本記事では短縮URL発行だけが目的なので、プロジェクトだけ作成すればOK。

参考:[Firebase] プロジェクトを新規に作成する

Firebaseを使った短縮URL発行 (REST API経由)

Dynamic Linksでリンクを発行する方法は4つある

  1. Firebase コンソールを使用
  2. iOS と Android で Dynamic Link Builder API を使用
  3. REST API を使用
  4. 手動

引用:https://firebase.google.com/docs/dynamic-links/create-links?hl=ja

1のFirebase コンソールにはそのような機能はなく、2だと別途アプリ開発環境が必要なので、今回は3.REST APIでリンクを発行する。

REST APIで短縮URLを発行する方法は、すでにGoogleがまとめているので下記記事を参照。

(Google)REST API を使用したダイナミック リンクの作成

上記記事に沿って、始める前にの1,2,3を実行。

これでFirebase側の設定は完了。

Postmanのインストール

PostmanはRESTサービスの一つ。自動化しやすいのが特徴とのこと。詳しくはこちら
ネイティブアプリが必要なので下記からインストール。
Postman

Postmanを使って複数の短縮URLを発行

Firebase側のREST APIをたたく。
サンプルコードは↓。

POST https://firebasedynamiclinks.googleapis.com/v1/shortLinks?key=api_key
Content-Type: application/json

{
  "dynamicLinkInfo": {
    "domainUriPrefix": "https://example.page.link",
    "link": "https://www.example.com/",
    "androidInfo": {
      "androidPackageName": "com.example.android"
    },
    "iosInfo": {
      "iosBundleId": "com.example.ios"
    }
  }
}

引用:(Google)パラメータから短いリンクを作成する

これをPostmanでたたく方法は下記の通り。

1. リクエストを作成:New → Request → プロジェクト名を入れてSave.

スクリーンショット 2020-04-12 20.17.47.png

スクリーンショット 2020-04-12 20.18.08.png

2. パラメータ(Params)の設定

  • 「POST」に変更
  • key-valueを設定。VALUEにはFirebaseで取得したapi_keyを入力。 スクリーンショット 2020-04-12 20.19.04.png

3. Bodyの設定

スクリーンショット 2020-04-12 20.19.14.png

{
    "dynamicLinkInfo": {
        "domainUriPrefix": "https://{yourDomain}", //設定している場合はドメイン名。
        "link": "https://docs.google.com/forms/d/e/1FAIpQLSdVnE7pHvFJ6-9Y5XZDy8Yz6MdBFEkj9QTR_qwNuDnSTNaQXw/viewform?usp=pp_url&entry.1563907928={{num}}" //GoogleFormのURL。`{{num}}`は変数なのでそのまま。
    },
    "suffix": {
        "option": "SHORT" //`SHORT`にすると最低文字数4文字で生成される。
    }
}

4. 環境変数の設定

アンケートフォームの事前入力値を「1,2,3…」とインクリメントさせるため、環境変数とTestsでnumを操作。

右上の歯車マーク → Globals → 変数を追加

スクリーンショット 2020-04-12 20.19.38.png

スクリーンショット 2020-04-12 20.19.46.png

VARIABLEINITIAL VALUECURRENT VALUE
num11

5. Testsの設定

スクリーンショット 2020-04-12 20.19.22.png

var num = Number(environment.num); //環境変数numの取得
tests["counter:" + num] = true; //結果の取得用。
pm.environment.set("num", ++num); //次の実行のためnumをインクリメント

6. クエリを複数回実行するためのRunnerを設定

Runner機能はこちらを参照。
下記からRunnerを起動。
スクリーンショット 2020-04-12 20.19.22 2.png

作成したPOSTを選択し、Save responsesにチェック。
Iterationsは実行回数。
Runで実行。
スクリーンショット 2020-04-12 20.21.55.png

結果、Response Bodyで短縮URLが得られる。
スクリーンショット 2020-04-12 20.22.33.png

Postmanの実行結果「Responses」をファイルで取得

複数の短縮URLは生成されたが、Postman上ではプロパティから値を確認できるだけ。一個一個確認するのは手間なので、実行結果を一気にファイル出力したいと思う。

調べたらファイル書き出し用のコードが用意されていたので、下記手順で実行することでファイルが書き出された。
Write Responses To File
(Github)ResponseToFile-Postman

日本語の説明が見当たらなかったので、念のため記載。

  1. Postmanのネイティブアプリを立ち上げておく
  2. Write Responses To Fileにアクセス
  3. ► Run In Postmanをクリック。アプリが立ち上がるので、collectionをインポート。
  4. ResponseToFile-Postmanを自機にクローン。あるいはコマンドでクローン。git clone https://github.com/sivcan/ResponseToFile-Postman
  5. クローンしたディレクトリを開いてインストール。コマンドはnpm i
  6. ローカルサーバを起動。コマンドはnode script.js
  7. これで実行結果は、新しく生成されるResponsesディレクトリに格納される。

保存されるファイルの拡張子や保存場所を変更したい場合、↑の3でインポートしたcollection「Write Responses To File」を、Edit Collectionで編集。
スクリーンショット 2020-04-13 0.03.57.png

取得例↓
ファイル名:「test_post_1.csv」

{"shortLink": "{Firebaseで生成された短縮URL}}

ファイルは実行回数分生成される。

おわりに

あとは生成されたファイルをcatでマージし、まとめられたファイルからshortLinkの行を抽出、valueのみ切り出せば、全ての短縮URLが得られる。

参考
ファイルを結合するには
[Excel] データを抽出する方法(フィルター機能)

対象URLのQRコードもほしかったので、GoogleSpreadSheetでQRコードを生成した。

GoogleスプレッドシートのIMAGE関数でQRコードを作成する方法


追記

短縮URLを複数取得する方法、他にも全然あった笑
URLShorter(フリーソフト) →bit.ly / j.mp
[非エンジニア向け]短縮URLを一括で大量に作る方法 →bit.ly

まあFirebaseなら、「1 つの IP アドレスで 1 秒あたり 5 回、1 日あたり 200,000 回という制限」、bit.lyは「1 分あたり最大 10,000 個のリンクを短縮する。月次最大数は、1 カ月あたり 10,000 個」らしいので、用途に応じて選ぶと良いかも。

Postmanを使ってStravaのAPIをたたいてみる

はじめに

Postmanを使ってStravaのAPIを叩き、アクティビティ情報を取得するまでの流れを説明する記事です

以前、StravaのAPIにアクセスしてアカウント情報を取得するの記事で、StravaのAPIをたたくまでの一連の流れを説明しました。
ただ、使う際にいちいちソースコード書いたりすることが面倒に感じ、今回Postmanを使ったお手軽API体験をしたので記事に残します。

Postmanとは

Postman.com
気軽にAPIを叩ける超便利ツールです。
今回初めて使ったのですが、思った以上に便利で簡単に使えました。

Stravaとは

参照:
StravaのAPIにアクセスしてアカウント情報を取得する

本題

~Stravaへのアプリ登録まで

参照:
StravaのAPIにアクセスしてアカウント情報を取得する

今回はこのような内容として登録してあります。
image.png

AccessToken取得

stravaにアプリを登録すると以下の情報が与えられます。

  • クライアントid
  • クライアントシークレット
  • アクセスToken

そもそもこの与えられたアクセスTokenを使えば簡単にWebAPIを叩けるのですが、アクセス範囲が範囲:読み取りで固定となっています。
そのため簡単なアスリート情報などは取得できるのですが、アクティビティ情報などは見ることができません。

アクティビティを参照するためにはactivity:readのスコープにおけるアクセスTokenが必要となるので、
このアクセスTokenをPostmanを利用して取得していきたいと思います。

PostmanによるアクセスToken取得

インストール部分は省略します

  • ユーザー登録?を求められますが特に登録は必要ないです。
  • とりあえず使いたい場合でも、Collectionの作成、Requestの登録を行わなくちゃいけないのが少しわかりづらかった。
    • これまで使ってたAdvanced REST Clientはそういうのなかったので

リクエスト作成

新規にRequestを作成したらAuthorizationのタブを選択し
TYPEをOAuth2.0とし、Get New Access Tokenのボタンを押します。
image.png

すると、AccessTokenを取得するために必要なパラメータが求められるので
アプリ登録時に与えられた以下の情報を入力していきます。

  • クライアントid
  • クライアントシークレット

ちなみにAuthURLや、AccessTokenURLなどに関しては公式ドキュメントに記載がありました。
また、Scopeに関しては自分が取得したい情報に合わせて設定します。
今回はアクティビティ情報を取得したいのでactivity:readとしました。

image.png

入力が完了したら、Request Tokenを押します。
そうするとPostman上でStravaへのサインインが求められるかと思うのでサインインを行い、認証の承認も行います。

image.png

すると、以下のような画面に遷移するかと思うのでUse Tokenを押せば自動でAccessTokenがセットされます。
image.png

WebAPIの利用

ここまでこればあとはURLを叩くだけです。

  1. Postmanの[Get]となっている部分に利用したいAPIのURLを記入
  2. 必要となるパラメータを追加
  3. Sendボタンを押す

を行えば完了です。
無事Activity情報を取得できました。

image.png

最後に

Postmanを利用すれば簡単にWebAPIを利用することができました。
気軽にWebAPIを叩いて個人開発に活かしていきたいですね。

また、StravaのWebAPIのDocumentは個人的に少しわかりづらかったので
この記事で少しでも気軽に使えるようになってもらえればと思います。

PostmanでTencentCloudのAPIを利用するについて

背景

TencentCloudのAPIをPostmanで利用したい時、どのようにすればいいか悩む方はいらっしゃるかと思いますので、
この記事では、PostmanでTencentCloudのAPIを利用できる環境設定の手順を紹介します。

1.Collection Pre-request Scriptを設定する

目的:

CollectionのPre-request Scriptの中でbuild_request関数を定義します。この関数は、公式のTencent Cloudドキュメントが提供するメソッドに従って、HTTP要求ヘッダーのフィールドを生成するために使用されます。Tencent CloudのID検証がTencent Cloudのさまざまなクラウド製品にアクセスできるように、署名の生成に重点が置かれています。この関数をCollectionに追加するのはCodeの再利用も目的であるため、Collection内の各リクエストはリクエストパラメータを定義するだけで済みます。

Postmanでの設定場所:

新しくCollectionを作るか、既存のCollectionのeditで以下のキャプチャのように設定スクリプトを追加します。
image1.png
スクリプト:

pm.globals.set("TencentCloudApi",functionTencentCloudApi(){lettencentcloudapi={};functionsha256_hex(msg){varutf8_str=CryptoJS.enc.Utf8.parse(msg);varsha256_str=CryptoJS.SHA256(utf8_str);varsha256_hex_str=CryptoJS.enc.Hex.stringify(sha256_str);returnsha256_hex_str;}functionsign_hmac256(key,msg){varutf8_str=CryptoJS.enc.Utf8.parse(msg);varhash_str=CryptoJS.HmacSHA256(utf8_str,key);returnhash_str;}functionsign_hmac256_hex(key,msg){varutf8_str=CryptoJS.enc.Utf8.parse(msg);varhash_str=CryptoJS.HmacSHA256(utf8_str,key);varhex_str=CryptoJS.enc.Hex.stringify(hash_str);returnhex_str;}functionget_pm_env_or_global(key){return(pm.environment.get(key)!==undefined)?pm.environment.get(key):pm.globals.get(key);}tencentcloudapi.build_request=functionbuild_request(params){varservice=pm.environment.get("service");varhost=service+get_pm_env_or_global("tencentcloud_endpoint");varregion=pm.environment.get("region");varversion=pm.environment.get("version");varaction=request.headers["X-TC-Action"];varalgorithm="TC3-HMAC-SHA256";vartimestamp=Math.round(Date.now()/1000);vard=newDate();vardate=d.toISOString().split('T')[0];// step 1:create canonical_requestvarhttp_request_method="POST";varcanonical_uri="/";varcanonical_querystring="";// tencentcloud suggests to add charset=utf-8, however postman will set content-type to// application/json when request data format json is selected. So we don't add charset.//content_type = "application/json; charset=utf-8";varcontent_type="application/json";varrequest_json_payload=JSON.stringify(params);varcanonical_headers="content-type:"+content_type+"\nhost:"+host+"\n";varsigned_headers="content-type;host";varhashed_request_payload=sha256_hex(request_json_payload);varcanonical_request=http_request_method+"\n"+canonical_uri+"\n"+canonical_querystring+"\n"+canonical_headers+"\n"+signed_headers+"\n"+hashed_request_payload;//console.log('canonical_request');//console.log(canonical_request);// step 2:create signing_stringvarcredential_scope=date+"/"+service+"/"+"tc3_request";varhashed_canonical_request=sha256_hex(canonical_request);varstring_to_sign=algorithm+"\n"+timestamp.toString()+"\n"+credential_scope+"\n"+hashed_canonical_request;//console.log('string_to_sign');//console.log(string_to_sign);// step 3:calculate signaturevarsecret_id=get_pm_env_or_global("secret_id");varsecret_key=get_pm_env_or_global("secret_key");varsecret_date_key=CryptoJS.enc.Utf8.parse("TC3"+secret_key);varsecret_date=sign_hmac256(secret_date_key,date);varsecret_service=sign_hmac256(secret_date,service);varsecret_signing=sign_hmac256(secret_service,"tc3_request");varsignature=sign_hmac256_hex(secret_signing,string_to_sign);//console.log("signature");//console.log(signature);// step 4:create authorizationvarauthorization=algorithm+""+"Credential="+secret_id+"/"+credential_scope+", "+"SignedHeaders="+signed_headers+", "+"Signature="+signature;//console.log("authorization");//console.log(authorization);// step 5: add HTTP headerspm.request.headers.add("X-TC-Region:"+region);pm.request.headers.add("X-TC-Timestamp:"+timestamp);pm.request.headers.add("X-TC-Version:"+version);pm.request.headers.add("Authorization:"+authorization);pm.request.headers.add("Host:"+host);// step 6: set environment variables using in requestpm.environment.set("host",host);pm.environment.set("request_json_payload",request_json_payload);};returntencentcloudapi;}+'TencentCloudApi();');

2.Environmentsを設定する

目的:

APIを利用する際の権限認証等の情報を設定します。

Postmanでの設定場所:

右上にあるEnviroment設定ボタンをクリックします。
image2.png
Addボタンをクリックします。
image6.png
CURRENT VALUEに以下のように情報を追加します。
(INITIAL VALUEに情報を記入する必要がありません。キャプチャは既存設定であるため自動的に記入されています。)
image5.png
追加する情報は以下となります。ここでは、LVBというライブ配信のプロダクトのAPIを例とします。

secret_id:ご自身のIDを記載してください
secret_key:ご自身のKeyを記載してください
region:ap-tokyo
service:live
tencentcloud_endpoint:.tencentcloudapi.com
version:2018-08-01

以下の情報は追加する必要はありません。すべての設定が完了すると、自動追加されます。

host
request_json_payload

これで環境設定は完了しました。次に、実際のAPIリクエストを実行してみます。

3.HTTPのリクエストBodyを設定する

先ほどCollectionのPre-requestでbuild_request関数で、リクエストのデータを環境変数のrequest_json_payloadに書き込むように設定したため、Bodyには{{request_json_payload}}のみ記載し、フォーマットをJSONに選択するだけでOKです。

以下のキャプチャをご確認ください。
image3.png

4.CreateLiveCallbackTemplateを作成する

 Pre-request ScriptでCreateLiveCallbackTemplateを作成します。
※ 上記リンクをクリックすると、TencentCloudのLVBのCreateLiveCallbackTemplateのAPIのドキュメントに飛びます。そこで、APIのリクエストパラメータ及びレスボンスパラメータを確認することができます。
image4.png

Scrpitの内容は以下となります。

varaction="CreateLiveCallbackTemplate";pm.request.headers.add("X-TC-Action:"+action);varparams={"TemplateName":"test","Description":"test","RecordNotifyUrl":"http://www.qq.com/api/notify?action=record","CallbackKey":"testkey"};eval(pm.globals.get('TencentCloudApi')).build_request(params);

あと、APIのURLhttps://live.tencentcloudapi.com/を記載して実際にAPIを叩くと、以下の様にテンプレートIDが返されますので、問題なくAPIを実行できました。
image.png

これで一通りPostmanでのTencentCloud APIの実行環境及びテストが終わりました。
あと少し補足ですが、JSON形式でAPIを実行する場合、HTTP POSTでリクエストする必要があります。

PostmanでLaravel Sanctumを使う手順

Larvel 7.xには「Laravel Sanctum」というSPAやモバイルアプリケーション向けの認証システムが用意されています。簡単にログイン・ログアウトができて大変便利なのですが、Postmanを使う際に色々と設定が必要だったので、ここに残しておきます。

とはいえ、海外のチュートリアルをそのまま日本語テキストにしただけなんですけどね...

英語のチュートリアル動画はこちら
https://codecourse.com/watch/laravel-sanctum-airlock-with-postman?part=laravel-sanctum-airlock-with-postman

それでは、やっていきましょう。

0. 事前情報

Dockerにて下記のイメージを使用しました。

  • nginx:latest
  • bitnami/php-fpm:latest
  • mariadb:latest

今回とは特に関係がありませんが、この環境でも問題なく動いたよという報告も兼ねて記載しておきます。

また、FiddleのHOSTを使って localhost:1000 qiita-sanctumとして登録しています。 http://qiita-sanctum/を叩けば、Laravelのトップページが表示されるようになっています。

以上が今回の環境です。


読む前に...下記の手順について追記

Collectionに「Pre-request Script」としてCSRFトークンを取得・セットする記述を行いましたが、login用のリクエストタブ内の「Pre-request Script」に追加するだけで十分なようです。

Collectionに設定してしまうと、他のリクエストを行う際も毎度まいどCSRFトークン発行をリクエストしてしまうので、余計な1リクエスト分を節約するためにも避けた方が良いかもしれません。(詳しいことは検証していないので、各自判断してください。)


1.environmentを作成する

c8438fa156129f157a6c7b7ca2a92ec2.png

  1. 目マークをクリックする。
  2. 「Add」をクリックする。

aa9bafc413c901cfd8f14a2eeadf4f36.png

  1. 適当にenvironmentの名前を付ける。(今回は「qiitaの環境」としました。)
  2. 「Add」で追加をする。
  3. Xボタンからモーダルを閉じる。

13acd1a6aa81d135ae8e578450df47ff.png

右上の欄から先程作成したenvironmentを選択する。(「qiitaの環境」を選択しました。)

2.Collectionを作成する

8bf8c0520564ff0c083ea6dd6b6c708c.png

  1. 「New Collection」をクリックする。
  2. 適当な名前を入力する。
  3. 「Create」でCollectionを作成する。

3.リクエストを諸々設定していく

リスエストを設定していく前に、リクエストをコレクションに保存しておく必要があります。

4897c36a29696df5259c093d4ee3bf93.png
4404bc38f325843c2b68b55dcadf539f.png

  1. ▼マークをクリックする。
  2. Save Asをクリックする。
  3. 先程作成した「Collection」を選択する。
  4. 「Save」をクリックする。

以上でコレクションへの保存は完了です。
次にリクエストを設定していきましょう。

0208444f4251c92007bd78cd7ec5a520.png

  1. POSTを選択する。
  2. LaravelのURL + /loginを入力する。(今回の環境では「qiita-sanctum/login」としました。)

14d9a3aa0df7ad76f37c3e710e6f686b.png

事前に作っておいたログイン用のアカウント情報を入力する。KEYには「email」と「password」と入力し、それぞれに沿った情報を入力する。

この状態で一旦、「Send」からリクエストを実行してみます。

9face4e321846c900e0f00ea17abf29d.png

エラーコード「419」が返ってきました。
これはCSRFトークンが添えられていないために起きる問題です。
Laravel Sanctumではログインを行う前にCSRFトークンを発行しておく必要があります。次の手順に進んでトークンを発行し、headerに含む設定を行います。

4.CSRFトークンを発行して適用する

f3be37292cc13a6b2a876e2964718861.png

  1. 先程作成したCollectionにカーソルを合わせて、三点リーダーのアイコンをクリックする。
  2. 「Edit」をクリックする。

2d7f06c6c6dc668a56228b924c747591.png

  1. 「Pre-request Scripts」タブを選択する。
  2. CSRFトークン取得・セットのスクリプトを記述する。
  3. 「Update」をクリックする。

(2)の記述は下記の通りです。

pm.sendRequest({
    url: 'http://qiita-sanctum/sanctum/csrf-cookie',
    method: 'GET'
}, function (error, response, { cookies }) {
    if (!error) {
        pm.environment.set('xsrf-token', cookies.get('XSRF-TOKEN'))
    }
})

Pre-request Scriptは、リクエストタブで指定したURLへのリクエストよりも先にリクエストを実行します。事前にCSRFトークンを発行し、Postmanのenvironmentにこのトークンをセットする...という処理です。(コードは動画からパクりましたw)

ここで一旦、「Send」でリクエストを実行してみましょう。

6120b8c51cb05863d8386b908a46545d.png

  1. 目マークをクリックする。
  2. 「xsrf-token」という名前でCSRFトークンがセットされていることを確認する。

CSRFトークンがセットできましたので、トークンを適用していきましょう。

63bef8a234108502a3c1bfad073ba888.png

  1. Headersタブを開く。
  2. それぞれの項目を入力する。

(2)では、下記の情報を入力しました。

Accept: application/json
X-XSRF-TOKEN: {{xsrf-token}}

{{xsrf-token}} と入力してマウスカーソルを当てると、トークンの内容が表示されるはずです。ここで表示されない場合は、何らかの手順が抜けている可能性があります。

5.ログインを実行する

では、ログインを実行するために「Send」をクリックしましょう。
Bodyに何も表示されなければ、もう一度実行してみましょう。

f3c11c07b1dcc9ea96b19646cd87a2a3.png

Bodyの75行目あたりに「You are logged in!」と表示されれば、ログイン成功となります!


番外編: api/user を叩くには

api/userをPostmanで叩くためには、ここでもいくつか作業が必要となります。

25bc6f6f425cbbb23a56a042652b55c0.png

単純に「qiita-sanctum/api/user」に対してHeader「Accept: application/json」だけを設定してリクエストを送っても正しく動きません。

2b84ba4e61395b35dd55518540f925b1.png

Headersにて「Referer」というKEYを追加し、「localhost」というVALUEを設定する必要があります。

このように設定を行うと、ログイン中のユーザー情報を取得することができます。

お疲れ様でした。

Postmanにてレスポンスボディのjsonの構造をチェックする

This section contains different examples of validating JSON responses using the Ajv schema validator. I do not recommend using the tv4 (Tiny Validator for JSON Schema v4).
https://postman-quick-reference-guide.readthedocs.io/en/latest/schema-validation.html
とあるのでこれに従いtestスクリプトを作成する。
そのためには想定するjsonの構造からチェック用のjsonスキーマを作成する必要がある。
想定するjson を入力すると自動でjsonスキーマに変換するサイトは以下。
https://app.quicktype.io/#s=coordinate
にて左のウィンドウでJSONを選択し、右のウィンドウにJSON Schemaを選択すると表示される。
この結果にはPostmanのtestでは不要な(エラーがでる)項目があり
https://postman-quick-reference-guide.readthedocs.io/en/latest/schema-validation.html
に示してある通りに整形する必要がある。
format
additionalProperties
は不要だった。
Postmanのtest の結果でエラーについてはある程度原因を教えてくれるのでそれにしたがって不要な物を消してPostmanでテスト。

強く推奨されるChromeプラグイン 5選

Chromeブラウザは、シンプルなインターフェースと強力な機能でエンジニアに愛されています。Chromeは内部ブラウザーアプリケーションをサポートするだけでなく、さまざまな強力なプラグインも備えています。今回は、非常に使いやすいChromeプラグインをいくつかお勧めします。これらのプラグインを上手に使用すると、作業と学習の効率を大幅に向上させるでしょう!

1.Sourcegraph

GoogleとFacebookは1億ドルを投資してSourcegraphを構築しました。Sourcegraphは、コード検索、コードレビュー、アラートと自動化のための標準で開発されたプラットフォームであり、各エリート開発チームがより優れたソフトウェアをより早くリリースできるようにしています。ourcegraphは現在、GitHubやGitLabなどの高品質のコミュニティをサポートしています。
alt

2.Postman

Postmanは、強力なHTTPデバッグおよびシミュレーションプラグインです。CSS、HTML、スクリプトなどの単純なWebページの基本情報をデバッグできるだけでなく、ほぼすべてのタイプのHTTPリクエストを送信できます。 Postmanは、ネットワークHTTPリクエストを送信するChromeプラグイン製品の代表的な製品の1つと言えます。
alt

3.Talend API Tester

Talend API Tester は、どんなに複雑であっても、すべてのHTTPリクエストを処理します。 変数を挿入することにより、リクエストを動的にすることができます。セキュリティと認証、およびハイパーメディアとHTMLフォームが完全にサポートされています。 HTTP応答を視覚化、事前設定、および検査できます。
alt

4.SimilarSites

任意のWebサイトにアクセスするときは、検索バーの横にあるSimilarSitesアイコンをクリックして、アクセスしているWebサイトに関連する類似のWebサイト結果を10件取得します。 推奨される各Webサイトのホームページの画像、簡単な説明、Webサイトのタイトルを取得できます。
alt

5.Octotree

Octotreeは、主に膨大な数のプログラマを対象とした、Githubプロジェクトのディレクトリ構造を表示するためのChromeプラグインです。Github上の何千ものオープンソースプロジェクトがプログラマに多くの助けをもたらします。ただし、特に1つのディレクトリから別のディレクトリにジャンプする場合、Githubでソースコードを表示するエクスペリエンスは非常に悪いです。 octotreeプラグインは上記の問題をうまく解決できます。
alt

Postmanを使ってAPIへのリクエストを試す

Postmanを使ってAPIへのリクエストを試す
Postman

Postmanとは

API開発における、設計、テスト、ドキュメントの作成などを行ってくれる便利ツール
いわゆるAPIマネージメントツールというやつ。

インストール

Mac, Windowsのappとコマンドラインから動かすSDKもある。今回はMac版の奴を使う

APIのリクエストを作成する

全体の流れはこんな感じで、簡単。

  1. 左側にある New CollectionでCollectionを作成。
  2. CollectionのAdd requestをクリック
  3. 作成したRequestのタブが出てくるので、APIのurl、パラメーターを入力
  4. Sendボタンを押して、実際にリクエストをする。

スクリーンショット 2019-11-23 0.06.18

画像はopenweatherapiを叩いてる結果です。同じことを試したい場合はopenweatherapiでアカウント登録後APPIDを取得して、postmanのYOURAPPIDの所に入力してください。

GETパラメータの入力はurlを直接でもURLの下にあるエディタでも可能で、POSTメソッドも選択可能。便利。

APIを開発している時にちょっとレスポンスを確認したい時とかに便利。Postman自体はリクエストだけでなく、テストとその自動化もできるのでその辺もまとめていく。

PostmanでAPIのテストをする

PostmanでAPIのテストをする

APIのリクエストは作れるようになったので、今度はAPIのレスポンスからテストを書いていきます。

テストの作成

テストする際は作成したRequestのtestsというタブを開きます。テスト入力用のテキストエリアと、横にサンプルのスニペットが表示されるので、Status Code 200と、Response time is less than 200msをクリック。テストエディタの中にjsのテストコードが入るので、そのままSendボタンを押します。

スクリーンショット 2019-11-24 1.28.16

リクエストが実行されると、Test Resultsのタブにテストの結果が表示される。

テストの書き方

だいたいここに書いてある通り

tests-example

//ある要素がa,bというkeyを持っているかpm.test("Checking if object contains any ONE of the keys",function(){pm.expect({a:1,b:2}).to.have.any.keys('a','b');});
//値が100かどうかpm.test("Check response value",function(){varjsonData=pm.response.json();pm.expect(jsonData.value).to.eql(100);});

テストの例

試しにレスポンスのcitynameがTokyoにマッチするか?というテストを書いてみる。

pm.test("CitynameがTokyoかどうかテストする",function(){varjsonData=pm.response.json();pm.expect(jsonData['city']['name']).to.match(/Tokyo/);console.log(jsonData['city']['name']);});

正規表現を使いたいときはmatchを使います。また、postmanアプリ左下のターミナルっぽいのを押すとconsole.logが確認できる。

テスト自体もJSでかけるし、基本的なものは画面右からクリックするだけで追加できるし、そもそもテスト環境を別に用意する必要がないので、楽ちん。

PostmanのVisualizeを使う

PostmanのVisualizeを使う。
Postman

PostmanでAPIにリクエストをしたり、APIのレスポンスをテストすることは大体できたので、今度はvisualizeの機能を試していきます。

過去の記事はこちら
- PostmanでAPIリクエストを作る
- Postmanを使ってAPIのテストをする

Postmanのvisualizeとは

ざっと説明するとAPIのレスポンスにhtmlをくっつけて表示できる機能で、これがPostmanのアプリ単体うごく感じです。
YoutubeのAPIを例に使ってやっていきます。

Visualize API responses

内容はこの記事とほぼ一緒です。

前準備

YoutubeのAPIを使うために、Youtube DATAAPIのappidを取得します。
これは公式ページの通りで大丈夫。

Youtube DATA APIの概要

Youtube APIへのリクエストを作る

APIのリクエストを作る手順でYoutubeへのアクセスできるリクエストを作ります。
クエリはdeadby daylightの最新日時順でソートするリクエストを作りました。
YOUR_APP_IDの部分に取得したAPPIDを入れます。

作成されたリクエストでJsonで結果が取れればOKです。

スクリーンショット 2020-05-18 23.51.34

Visualize用のテンプレートを作る

テストコードを書いた時と同様にtestタブに行って、テンプレートと取得結果のマッピングを書きます。
response.jsonで取得したデータを下層に辿るのはドットでつなげばオーケーなので以下のように書きました。

vartemplate=`
    <table>
        <tr bgcolor="coffee">
            <th>Title</th>
            <th>Thumb</th>
        </tr>

        {{#each response.items}}
           <tr bgcolor="white">
                <td>{{snippet.title}}</td>
                <td><img src="{{snippet.thumbnails.default.url}}"></td>
            </tr>
        {{/each}}
    </table>
`;// Set visualizerpm.visualizer.set(template,{// Pass the response body parsed as JSON as `data`response:pm.response.json()});

Visualizeの確認

templateを書いた状態で取得結果のjsonの上にあるvisualizeのボタンをクリックします。
うまくいけば検索結果がテーブルで表示されていると思います。

スクリーンショット 2020-05-18 23.52.04

Postman公式のページにいくと、Bootstrapを読み込んで綺麗に表示させていたりするチュートリアルも合ったりするので、参考にするといいかも。

API開発した確認フェーズにこれを一回設定しておくと便利そうだなと思ったのと、まだ調べてないけど、それぞれのテストコード、テンプレートファイルを共有もできるっぽいので、
このPostmanのテスト全部通ったらOK、確認はVisualizeでやって!みたいな感じの仕事の回し方ができそう。

結構面倒そうな機能だったんだけど、かなり簡単にできたので、もうちょっと早く試してみればよかったな。

STOW-RSでハマった話

STOW-RSでハマった話

Docker Desktop for WindowsでOrthancコンテナを立ち上げ、DICOM Webの確認をしていたときのハマった事例を共有します。

環境

  • Docker Desktop for Windows
    • Orthanc
    • CentOS 8
  • Postman

ハマったこと

  • Postman→OrthancにSTOW-RSでDICOMデータを登録しても登録されない。
    • HTTP 200応答される
    • データは登録されていない。

調査~解決

  1. Orthancコミュニティで質問したところ、curlコマンドとDICOMファイルの提出を求められたのでPostmanからcurlを生成して調査
  2. --formにContent-typeがついてないことに気がつく。
  3. つけてみてcurl実行 (CentOS8上で) →成功・ファイル登録された。
curl --location--request POST 'http://172.17.0.2:8042/dicom-web/studies/'\--header'Content-Type: multipart/related; type="application/dicom"'\--header'Authorization: Basic b3J0aGFuYzpvcnRoYW5j'\--form'content=@sample.dcm; type=application/dicom'\--verbose

仕様・規格

現行のPostman仕様とDICOM規格からすると、PostmanでSTOW-RSを使うのは不可能のようです。

UiPath Orchestrator のAPIを呼び出す件(Postman編)

UiPath Orchestrator のAPIを呼び出す件の記事で UiPath Orchestrator APIを呼び出してみました。その記事ではAPIを呼ぶHTTPリクエストを送信するのにcurlコマンドを使用しました。ただcurlは便利なのですが、コマンドプロンプトから実行するなどエンジニア以外のヒトにはとっつきにくいツールだったので、今回はHTTPリクエストを送信する便利ツールのPostmanを使ってみます。

u002.png

インストーラのダウンロードと、サインアップ

https://www.postman.comへアクセス。

右上の「Download」をクリック。

000.png

環境にあったインストーラをダウンロードします。

001.png

ダウンロードしたインストーラを起動すると、そのままアプリが起動します。ちなみに、アプリは2回目以降はスタートメニューから起動可能です。

下記のログイン画面が表示されます。agree のチェックを入れて、今回は「Sing up with Google」をクリック。

006_.png

ブラウザが起動します。「Continue to Sign in」をクリック。

007_.png

Googleで認証・認可すると、EULA が表示されるので「Accept」します。

008_.png

Sign inが完了しました。

008.png

すると下記の通りアプリ側もログインが完了するようですね。

009_.png

やってみる

HelloWorld をやってみる

ではさっそく使ってみます。RESTのAPIでよくつかわれるお天気Webサービス(REST)を呼び出してみましょう。

URLは、http://weather.livedoor.com/forecast/webservice/json/v1?city=130010です

curlだと

$curl 'http://weather.livedoor.com/forecast/webservice/json/v1?city=130010'

こうです。

メイン部分の「+」ボタンをクリックして、「Request」を新規作成します。

010_.png

HTTPリクエストを記述するための画面が表示されるので下記のように「http://weather.livedoor.com/forecast/webservice/json/v1?city=130010」と入れてみます。入れた時点でパラメタが解析されて「Query Params」にセットされたりしているのがステキですね。

さて「Send」をクリックします。

011_.png

結果が表示されました!簡単ですね。

012_.png

「Request」は保存しておくことができるので、「Save」をクリックします。

13_.png

下記のようなダイアログが開きます。まず名前(Request name)を「130010の天気」とかにします。
どうも「Request」を保存するには「Collection」というフォルダ的なモノがないとダメなので「+ Create Collection」をクリック。

14_.png

Collection名を「Test Folder」として、右のチェックをクリック。

15_.png

「Save To Test Folder」をクリックすると、、

16_.png

Test Folder というハコのなかに、保存されましたね!

17_.png

Hello World は以上です。

UiPath Orchestrator APIのリクエストを投げてみる

最後にUiPath Orchestrator のAPIリクエストを投げてみましょう。
UiPath Orchestrator のAPIを呼び出す件(アクセストークンの取得)にある、アクセストークンの取得APIの呼び出しです。

前準備として、「OC画面より「User Key/Client Id」を取得」にしたがって、Community Cloud](https://cloud.uipath.com/) の画面から [User Key],[Client Id] を取得しておきましょう。

u000

アクセストークンの取得APIの呼び出しは、curlだとこうなります(Client Id/User Keyは上記に置き換えてください)。

$curl -X POST https://account.uipath.com/oauth/token  \-H'Content-Type:application/json'\--data'{"grant_type": "refresh_token", "client_id": "[Client Id]", "refresh_token": "[User Key]"}'

では Postman で。

メイン部分の「+」ボタンをクリックして、「Request」を新規作成します。

u001.png

  • Methodを「POST」にして、URLを入力します
  • パラメタは「Body」を選択して
    • 形式を「raw」
    • Text → JSON
  • Bodyのデータは、下記の通り。
{"grant_type":"refresh_token","client_id":"[Client Id]",画面から取得したモノで、手動で置き換える"refresh_token":"[User Key]"画面から取得したモノで、手動で置き換える}

とします。

u002.png

さて、実行です。

Sendで実行してみると アクセストークンが取得できましたね!

u003.png

次回以降、このアクセストークンを使用して、もっとOrchestrator API を触ってみようと思います。

次回以降のテーマ

  • Orchestrator APIを使って、ロボットの情報を取得したり、いろいろAPIを触ってみようと思います。
  • [User Key],[Client Id] などは、実際の値で置き換えましたが、変数のままにしておいて、他のリクエストと共有することもできます。同様に、取得したアクセストークンも他のリクエストで使用したいですが、そのTIPSのご紹介。

おつかれさまでしたー。

関連リンク

Postmanを使ってHTTPに送ったデータを確認する

Postmonとは

HTTPのメソッドを通して行なったリクエストの結果を、簡単に確認できるようにするツール。

APIを構築する時、ブラウザからHTTPリクエストをサーバーに出すことになる。Postmanを使うと、HTTPのリクエストを確認し、REST APIが機能しているかを、簡単にチェックすることができる。

インストール方法

「Download Postman for Mac」https://www.postman.com/downloads/
上記のページよりダウンロードする。

アカウントを作成し、Sign inする必要がある(googleアカウントでもサインイン可能)

APIからのリクエストを確認する

テストのためのファイルを作成

<作成方法1>

・「+New」をクリックし、「Request」を作成

スクリーンショット 2020-06-21 10.14.42.png

・リクエストに名前をつける。HTTPの動作を確認する「Collections」を作成

スクリーンショット 2020-06-21 10.23.12.png

・request name: テストしたい、APIのHTTPリクエスト名
(例:GETをテストしたいのか、DELETEをテストしたいのか、など)
・create folder: テストのためのフォルダーを作成。Postman上の既存のフォルダーに付け加えることもできる
・「Save to APIアプリ名」で保存

<作成方法2>

・「+New collection」
・「Name」にコレクション名(テストしたいアプリ名)をつけて「Create」

スクリーンショット 2020-06-21 10.19.19.png

・「...」をクリックし「Add request」を選択

スクリーンショット 2020-06-21 10.20.24.png

・request name(テストしたいHTTPリクエストの名前)をつける。
・「save to コレクション名」をクリックし保存

スクリーンショット 2020-06-21 10.21.09.png

使ってみよう

①データをgetする

スクリーンショット 2020-06-21 10.29.59.png

・テストしたいAPIのURLを入力
・テストしたいHTTPメソッドを選択(今回はGET)
・「send」をクリック

「Body」にHTTPのレスポンスが表示される

②データをpostする

スクリーンショット 2020-06-21 10.28.46.png

・テストしたいAPIのURLを入力
・テストしたいHTTPメソッドを選択(今回はPOST)
・POSTしたいデータをPostman上から入力する

「Body」>「raw」>「JSON」を選択し、POSTしたいデータをJOSN形式で書き込む。

・「send」を押してデータをPOST

「Body」にHTTPのレスポンスが表示されるので、データがPOSTできているか確認する

<参考>今回のアプリで使用したコード

constexpress=require('express');require('./db/mongoose')constUser=require('./models/user')constTask=require('./models/task')constapp=express()constport=process.env.PORT||3000//postしたデータを受け取る処理app.use(express.json())app.post('/users',(req,res)=>{constuser=newUser(req.body)//.save()でPromiseオブジェクトを作成し、インスタンスをデータベースに保存user.save().then(()=>{res.send(user)}).catch((e)=>{//.catchでエラー時の処理を分岐させるres.send(e)})})

HTTPステータスを操作する

①返ってくるHTTPステータスの確認

スクリーンショット 2020-06-21 10.31.10.png

「Body」に表示されるHTTPのレスポンスの「status」を確認。
ここに表示されているのが、返ってくるHTTPステータス

②返ってくるHTTPステータスの変更
app.post('/users',(req,res)=>{constuser=newUser(req.body)//.save()でPromiseオブジェクトを作成し、インスタンスをデータベースに保存user.save().then(()=>{res.status(201).send(user)}).catch((e)=>{res.status(400).send(e)})})

返ってくるHTTPステータスは「.status()」で設定できる。
Postmanでレスポンスを確認する際はstatus欄も確認する。

<参考>HTTPステータスの一覧と意味

HTTP Status Codes
https://httpstatuses.com/

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

さてさて前回の記事 UiPath Orchestrator のAPIを呼び出す件(Postman編)

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

までを行いましたが、今回はそのつづきです。
前回作成した「Request」も引き続き使いますので、前回の記事は終わらせておくことをおすすめします。
prev

概要

さて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_

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

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

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

ということで「Request」は下記のようになったはずです。リクエストとして送信される電文に、変数を埋め込むことができました。
01

埋め込んだ変数に実際の値を設定するために、Postman上で clientId,userKeyという変数を定義します。
まずは右上の歯車アイコンをクリック。
02

Manage Environmentsというポップアップが上がったと思います。これは変数たちの定義を入れておくハコ「Environments」の管理画面です。変数たちを定義する場所って考えればOKです。
というわけで「Add」をクリック。
03

「Cloud」って名前の「Environment」をひとつ定義しました。そして「Add」をクリック。
04

保存できたようです。
つづいて、CloudってEnvironmentに先の変数たちを定義していきますので、「Cloud」をクリックして中に入ります。
05

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

最後に「Update」をクリック。
06

保存できたようなので上部「×」ボタンでポップアップを閉じます。
07

さて、変数にセットした値を再度確認したり、値を実際に使ったりするには、右上のEnvironmentsのプルダウンをデフォルトの「No Environment」から「Cloud」へ変更します。
08

選択されたEnvironment に定義された変数たちの値を確認するために、目玉のマークをクリックすると、
09

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

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

11

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

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

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

{"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_

  • [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追記 以上--

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

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

変数名説明
clientIdOC画面の「クライアントID」
userKeyOC画面の「ユーザーキー」
tenantNameOC画面の「テナントの論理名」
urlhttps://platform.uipath.com/[Account Name]/[Tenant Logical Name]
token認証リクエストの戻り値のaccess_tokenの値

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

画面上で変数を確認すると、こんな感じです。
12

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

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

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

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

plus

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

まずはURL。
URLは「{{url}}/odata/Machines」とします。すでに認識かとおもいますが {{url}}は「Cloud」Environment上にセットした値で置換されます。またメソッドは「GET」で。
100

つづいて認証情報。
Authorizationタブ をクリックして、Typeプルダウンで「Bearer Token」を選択、右側のTokenに {{token}}と設定。認証リクエストで取得した値がココにセットされるって事ですね。
102

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

以上で完了。
さっそくリクエストを送信してみましょう。「Send」をクリックすると
104

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

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

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

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

ちなみに、いま実際にどんなHTTPリクエストが送信されたか、を確認したいときもありますよね。その場合は右上「code」をクリックすると、、、
109

左メニューから HTTPを選ぶと、HTTP電文が確認できます2
http

左メニューから cURLを選ぶと、cURLのコマンドが。
curl

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

TIPS

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

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

token変数は、認証リクエストの戻り値の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

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

Tests
pm.test("Token Saved",()=>{constjsonData=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

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

107

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

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

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

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

Pre-requestScript
constGetTenant=(url)=>{constpieces=url.split('/')// Check if user formatted the url correctlyif(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 namereturnpieces.pop()}// Get URLconsturl=pm.environment.get("url")consttenant=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

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などのご紹介、などなどをしていこうと思います。

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

関連リンク


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

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

Browsing Latest Articles All 69 Live