17
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

この記事は セゾンテクノロジー 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画面から単一/複数HULFTの管理情報や集配信履歴を一元管理し、REST APIで外部サービスと連携することが可能なシステムです。       

<利用方法>
主に、二つの方法で利用できます。           
1. Web画面
2. REST API   :point_left_tone2: 今回はココ   

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 (実行後生成される)     

詳細ホスト情報登録   

request1.json     
{  
  "method": "POST",  
  "endpoint": "/managements/hosts/detail",  
  "data": {      
    "hostname": "localhost",      
    "host_type": "windows",    
    "code_set": "utf8",    
    "receive_port": 30100,      
    "observe_port": 31100    
  }
}

転送グループ情報登録   

request2.json           
{
  "method": "POST",  
  "endpoint": "/managements/transfer-groups/detail",  
  "data": {
    "hosts": ["localhost"],  
    "meta": {
      "os_type": "windows"  
    },
    "id": "LOOPBACK"
  }
}

配信管理情報登録 

request3.json         
{
  "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"
    }
  }
}

集信管理情報登録

request4.json           
{
  "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"      
    }
  }
}

配信要求

request5.json       
{
  "method": "POST",        
  "endpoint": "/requests/sendings",
  "data": {
    "id": "LOOPBACK2"    
  }
}

実行ファイル

run_requests.js                             
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ハンズオンセミナーも開催しておりますので、ご興味のある方はぜひ参加してみてください。                   

関連記事

17
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
17
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?