見出し画像

JavaからAPIをcurlで呼び出す方法


はじめに

こんにちは。SHIFTのテスト自動化エンジニアの松岡です。
今回は、サーバ外からの呼び出しが無効となるAPIを、Javaを使用してサーバにログインし、APIを呼び出すケースの実装方法を紹介したいと思います。

◆想定されるケース

  • sshでログインしてからAPI呼び出しを行う

  • サーバ外からのAPI呼び出しは無効

◆前提条件

  • API呼び出しに使用するサーバはLinux

  • サーバのIPアドレスは固定で、テスト実行環境からログイン可能な状態にあること

  • ID/PWを使用してサーバにsshでログインする

◆各種クラスファイル一覧

  • テスト用クラス

    • BaseTest……テストシナリオのスーパークラス。ブラウザドライバなどの処理を実施。※今回は割愛

    • FooTest……実際のテストシナリオ。BaseTestを継承

  • 定数クラス

    • Constants……APIを呼び出すコマンド文字列を保持する定数クラス

  • ユーティリティクラス

    • SshApi……SSHしてコマンドを実行するクラス

【1】FooTest.java

@Feature("サーバ上でのAPI呼び出しを含むシナリオ")
public class FooTest extends BaseTest{

   public static final String sutURL = "foobar"; //テスト対象のURL
   
   @Test
   @Description("API呼び出し")
   public void testFileInput() {
      boolean okFlg = callAPI();
      // 以下、必要に応じてokFlgのアサーションを実装
      …(以下省略)…
   }

   private boolean callAPI() {
      final String host = "xxx.xxx.xxx.xxx";
      final String user = "user";
      final String password = "password";

      final String executeCommand = Constants.API_COMMAND;
      okFlg = true;
      
      SshApi sshApi = new SshApi(host, user, password);
      try {
         sshApi.execute(executeCommand, "200");
      } catch (Exception e) {
         e.printStackTrace();
         okFlg = false;
      }

      return okFlg;
   }
}

テストシナリオのクラスです。 privateメソッドのcallAPIを呼び出しています。 callAPIメソッドからさらに、サーバにログインしてコマンドを実行するSshApiクラスのexecuteメソッド(後述)を呼び出しています。 今回は便宜的にログインユーザID、パスワードもクラス内に直接記載していますが、実際のコードではCI/CDツールで該当項目をマスクして渡し、コマンドライン引数から受けるようにすると良いでしょう。

【2】Constants.java

public class Constants {
   public static final String API_COMMAND = "curl -kI -X POST -H \"Accept:application/json\" https://localhost:12345/foobar -o /dev/null -w '%{http_code}\n' -s";
}

定数クラスにAPIを呼び出すコマンドを定義しています。 今回の例ではサーバのlocalhostのポート12345に、メソッドPOSTの呼び出しをcurlコマンドで行っています。また、返ってくるレスポンスをhttpステータスコードのみにして、後述の呼び出し元メソッド内でアサーションを行います。(期待値:200)

【3】SshApi.java

public class SshApi {
   private static final int PORT_NUM = 22; //sshポート番号
   private static final String CHANNEL_TYPE = "exec"; //Channel接続タイプ

   private Session session = null;
   private ChannelExec channel = null;

   // コンストラクタ
   public SshApi(String host, String user, String password) {
      JSch jsch = new JSch();
      try {
         session = jsch.getSession(user, host, PORT_NUM);
         session.setConfig("StrictHostKeyChecking", "no");
         session.setPassword(password);
         session.connect();
         channel = (ChannelExec) session.openChannel(CHANNEL_TYPE);
      } catch (JSchException e) {
         e.printStackTrace();
         disconnect();
      }
   }

   // 切断
   public void disconnect(){
      if (session != null) {
         session.disconnect();
      }
      if (channel != null) {
         channel.disconnect();
      }
   }
   
   // コマンド実行
   public void execute(String command, String expectedOutput) throws Exception{
      boolean okFlg = false;
      InputStream is = null;
      BufferedReader br = null;

      try {
         channel.setCommand(command);
         channel.connect();

         is = channel.getInputStream();
         StringBuffer output = StringBuffer();
         br = new BufferedReader(new InputStreamReader(is));

         String line;
         while ((line = br.readLine()) != null) {
            if (line.contains(expectedOutput)) {
               okFlg = true;
               break;
            }
         }
      } catch (IOException | JSchException e) {
         okFlg = false;
         br.close();
         is.close();
         disconnect();
         throw e;
      } finally {
         if (br != null) {
            br.close();
         }
         if (is != null) {
            is.close();
         }
         disconnect();
      }
      assertEquals(true, okFlg, "出力アサーション失敗");
   }
}

コンストラクタで設定したchannelを使用してサーバに接続後、commandに記載されたコマンドを実行します。 期待値を含む文字列が出力されたらフラグに true をセットし、メソッドの最後でアサーションを行っています。 なお、今回はID/PWでログインするサーバのためJSchを使用していますが、ssh鍵でログインする場合などは、定義他のライブラリを使用して接続するようにして下さい。

※ エディタの都合上インデントがずれてしまう場合があります。コピペ時にお手元でご確認ください。


執筆者プロフィール:松岡 直人
SIerでのJava、jqueryの開発経験を経て、SHIFTに入社。 SHIFTでは入社当初より画面/APIテスト自動化に関わる。 「人間が最低限しか頑張らない自動化」を目指している

お問合せはお気軽に

SHIFTについて(コーポレートサイト)
https://www.shiftinc.jp/

SHIFTのサービスについて(サービスサイト)
https://service.shiftinc.jp/

SHIFTの導入事例
https://service.shiftinc.jp/case/

お役立ち資料はこちら
https://service.shiftinc.jp/resources/

SHIFTの採用情報はこちら

PHOTO:UnsplashClément Hélardot