📢 Webサイト閉鎖と移転のお知らせ
このWebサイトは2026年9月に閉鎖いたします。
新しい記事は移転先で追加しております。(旧サイトでは記事を追加しておりません)

編集の要約なし
 
(同じ利用者による、間の5版が非表示)
8行目: 8行目:
サーバの実装において、Linuxディストリビューションに必要なプログラム言語とフレームワークをインストールする。<br>
サーバの実装において、Linuxディストリビューションに必要なプログラム言語とフレームワークをインストールする。<br>
一般的な選択肢として、PythonのFlaskやFastAPI、Node.jsのExpress、RubyのSinatra、JavaのSpring Boot、Go言語のGin等がある。<br>
一般的な選択肢として、PythonのFlaskやFastAPI、Node.jsのExpress、RubyのSinatra、JavaのSpring Boot、Go言語のGin等がある。<br>
<br>
以下の例では、PythonのFlaskを使用した基本的なHTTP APIを構築している。<br>
<syntaxhighlight lang="python">
from flask import Flask, request, jsonify
app = Flask(__name__)
# 計算処理のエンドポイント例
@app.route('/api/calculate', methods=['POST'])
def calculate():
    data = request.get_json()
    operation = data.get('operation')
    values = data.get('values', [])
    if operation == 'sum':
      result = sum(values)
    elif operation == 'average':
      result = sum(values) / len(values) if values else 0
    else:
      return jsonify({'error': 'Unknown operation'}), 400
    return jsonify({'result': result})
# データ取得のエンドポイント例
@app.route('/api/status', methods=['GET'])
def get_status():
    return jsonify({'status': 'running', 'version': '1.0.0'})
if __name__ == '__main__':
    app.run(debug=True)
</syntaxhighlight>
<br>
セキュリティでは、APIキーの実装、HTTPS通信の設定、入力データのバリデーション、SQLインジェクション対策等を行う必要がある。<br>
また、認証・認可の仕組みとして、JWTトークン、Basic認証、OAuth2.0の実装も検討する必要がある。<br>
<br>
パフォーマンスとスケーラビリティでは、キャッシュの実装 (例: Redis、Memcached)、データベースの最適化 (インデックス設計等)、ロードバランサの設置が重要である。<br>
また、コンテナ化 (Docker、Podman等) やオーケストレーション (Kubernetes) の導入も検討する。<br>
<br>
APIのドキュメント化も重要な要素となる。<br>
Swagger / OpenAPI、API Blueprint、Postmanコレクション等を使用することにより、APIの仕様を明確に定義して、自動的にドキュメントを生成することができる。<br>
これにより、他の開発者がAPIを理解および使用することが容易になる。<br>
<br>
モニタリングとログ収集の設定において、PrometheusやGrafanaを使用してメトリクスを収集・可視化して、<br>
ELKスタック (Elasticsearch、Logstash、Kibana) またはLoki等でログを収集・分析することにより、APIの健全性を監視することができる。<br>
<br>
<br>
HTTP APIサーバを構築・運用する場合は、以下に示す事柄に注意する。<br>
HTTP APIサーバを構築・運用する場合は、以下に示す事柄に注意する。<br>
403行目: 359行目:
クライアントは以下に示すソースコードを意識することなく、定義されたAPIエンドポイントを通じてデータの操作や機能の実行を行うことが可能となる。<br>
クライアントは以下に示すソースコードを意識することなく、定義されたAPIエンドポイントを通じてデータの操作や機能の実行を行うことが可能となる。<br>
<br>
<br>
まず、基本的なHTTP APIの実装例を示す。<br>
<syntaxhighlight lang="python">
# 基本的なAPI実装例
from flask import Flask, request, jsonify
app = Flask(__name__)
# 計算処理のエンドポイント例
@app.route('/api/calculate', methods=['POST'])
def calculate():
    data = request.get_json()
    operation = data.get('operation')
    values = data.get('values', [])
    if operation == 'sum':
      result = sum(values)
    elif operation == 'average':
      result = sum(values) / len(values) if values else 0
    else:
      return jsonify({'error': 'Unknown operation'}), 400
    return jsonify({'result': result})
# データ取得のエンドポイント例
@app.route('/api/status', methods=['GET'])
def get_status():
    return jsonify({'status': 'running', 'version': '1.0.0'})
