# ============ Part 1 / 3 : app.py (Flask base) ============
# Flask 서버: 정적 파일/템플릿 서빙 + Bitget API 프록시 엔드포인트
# - 다음 단계(Part 2, Part 3)에서 index.html / main.js를 추가해도 그대로 동작합니다.
from flask import Flask, send_from_directory, render_template, jsonify, request
import requests
import os
app = Flask(
__name__,
static_folder="static", # Part 3에서 main.js 등 들어갈 폴더
template_folder="templates" # Part 2에서 index.html이 들어갈 폴더
)
BITGET_API = "https://api.bitget.com"
def _proxy_get(path: str, params: dict | None = None):
"""Bitget 공용 API 프록시: 브라우저 CORS/레이트이슈 대비"""
url = f"{BITGET_API}{path}"
try:
r = requests.get(url, params=params or {}, timeout=10)
r.raise_for_status()
# Bitget 응답을 그대로 반환 (필요시 캐싱/정규화 로직을 여기에 추가)
return r.json(), 200
except requests.HTTPError as e:
status = e.response.status_code if e.response else 502
return {"error": f"HTTP {status}", "detail": str(e)}, status
except requests.RequestException as e:
return {"error": "Bad Gateway", "detail": str(e)}, 502
# --------------------------
# 기본 라우트
# --------------------------
@app.route("/")
def index():
# Part 2에서 templates/index.html이 준비되면 해당 파일을 렌더합니다.
# (지금은 없더라도 안내 HTML을 임시로 반환)
if os.path.exists(os.path.join(app.template_folder, "index.html")):
return render_template("index.html")
return """
withgot · Flask Base Ready
Flask base is running
Next: add templates/index.html (Part 2) and static/main.js (Part 3).
"""
# --------------------------
# 정적 파일 (JS/CSS/자산)
# --------------------------
@app.route("/static/")
def static_files(filename):
return send_from_directory(app.static_folder, filename)
# --------------------------
# Bitget 프록시 엔드포인트 (브라우저에서 이 주소만 호출)
# --------------------------
# Spot 티커 (원본: /api/v2/spot/market/tickers)
@app.get("/api/bitget/spot_tickers")
def api_spot_tickers():
return _proxy_get("/api/v2/spot/market/tickers")
# Futures 티커 (원본: /api/v2/mix/market/tickers?productType=USDT-FUTURES)
@app.get("/api/bitget/futures_tickers")
def api_futures_tickers():
product_type = request.args.get("productType", "USDT-FUTURES")
return _proxy_get("/api/v2/mix/market/tickers", {"productType": product_type})
# (선택) 캔들/히스토리 등 필요 시 추가
# 예: /api/v2/mix/market/history-candles
@app.get("/api/bitget/mix/history_candles")
def api_mix_history_candles():
# 프런트에서 symbol, granularity, limit, endTime 등을 그대로 전달
params = {
"symbol": request.args.get("symbol", ""),
"granularity": request.args.get("granularity", ""),
"productType": request.args.get("productType", "USDT-FUTURES"),
"limit": request.args.get("limit", "200"),
}
# endTime이 있으면 포함
end_time = request.args.get("endTime")
if end_time:
params["endTime"] = end_time
return _proxy_get("/api/v2/mix/market/history-candles", params)
# (선택) CORS 간단 허용이 필요하면 아래 주석 해제 후 사용
# from flask_cors import CORS
# CORS(app, resources={r"/api/*": {"origins": "*"}})
if __name__ == "__main__":
# 개발모드로 실행 (배포 시에는 WSGI/ASGI 서버 사용 권장)
app.run(host="0.0.0.0", port=5000, debug=True)
# ========== / Part 1 / 3 ==========