You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

152 lines
5.3 KiB

// Package main provides the main entry point for the Hyperledger Fabric Asset Transfer REST API
//
// @title Hyperledger Fabric Asset Transfer API
// @version 1.0
// @description RESTful API for managing assets on Hyperledger Fabric blockchain
// @termsOfService http://swagger.io/terms/
//
// @contact.name API Support
// @contact.url http://www.swagger.io/support
// @contact.email support@swagger.io
//
// @license.name Apache 2.0
// @license.url http://www.apache.org/licenses/LICENSE-2.0.html
//
// @host localhost:8888
// @BasePath /api/v1
//
// @schemes http https
package main
import (
"fmt"
"log"
"net/http"
"spiderman/docs" // Import generated docs
"spiderman/internal/api"
"spiderman/internal/fabric"
"spiderman/internal/logger"
"spiderman/internal/middleware"
"spiderman/pkg/config"
"github.com/gorilla/mux"
"github.com/sirupsen/logrus"
httpSwagger "github.com/swaggo/http-swagger"
)
func main() {
// Load configuration from environment variables and .env files
cfg := config.LoadConfig()
// Update Swagger configuration with values from config.env
docs.SwaggerInfo.Host = fmt.Sprintf("%s:%s", cfg.Server.Host, cfg.Server.Port)
// Initialize logger
logger.Init(&cfg.Log)
// Log startup information
logger.Logger.WithFields(logrus.Fields{
"environment": cfg.Environment.Environment,
"host": cfg.Server.Host,
"port": cfg.Server.Port,
"swagger_host": docs.SwaggerInfo.Host,
"log_level": cfg.Log.Level,
"log_format": cfg.Log.Format,
}).Info("Starting Hyperledger Fabric Asset Transfer REST API")
// Initialize Fabric client
logger.Logger.Info("Initializing Fabric client...")
fabricClient, err := fabric.NewClient(&cfg.Fabric)
if err != nil {
logger.Logger.WithError(err).Fatal("Failed to initialize Fabric client")
}
defer fabricClient.Close()
// Create API handler
apiHandler := api.NewHandler(fabricClient)
// Setup router with middleware
router := setupRouter(apiHandler, cfg)
// Start server
startServer(router, cfg)
}
func setupRouter(apiHandler *api.Handler, cfg *config.Config) *mux.Router {
router := mux.NewRouter()
// Add middleware in order
router.Use(middleware.Recovery)
router.Use(middleware.CORS)
router.Use(middleware.Logging)
// Swagger documentation route (only in development)
if cfg.IsDevelopment() {
router.PathPrefix("/swagger/").Handler(httpSwagger.WrapHandler)
logger.Logger.Info("Swagger documentation enabled at /swagger/")
}
// API routes
api := router.PathPrefix("/api/v1").Subrouter()
// Health check
router.HandleFunc("/health", apiHandler.HealthCheck).Methods("GET").Name("HealthCheck")
// Ledger operations
api.HandleFunc("/ledger/init", apiHandler.InitLedger).Methods("POST").Name("InitLedger")
// Asset operations with OPTIONS support
api.HandleFunc("/assets", apiHandler.GetAllAssets).Methods("GET").Name("GetAllAssets")
api.HandleFunc("/assets", apiHandler.CreateAsset).Methods("POST").Name("CreateAsset")
api.HandleFunc("/assets", func(w http.ResponseWriter, r *http.Request) {}).Methods("OPTIONS").Name("AssetsOptions")
api.HandleFunc("/assets/{id}", apiHandler.GetAssetByID).Methods("GET").Name("GetAssetByID")
api.HandleFunc("/assets/{id}/transfer", apiHandler.TransferAsset).Methods("PUT").Name("TransferAsset")
api.HandleFunc("/assets/{id}", apiHandler.UpdateAsset).Methods("PUT").Name("UpdateAsset")
api.HandleFunc("/assets/{id}", func(w http.ResponseWriter, r *http.Request) {}).Methods("OPTIONS").Name("AssetByIdOptions")
api.HandleFunc("/assets/{id}/transfer", func(w http.ResponseWriter, r *http.Request) {}).Methods("OPTIONS").Name("TransferAssetOptions")
// Blockchain operations
api.HandleFunc("/blockchain/height", apiHandler.GetBlockHeight).Methods("GET").Name("GetBlockHeight")
api.HandleFunc("/blockchain/info", apiHandler.GetChainInfo).Methods("GET").Name("GetChainInfo")
api.HandleFunc("/blockchain/height", func(w http.ResponseWriter, r *http.Request) {}).Methods("OPTIONS").Name("BlockHeightOptions")
api.HandleFunc("/blockchain/info", func(w http.ResponseWriter, r *http.Request) {}).Methods("OPTIONS").Name("ChainInfoOptions")
// Transaction operations
api.HandleFunc("/transactions/{txid}", apiHandler.GetTransactionByID).Methods("GET").Name("GetTransactionByID")
api.HandleFunc("/transactions/{txid}", func(w http.ResponseWriter, r *http.Request) {}).Methods("OPTIONS").Name("TransactionByIdOptions")
return router
}
func startServer(router *mux.Router, cfg *config.Config) {
host := cfg.Server.Host
port := cfg.Server.Port
logger.Logger.WithFields(logrus.Fields{
"host": host,
"port": port,
"environment": cfg.Environment.Environment,
"swagger_url": fmt.Sprintf("http://%s:%s/swagger/index.html", host, port),
"health_url": fmt.Sprintf("http://%s:%s/health", host, port),
"api_base_url": fmt.Sprintf("http://%s:%s/api/v1", host, port),
}).Info("Server configuration")
fmt.Printf("Starting REST API server on %s:%s\n", host, port)
fmt.Printf("Environment: %s\n", cfg.Environment.Environment)
fmt.Printf("Health check: http://%s:%s/health\n", host, port)
if cfg.IsDevelopment() {
fmt.Printf("Swagger documentation: http://%s:%s/swagger/index.html\n", host, port)
}
logger.Logger.WithFields(logrus.Fields{
"address": ":" + port,
}).Info("Starting HTTP server")
if err := http.ListenAndServe(":"+port, router); err != nil {
log.Fatal("Failed to start server: ", err)
}
}