if __name__ == '__main__':
    app.run(debug=True)
</syntaxhighlight>
<br>
次に、エラーハンドリングとロギングを含む、より本格的な実装例を示す。<br>
  <syntaxhighlight lang="python">
  <syntaxhighlight lang="python">
  # app.pyファイル
  # app.pyファイル
633行目: 623行目:
<br><br>
<br><br>


== 認証と認可の実装 ==
== 認証と認可 ==
==== APIキー認証を実装する場合 ====
HTTP APIにおいて、認証・認可の仕組みは重要なセキュリティ要素となる。<br>
Python + Flaskでの実装例を示す。<br>
適切な認証方式を選択することにより、APIへの不正アクセスを防止することができる。<br>
<br>
代表的な認証方式として、APIキー認証、JWT (JSON Web Token) 認証、Basic認証、OAuth2.0等がある。<br>
それぞれの用途や要件に応じて、最適な認証方式を選択する必要がある。<br>
<br>
==== APIキー認証 ====
以下の例では、Python + FlaskでAPI認証を行っている。<br>
  <syntaxhighlight lang="python">
  <syntaxhighlight lang="python">
  # auth.pyファイル
  # auth.pyファイル
650行目: 646行目:
     def decorated_function(*args, **kwargs):
     def decorated_function(*args, **kwargs):
       api_key = request.headers.get('X-API-Key')
       api_key = request.headers.get('X-API-Key')
     
       if not api_key or api_key not in VALID_API_KEYS:
       if not api_key or api_key not in VALID_API_KEYS:
           return jsonify({'error': 'Invalid or missing API key'}), 401
           return jsonify({'error': 'Invalid or missing API key'}), 401
     
       return f(*args, **kwargs)
       return f(*args, **kwargs)
     return decorated_function
     return decorated_function
664行目: 660行目:
  </syntaxhighlight>
  </syntaxhighlight>
<br>
<br>
==== JWT認証を実装する場合 ====
==== JWT認証 ====
必要なライブラリをインストールする。<br>
JWT認証に必要なライブラリをインストールする。<br>
  pip install pyjwt
  pip install pyjwt
<br>
<br>
JWT認証の実装例を示す。<br>
以下の例では、JWT認証を行っている。<br>
  <syntaxhighlight lang="python">
  <syntaxhighlight lang="python">
  # jwt_auth.pyファイル
  # jwt_auth.pyファイル
714行目: 710行目:
<br><br>
<br><br>


== レート制限の実装 ==
== セキュリティ対策 ==
レート制限を実装することにより、API呼び出しの過度な使用を防止して、サーバリソースを保護することができる。<br>
HTTP APIサーバのセキュリティ対策は、システム全体の安全性を確保するために不可欠である。<br>
適切なセキュリティ対策を実施することにより、不正アクセス、データ漏洩、サービス妨害等の脅威から保護することができる。<br>
<br>
主要なセキュリティ対策として、以下の項目を実装する必要がある。<br>
* APIキーまたはトークンベースの認証の実装
* HTTPS通信の設定と強制
* 入力データのバリデーション
* SQLインジェクション対策
* クロスサイトスクリプティング (XSS) 対策
* クロスサイトリクエストフォージェリ (CSRF) 対策
* レート制限によるDDoS攻撃対策
* 適切なCORS設定
<br>
==== 入力バリデーション ====
入力データの検証は、セキュリティの基本的な対策である。<br>
悪意のあるデータやフォーマットの誤ったデータを早期に検出することにより、後続の処理における問題を防止できる。<br>
<br>
<syntaxhighlight lang="python">
# validation.pyファイル
from flask import request, jsonify
from functools import wraps
import re
def validate_input(schema):
    def decorator(f):
      @wraps(f)
      def decorated_function(*args, **kwargs):
          data = request.get_json()
          for field, rules in schema.items():
            if rules.get('required') and field not in data:
                return jsonify({'error': f'Missing required field: {field}'}), 400
            if field in data:
                value = data[field]
                # 型チェック
                if 'type' in rules and not isinstance(value, rules['type']):
                  return jsonify({'error': f'Invalid type for field: {field}'}), 400
                # 最大長チェック
                if 'max_length' in rules and len(str(value)) > rules['max_length']:
                  return jsonify({'error': f'Field {field} exceeds maximum length'}), 400
                # 正規表現チェック
                if 'pattern' in rules and not re.match(rules['pattern'], str(value)):
                  return jsonify({'error': f'Field {field} does not match required pattern'}), 400
          return f(*args, **kwargs)
      return decorated_function
    return decorator
