この記事は セゾンテクノロジー Advent Calendar 2024 19日目の記事です。
シリーズ2は HULFT10 のエンジニアによる投稿をお届けします。
はじめに
初めまして、セゾンテクノロジーの張と申します。
私は昨年10月に未経験エンジニアとして転職し、初めてのプロジェクトとしてHULFT10 API Gatewayの開発に参画しました。開発工程からテスト工程まで携わりました。
本記事では、12月10日にリリースされた当社の新製品HULFT10 API GatewayのwebAPIの叩き方について共有させていただきます。
残念なことに、今回のリリースはHULFT10 API Gatewayのコピー機能が実装されていないため、動作確認の時は似たような管理情報をweb画面から登録するのが面倒だと感じました。
さらに、HULFTを使ってファイル転送を行うには、最低でも管理情報(詳細ホスト、転送グループ、配信、集信)の登録と要求発行の五つのステップが必要です。画面で一つずつ登録するよりも、せっかくAPI対応もできているので、まとめてAPIを一気に投げた方が効率的だと思いました。そのため、今回はファイル転送のために複数のAPIを一気に叩く簡単なスクリプトも作成しました。
<今回の実行環境>
Windows 10
実際に動かしてみたい方は是非myHULFTから評価版をダウンロードして動かしてみて下さい。
事前準備
- HULFT10 API Gateway導入
- web画面からアクセストークン発行
- web画面から接続先HULFTのホストID取得
まず、HULFT10 API Gatewayとは
Web画面から単一/複数HULFTの管理情報や集配信履歴を一元管理し、REST APIで外部サービスと連携することが可能なシステムです。
<利用方法>
主に、二つの方法で利用できます。
1. Web画面
2. REST API 今回はココ
Web画面で利用できる機能は一部REST APIとして公開されていません。
APIリクエスト
今回はcurlコマンドを使ってREST APIを叩きます。
curlコマンド
各APIに応じて必要な情報を埋めて実行し、リスポンスが返されます。
curl -X HTTPメソッド \
-k \
-H "Authorization: Bearer アクセストークン" \
-H "Content-Type: application/json" \
-i "URL" \
-d "リクエストボディ"
HTTPメソッド、URL、リクエストボディの設定値とHTTPステータスコードは HULFT10 API Gateway WebAPI仕様を参照してください。
例:詳細ホスト管理情報登録
curl -X POST \
-k \
-H "Authorization: Bearer pptcaie9_3nphltjks0dbdt10nif5qc31a-ttksrfrcd4ik5rr0cmna5lbcdkmtfdo8addpekmk3kod6dhkdehms5_pqgarg+1+r7pi7g+fa-afdmjhbsiknci9h--t5" \
-H "Content-Type: application/json" \
-i "http://localhost:10117/api/v1/hulft/HOSTID20241111203851202/managements/hosts/detail" \
-d "{\"hostname\":\"localhost\",\"host_type\":\"windows\",\"code_set\":\"utf8\",\"receive_port\":30100,\"observe_port\":31100}"
HTTP/1.1 201 Created
Cache-Control: no-cache
Content-Security-Policy: default-src 'none'; script-src 'self'; style-src 'self'; img-src 'self'; font-src 'self'; object-src 'self'; connect-src 'self'
Content-Type: application/json; charset=utf-8
Location: /api/v1/hulft/HOSTID20241111203851202/managements/hosts/detail
Pragma: no-cache
Referrer-Policy: strict-origin-when-cross-origin
Strict-Transport-Security: max-age=315360000; includeSubdomains
X-Content-Type-Options: nosniff
X-Frame-Options: DENY
X-Request-Id: aede82f2-5029-563b-9799-d4e14c9265b9
Date: Wed, 13 Dec 2024 13:20:58 GMT
Content-Length: 550
複数APIを一気に叩くスクリプト(Node.js実行環境が必要)
以下のスクリプトを使用して、複数のAPIを順次実行することができます。(実行順番はjsonファイル名順と設定しています。)
今回は自ホストにファイルを転送するための最低必要の管理情報の登録から配信要求発行の五つのAPIを作りました。
/api-gateway
/requests
request1.json
request2.json
request3.json
...
run_requests.js
log_実行時間.log (実行後生成される)
詳細ホスト情報登録
{
"method": "POST",
"endpoint": "/managements/hosts/detail",
"data": {
"hostname": "localhost",
"host_type": "windows",
"code_set": "utf8",
"receive_port": 30100,
"observe_port": 31100
}
}
転送グループ情報登録
{
"method": "POST",
"endpoint": "/managements/transfer-groups/detail",
"data": {
"hosts": ["localhost"],
"meta": {
"os_type": "windows"
},
"id": "LOOPBACK"
}
}
配信管理情報登録
{
"method": "POST",
"endpoint": "/managements/sendings/detail",
"data": {
"id": "LOOPBACK2",
"file": {
"name": "C:\\demofile\\snd\\snd.txt",
"type": "binary"
},
"communication": {
"transfer_group": "LOOPBACK"
},
"code_conversion": {
"side": "sending"
},
"compression": {
"type": "none"
}
}
}
集信管理情報登録
{
"method": "POST",
"endpoint": "/managements/receivings/detail",
"data": {
"id": "LOOPBACK2",
"file": {
"name": "C:\\demofile\\rcv\\rcv.txt",
"write_mode": "replace",
"abnormal_treat": "delete",
"receive_mode": "single",
"generational_management": "disable"
}
}
}
配信要求
{
"method": "POST",
"endpoint": "/requests/sendings",
"data": {
"id": "LOOPBACK2"
}
}
実行ファイル
const fs = require('fs');
const path = require('path');
const { exec } = require('child_process');
// 変数定義
const AUTH_TOKEN = 'pptcaie9_3nphltjks0dbdt10nif5qc31a-ttksrfrcd4ik5rr0cmna5lbcdkmtfdo8addpekmk3kod6dhkdehms5_pqgarg+1+r7pi7g+fa-afdmjhbsiknci9h--t5';
const CONTENT_TYPE = 'application/json';
const BASE_URL = 'http://localhost:10117/api/v1/hulft/HOSTID20241111203851202';
const requestsDir = path.join(__dirname, 'requests');
// 実行時間で実行ログを生成
const now = new Date();
const logFileName = `log_${now.getFullYear()}${String(now.getMonth() + 1).padStart(2, '0')}${String(now.getDate()).padStart(2, '0')}_${String(now.getHours()).padStart(2, '0')}${String(now.getMinutes()).padStart(2, '0')}${String(now.getSeconds()).padStart(2, '0')}.log`;
const logFile = path.join(__dirname, logFileName);
// ログファイルを作成
fs.writeFileSync(logFile, '', 'utf8');
// JSONファイルからAPIコマンドを生成
fs.readdir(requestsDir, (err, files) => {
if (err) {
console.error('リクエストディレクトリの読み取りエラー:', err);
return;
}
// ファイル名でソート
const jsonFiles = files.filter(file => file.endsWith('.json')).sort();
// Promiseチェーンを使用してコマンドを順次実行
jsonFiles.reduce((promise, file) => {
return promise.then(() => {
return new Promise((resolve, reject) => {
const filePath = path.join(requestsDir, file);
// JSONファイルの内容を読み取る
fs.readFile(filePath, 'utf8', (err, jsonData) => {
if (err) {
console.error(`${file}の読み取りエラー:`, err);
return reject(err);
}
// JSONデータを解析
let jsonContent;
try {
jsonContent = JSON.parse(jsonData);
} catch (parseErr) {
console.error(`${file}の解析エラー:`, parseErr);
return reject(parseErr);
}
const { method, endpoint, data } = jsonContent;
if (!method || !endpoint || !data) {
console.error(`${file}のJSONフォーマットが無効です`);
return reject(new Error(`${file}のJSONフォーマットが無効です`));
}
// エスケープ
const escapedJsonData = JSON.stringify(data).replace(/\\/g, '\\\\').replace(/"/g, '\\"').replace(/\n/g, '');
// curlコマンド生成
const curlCmd = `curl -k -H "Authorization: Bearer ${AUTH_TOKEN}" -H "Content-Type: ${CONTENT_TYPE}" -i -X ${method} -d "${escapedJsonData}" ${BASE_URL}${endpoint}`;
// curlコマンド実行
console.log(`Executing: ${curlCmd}`);
exec(curlCmd, (err, stdout, stderr) => {
const logEntry = `File: ${file}\nCommand: ${curlCmd}\nResponse:\n${stdout || stderr}\n\n`;
// ログ
fs.appendFile(logFile, logEntry, logErr => {
if (logErr) {
console.error(`${file}のログファイルへの書き込みエラー:`, logErr);
}
});
if (err) {
console.error(`${file}のcurlコマンド実行エラー:`, err);
return reject(err);
}
console.log(`${file}のレスポンス:\n`, stdout);
resolve();
});
});
});
});
}, Promise.resolve());
});
スクリプト実行
実行ファイルディレクトリで以下のコマンドを実行すれば五つのAPIを実行します。
node run_requests.js
おわりに
今回のスクリプトを使うことで、画面で入力する、curlコマンドを一つずつ作成して実行するよりも、複数のAPIを一気に効率よく実行することができます。
時間的にQueryが指定できるAPI等は対応できていないですが、作ってみて楽しかったです!
また、HULFT10ハンズオンセミナーも開催しておりますので、ご興味のある方はぜひ参加してみてください。
関連記事