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鍵でログインする場合などは、定義他のライブラリを使用して接続するようにして下さい。
※ エディタの都合上インデントがずれてしまう場合があります。コピペ時にお手元でご確認ください。
お問合せはお気軽に
SHIFTについて(コーポレートサイト)
https://www.shiftinc.jp/
SHIFTのサービスについて(サービスサイト)
https://service.shiftinc.jp/
SHIFTの導入事例
https://service.shiftinc.jp/case/
お役立ち資料はこちら
https://service.shiftinc.jp/resources/
SHIFTの採用情報はこちら
PHOTO:UnsplashのClément Hélardot