# 使用例
@app.route('/api/user', methods=['POST'])
@validate_input({
    'username': {'required': True, 'type': str, 'max_length': 50, 'pattern': r'^[a-zA-Z0-9_]+$'},
    'email': {'required': True, 'type': str, 'pattern': r'^[\w\.-]+@[\w\.-]+\.\w+$'}
})
def create_user():
    # 処理ロジック
    pass
</syntaxhighlight>
<br>
==== SQLインジェクション対策 ====
SQLAlchemyを使用することにより、パラメータ化されたクエリが自動的に生成されて、SQLインジェクションを防ぐことができる。<br>
直接SQL文字列を構築することは避け、必ずパラメータバインディングを使用する。<br>
<br>
<br>
必要なライブラリをインストールする。<br>
<syntaxhighlight lang="python">
# 安全な実装例
from sqlalchemy import text
# 悪い例 (脆弱)
# query = f"SELECT * FROM users WHERE username = '{username}'"
# 良い例 (安全)
query = text("SELECT * FROM users WHERE username = :username")
result = db.session.execute(query, {"username": username})
</syntaxhighlight>
<br>
==== CORS設定 ====
CORS (Cross-Origin Resource Sharing) を適切に設定することにより、信頼されたドメインからのアクセスのみを許可することができる。<br>
本番環境では、ワイルドカード (*) の使用を避け、具体的なドメインを指定することが推奨される。<br>
<br>
<syntaxhighlight lang="python">
# cors_config.pyファイル
from flask_cors import CORS
# 本番環境向けの厳格なCORS設定
CORS(app, resources={
    r"/api/*": {
      "origins": ["https://example.com", "https://app.example.com"],
      "methods": ["GET", "POST", "PUT", "DELETE"],
      "allow_headers": ["Content-Type", "Authorization"],
      "expose_headers": ["Content-Range", "X-Content-Range"],
      "supports_credentials": True,
      "max_age": 3600
    }
})
</syntaxhighlight>
<br><br>
 
== レート制限 ==
レート制限を行うことにより、API呼び出しの過度な使用を防止して、サーバリソースを保護することができる。<br>
適切なレート制限の実装により、DDoS攻撃やAPIの乱用を効果的に防ぐことが可能となる。<br>
<br>
レート制限に必要なライブラリをインストールする。<br>
  pip install flask-limiter
  pip install flask-limiter
<br>
<br>
743行目: 845行目:
  def get_data():
  def get_data():
     return jsonify({'data': 'sample data'})
     return jsonify({'data': 'sample data'})
</syntaxhighlight>
<br><br>
== パフォーマンスとスケーラビリティ ==
HTTP APIサーバの性能向上と拡張性の確保は、サービス品質を維持するために重要である。<br>
適切な最適化とアーキテクチャ設計により、大量のリクエストに対応可能なシステムを構築することができる。<br>
<br>
主要な対策として、以下の項目を検討する必要がある。<br>
<br>
==== キャッシュの実装 ====
頻繁にアクセスされるデータをキャッシュすることにより、データベースへの負荷を軽減して、レスポンス時間を改善することができる。<br>
RedisやMemcached等のインメモリデータストアを活用することが一般的である。<br>
<br>
キャッシュ戦略としては、以下の方式を検討する。<br>
* キャッシュアサイド (Cache-Aside) パターン
*: アプリケーションがキャッシュの読み書きを制御する方式
* ライトスルー (Write-Through) キャッシュ
*: データ書き込み時に同時にキャッシュを更新する方式
* ライトビハインド (Write-Behind) キャッシュ
*: 非同期でキャッシュからデータベースへ書き込む方式
<br>
==== データベースの最適化 ====
データベースの性能は、API全体のパフォーマンスに大きく影響する。<br>
以下の最適化手法を実施することが推奨される。<br>
* インデックスの適切な設計と管理
* クエリの最適化とN+1問題の回避
* コネクションプーリングの活用
* クエリキャッシュの利用
* 読み取り専用レプリカの導入
<br>
==== ロードバランサの設置 ====
複数のAPIサーバインスタンスにトラフィックを分散することにより、可用性とスケーラビリティを向上させることができる。<br>
NginxやHAProxy等のロードバランサを使用して、以下の機能を実現する。<br>
* ラウンドロビンまたは最小接続数による負荷分散
* ヘルスチェックによる障害検知と自動切り離し
* セッションの永続化 (スティッキーセッション)
* SSL/TLSターミネーション
<br>
==== コンテナ化とオーケストレーション ====
DockerやPodman等のコンテナ技術を使用することにより、アプリケーションの移植性と管理性が向上する。<br>
さらに、Kubernetes等のオーケストレーションツールを導入することにより、以下の機能を実現できる。<br>
* 自動スケーリング (Horizontal Pod Autoscaler)
* ローリングアップデートとロールバック
* サービスディスカバリとロードバランシング
* 自己修復機能 (Pod の自動再起動)
<br><br>
== APIドキュメント化 ==
APIのドキュメント化は、開発者がAPIを理解して活用するために不可欠な要素である。<br>
適切なドキュメントを提供することにより、APIの利用促進と問い合わせの削減を実現することができる。<br>
<br>
==== Swagger / OpenAPIの使用 ====
Swagger (現在のOpenAPI Specification) は、RESTful APIを記述するための標準的な仕様である。<br>
この仕様に基づいてAPIを定義することにより、インタラクティブなAPIドキュメントを自動生成することができる。<br>
<br>
Pythonでは、flasgger等のライブラリを使用して、SwaggerドキュメントをFlaskアプリケーションに統合することができる。<br>
pip install flasgger
<br>
<syntaxhighlight lang="python">
# Swagger統合の例
from flasgger import Swagger
from flask import Flask, jsonify
app = Flask(__name__)
swagger = Swagger(app)
@app.route('/api/user/<int:user_id>', methods=['GET'])
def get_user(user_id):
    """
    ユーザ情報を取得するエンドポイント
    ---
    parameters:
      - name: user_id
        in: path
        type: integer
        required: true
        description: ユーザID
    responses:
      200:
        description: ユーザ情報
        schema:
          properties:
            id:
              type: integer
            name:
              type: string
            email:
              type: string
      404:
        description: ユーザが見つかりません
    """
    # 実装ロジック
    return jsonify({'id': user_id, 'name': 'Example User', 'email': 'user@example.com'})
</syntaxhighlight>
<br>
==== API Blueprintの使用 ====
API Blueprintは、マークダウン形式でAPIを記述することができる軽量な仕様である。<br>
技術者以外でも読みやすい形式であり、ドキュメント駆動開発 (Documentation-Driven Development) に適している。<br>
<br>
==== Postmanコレクションの活用 ====
Postmanコレクションは、APIエンドポイントのリクエスト例とレスポンス例を集約したものである。<br>
開発者はPostmanコレクションをインポートすることにより、即座にAPIのテストと動作確認を行うことができる。<br>
<br>
Postmanでは、コレクションからドキュメントを自動生成する機能も提供されており、<br>
Webページとして公開することにより、他の開発者と共有することが可能である。<br>
<br><br>
== 監視とログ管理 ==
APIサーバの監視とログ管理は、システムの健全性を維持して、問題の早期発見と迅速な対応を可能にする重要な要素である。<br>
適切な監視体制を構築することにより、サービスの可用性と信頼性を向上させることができる。<br>
<br>
==== メトリクスの収集と可視化 ====
PrometheusとGrafanaを組み合わせることにより、APIサーバのメトリクスを収集して可視化することができる。<br>
これにより、リクエスト数、レスポンス時間、エラー率等の重要な指標をリアルタイムで監視することが可能となる。<br>
<br>
主要な監視項目として、以下の指標を追跡することが推奨される。<br>
* リクエスト数とレスポンス時間の推移
* HTTPステータスコード別の分布
* CPU使用率とメモリ使用量
* データベース接続数とクエリ実行時間
* エラー発生率とアラート
<br>
==== Prometheusによる監視 ====
[https://github.com/prometheus/prometheus PrometheusのGithub]にアクセスして、Prometheusをインストールする。<br>
ダウンロードしたファイルを解凍する。<br>
tar xf prometheus-<バージョン>.linux-<アーキテクチャ>.tar.gz
cd prometheus-<バージョン>.linux-<アーキテクチャ>
<br>
Prometheus設定ファイルを作成する。<br>
<syntaxhighlight lang="yaml">
# prometheus.ymlファイル
global:
  scrape_interval: 15s
  evaluation_interval: 15s
scrape_configs:
  - job_name: 'api_server'
    static_configs:
      - targets: ['localhost:5000']
    metrics_path: '/metrics'
</syntaxhighlight>
<br>
Pythonアプリケーションにメトリクスエンドポイントを追加する。<br>
pip install prometheus-flask-exporter
<br>
<syntaxhighlight lang="python">
# app.pyファイルにメトリクス設定を追加
from prometheus_flask_exporter import PrometheusMetrics
app = Flask(__name__)
metrics = PrometheusMetrics(app)
# カスタムメトリクスの定義も可能
metrics.info('app_info', 'Application info', version='1.0.0')
</syntaxhighlight>
<br>
==== Grafanaによる可視化 ====
Grafanaをインストールする。<br>
# RHEL
sudo dnf install grafana
# SUSE
sudo zypper install grafana
# Raspberry Pi
sudo apt install apt-transport-https software-properties-common
sudo wget -q -O /usr/share/keyrings/grafana.key https://apt.grafana.com/gpg.key
echo "deb [signed-by=/usr/share/keyrings/grafana.key] https://apt.grafana.com stable main" | sudo tee /etc/apt/sources.list.d/grafana.list
sudo apt update
sudo apt install grafana
<br>
Grafanaサービスを起動して、自動起動を有効にする。<br>
sudo systemctl start grafana-server
sudo systemctl enable grafana-server
<br>
Webブラウザで http://localhost:3000 にアクセスして、Grafanaにログインする。<br>
デフォルトのログイン情報を以下に示す。<br>
* ユーザ名
*: admin
* パスワード
*: admin
<br>
==== ログ収集と分析 ====
ログの適切な管理により、システムの動作状況の把握と問題の診断が容易になる。<br>
ELKスタック (Elasticsearch、Logstash、Kibana) またはLoki等を使用することにより、大量のログデータを効率的に収集して分析することができる。<br>
<br>
ログ収集戦略として、以下の項目を実施することが推奨される。<br>
* 構造化ログ (JSON形式) の採用
* ログレベルの適切な設定 (DEBUG、INFO、WARNING、ERROR、CRITICAL)
* ログローテーションによるディスク容量の管理
* 機密情報のマスキング
* 分散トレーシングの導入 (マイクロサービス環境の場合)
<br>
==== ログ管理 ====
ログローテーションを設定する。<br>
<syntaxhighlight lang="text">
# /etc/logrotate.d/myapiファイル
/var/log/myapi/*.log {
    daily
    rotate 30
    compress
    delaycompress
    notifempty
    create 0640 myapi_user myapi_group
    sharedscripts
    postrotate
      systemctl reload myapi > /dev/null 2>&1 || true
    endscript
}
</syntaxhighlight>
<br>
構造化ログの例を以下に示す。<br>
<syntaxhighlight lang="python">
# logging_config.pyファイル
import logging
import json
from datetime import datetime
class JSONFormatter(logging.Formatter):
    def format(self, record):
      log_data = {
          'timestamp': datetime.utcnow().isoformat(),
          'level': record.levelname,
          'message': record.getMessage(),
          'module': record.module,
          'function': record.funcName,
          'line': record.lineno
      }
      if hasattr(record, 'user_id'):
          log_data['user_id'] = record.user_id
      if record.exc_info:
          log_data['exception'] = self.formatException(record.exc_info)
      return json.dumps(log_data)
# ロガーの設定
def setup_logger(name):
    logger = logging.getLogger(name)
    logger.setLevel(logging.INFO)
    handler = logging.FileHandler('/var/log/myapi/app.log')
    handler.setFormatter(JSONFormatter())
    logger.addHandler(handler)
    return logger
  </syntaxhighlight>
  </syntaxhighlight>
<br><br>
<br><br>


== HTTPS対応 ==
== HTTPS対応 ==
==== Let's Encryptを使用する場合 ====
==== Let's Encryptの使用 ====
Certbotをインストールする。<br>
Certbotをインストールする。<br>
  # RHEL
  # RHEL
768行目: 1,122行目:
  0 3 * * * certbot renew --quiet
  0 3 * * * certbot renew --quiet
<br>
<br>
==== 自己署名証明書を使用する場合 ====
==== 自己署名証明書の使用 ====
開発環境やテスト環境では、自己署名証明書を使用することができる。<br>
開発環境やテスト環境では、自己署名証明書を使用することができる。<br>
<br>
<br>
  openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem -days 365 -nodes
  openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem -days 365 -nodes
<br>
<br>
Pythonアプリケーションで使用する場合の例を示す。<br>
以下の例では、Pythonアプリケーションで使用している。<br>
  <syntaxhighlight lang="python">
  <syntaxhighlight lang="python">
  # HTTPS対応でFlaskアプリを起動
  # HTTPS対応でFlaskアプリを起動
982行目: 1,336行目:
設定を確認する。<br>
設定を確認する。<br>
  sudo ufw status
  sudo ufw status
<br><br>
== 監視とログ管理 ==
==== Prometheusによる監視 ====
[https://github.com/prometheus/prometheus PrometheusのGithub]にアクセスして、Prometheusをインストールする。<br>
ダウンロードしたファイルを解凍する。<br>
tar xf prometheus-<バージョン>.linux-<アーキテクチャ>.tar.gz
cd prometheus-<バージョン>.linux-<アーキテクチャ>
<br>
Prometheus設定ファイルを作成する。<br>
<syntaxhighlight lang="yaml">
# prometheus.ymlファイル
global:
  scrape_interval: 15s
  evaluation_interval: 15s
scrape_configs:
  - job_name: 'api_server'
    static_configs:
      - targets: ['localhost:5000']
    metrics_path: '/metrics'
</syntaxhighlight>
<br>
Pythonアプリケーションにメトリクスエンドポイントを追加する。<br>
pip install prometheus-flask-exporter
<br>
<syntaxhighlight lang="python">
# app.pyファイルにメトリクス設定を追加
from prometheus_flask_exporter import PrometheusMetrics
app = Flask(__name__)
metrics = PrometheusMetrics(app)
# カスタムメトリクスの定義も可能
metrics.info('app_info', 'Application info', version='1.0.0')
</syntaxhighlight>
<br>
==== Grafanaによる可視化 ====
Grafanaをインストールする。<br>
# RHEL
sudo dnf install grafana
# SUSE
sudo zypper install grafana
# Raspberry Pi
sudo apt install apt-transport-https software-properties-common
sudo wget -q -O /usr/share/keyrings/grafana.key https://apt.grafana.com/gpg.key
echo "deb [signed-by=/usr/share/keyrings/grafana.key] https://apt.grafana.com stable main" | sudo tee /etc/apt/sources.list.d/grafana.list
sudo apt update
sudo apt install grafana
<br>
Grafanaサービスを起動して、自動起動を有効にする。<br>
sudo systemctl start grafana-server
sudo systemctl enable grafana-server
<br>
Webブラウザで http://localhost:3000 にアクセスして、Grafanaにログインする。<br>
デフォルトのログイン情報は、ユーザ名: admin、パスワード: admin である。<br>
<br>
==== ログ管理 ====
ログローテーションを設定する。<br>
<syntaxhighlight lang="text">
# /etc/logrotate.d/myapiファイル
/var/log/myapi/*.log {
    daily
    rotate 30
    compress
    delaycompress
    notifempty
    create 0640 myapi_user myapi_group
    sharedscripts
    postrotate
      systemctl reload myapi > /dev/null 2>&1 || true
    endscript
}
</syntaxhighlight>
<br>
構造化ログの実装例を示す。<br>
<syntaxhighlight lang="python">
# logging_config.pyファイル
import logging
import json
from datetime import datetime
class JSONFormatter(logging.Formatter):
    def format(self, record):
      log_data = {
          'timestamp': datetime.utcnow().isoformat(),
          'level': record.levelname,
          'message': record.getMessage(),
          'module': record.module,
          'function': record.funcName,
          'line': record.lineno
      }
     
      if hasattr(record, 'user_id'):
          log_data['user_id'] = record.user_id
     
      if record.exc_info:
          log_data['exception'] = self.formatException(record.exc_info)
     
      return json.dumps(log_data)
# ロガーの設定
def setup_logger(name):
    logger = logging.getLogger(name)
    logger.setLevel(logging.INFO)
   
    handler = logging.FileHandler('/var/log/myapi/app.log')
    handler.setFormatter(JSONFormatter())
   
    logger.addHandler(handler)
    return logger
</syntaxhighlight>
<br><br>
<br><br>


1,160行目: 1,396行目:
   test:
   test:
     runs-on: ubuntu-latest
     runs-on: ubuntu-latest
   
     steps:
     steps:
     - uses: actions/checkout@v2
     - uses: actions/checkout@v2
   
     - name: Set up Python
     - name: Set up Python
       uses: actions/setup-python@v2
       uses: actions/setup-python@v2
       with:
       with:
         python-version: '3.9'
         python-version: '3.9'
   
     - name: Install dependencies
     - name: Install dependencies
       run: |
       run: |
1,174行目: 1,410行目:
         pip install -r requirements.txt
         pip install -r requirements.txt
         pip install pytest pytest-cov
         pip install pytest pytest-cov
   
     - name: Run tests
     - name: Run tests
       run: |
       run: |
         pytest --cov=app tests/
         pytest --cov=app tests/
 
   deploy:
   deploy:
     needs: test
     needs: test
     runs-on: ubuntu-latest
     runs-on: ubuntu-latest
     if: github.ref == 'refs/heads/main'
     if: github.ref == 'refs/heads/main'
   
     steps:
     steps:
     - name: Deploy to server
     - name: Deploy to server
1,197行目: 1,433行目:
           pip install -r requirements.txt
           pip install -r requirements.txt
           sudo systemctl restart myapi
           sudo systemctl restart myapi
</syntaxhighlight>
<br><br>
== セキュリティ対策 ==
==== 入力バリデーション ====
<syntaxhighlight lang="python">
# validation.pyファイル
from flask import request, jsonify
from functools import wraps
import re
def validate_input(schema):
    def decorator(f):
      @wraps(f)
      def decorated_function(*args, **kwargs):
          data = request.get_json()
          for field, rules in schema.items():
            if rules.get('required') and field not in data:
                return jsonify({'error': f'Missing required field: {field}'}), 400
            if field in data:
                value = data[field]
                # 型チェック
                if 'type' in rules and not isinstance(value, rules['type']):
                  return jsonify({'error': f'Invalid type for field: {field}'}), 400
                # 最大長チェック
                if 'max_length' in rules and len(str(value)) > rules['max_length']:
                  return jsonify({'error': f'Field {field} exceeds maximum length'}), 400
                # 正規表現チェック
                if 'pattern' in rules and not re.match(rules['pattern'], str(value)):
                  return jsonify({'error': f'Field {field} does not match required pattern'}), 400
          return f(*args, **kwargs)
      return decorated_function
    return decorator
# 使用例
@app.route('/api/user', methods=['POST'])
@validate_input({
    'username': {'required': True, 'type': str, 'max_length': 50, 'pattern': r'^[a-zA-Z0-9_]+$'},
    'email': {'required': True, 'type': str, 'pattern': r'^[\w\.-]+@[\w\.-]+\.\w+$'}
})
def create_user():
    # 処理ロジック
    pass
</syntaxhighlight>
<br>
==== SQLインジェクション対策 ====
SQLAlchemyを使用することにより、パラメータ化されたクエリが自動的に生成されて、SQLインジェクションを防ぐことができる。<br>
<br>
<syntaxhighlight lang="python">
# 安全な実装例
from sqlalchemy import text
# 悪い例 (脆弱)
# query = f"SELECT * FROM users WHERE username = '{username}'"
# 良い例 (安全)
query = text("SELECT * FROM users WHERE username = :username")
result = db.session.execute(query, {"username": username})
</syntaxhighlight>
<br>
==== CORS設定 ====
<syntaxhighlight lang="python">
# cors_config.pyファイル
from flask_cors import CORS
# 本番環境向けの厳格なCORS設定
CORS(app, resources={
    r"/api/*": {
      "origins": ["https://example.com", "https://app.example.com"],
      "methods": ["GET", "POST", "PUT", "DELETE"],
      "allow_headers": ["Content-Type", "Authorization"],
      "expose_headers": ["Content-Range", "X-Content-Range"],
      "supports_credentials": True,
      "max_age": 3600
    }
})
  </syntaxhighlight>
  </syntaxhighlight>
<br><br>
<br><br>