Spaces:
Configuration error
Configuration error
| package http | |
| import ( | |
| "embed" | |
| "errors" | |
| "fmt" | |
| "net/http" | |
| "github.com/dave-gray101/v2keyauth" | |
| "github.com/mudler/LocalAI/pkg/utils" | |
| "github.com/mudler/LocalAI/core/http/endpoints/localai" | |
| "github.com/mudler/LocalAI/core/http/endpoints/openai" | |
| "github.com/mudler/LocalAI/core/http/middleware" | |
| "github.com/mudler/LocalAI/core/http/routes" | |
| "github.com/mudler/LocalAI/core/config" | |
| "github.com/mudler/LocalAI/core/schema" | |
| "github.com/mudler/LocalAI/core/services" | |
| "github.com/mudler/LocalAI/pkg/model" | |
| "github.com/gofiber/contrib/fiberzerolog" | |
| "github.com/gofiber/fiber/v2" | |
| "github.com/gofiber/fiber/v2/middleware/cors" | |
| "github.com/gofiber/fiber/v2/middleware/csrf" | |
| "github.com/gofiber/fiber/v2/middleware/favicon" | |
| "github.com/gofiber/fiber/v2/middleware/filesystem" | |
| "github.com/gofiber/fiber/v2/middleware/recover" | |
| // swagger handler | |
| "github.com/rs/zerolog/log" | |
| ) | |
| // Embed a directory | |
| // | |
| //go:embed static/* | |
| var embedDirStatic embed.FS | |
| // @title LocalAI API | |
| // @version 2.0.0 | |
| // @description The LocalAI Rest API. | |
| // @termsOfService | |
| // @contact.name LocalAI | |
| // @contact.url https://localai.io | |
| // @license.name MIT | |
| // @license.url https://raw.githubusercontent.com/mudler/LocalAI/master/LICENSE | |
| // @BasePath / | |
| // @securityDefinitions.apikey BearerAuth | |
| // @in header | |
| // @name Authorization | |
| func App(cl *config.BackendConfigLoader, ml *model.ModelLoader, appConfig *config.ApplicationConfig) (*fiber.App, error) { | |
| fiberCfg := fiber.Config{ | |
| Views: renderEngine(), | |
| BodyLimit: appConfig.UploadLimitMB * 1024 * 1024, // this is the default limit of 4MB | |
| // We disable the Fiber startup message as it does not conform to structured logging. | |
| // We register a startup log line with connection information in the OnListen hook to keep things user friendly though | |
| DisableStartupMessage: true, | |
| // Override default error handler | |
| } | |
| if !appConfig.OpaqueErrors { | |
| // Normally, return errors as JSON responses | |
| fiberCfg.ErrorHandler = func(ctx *fiber.Ctx, err error) error { | |
| // Status code defaults to 500 | |
| code := fiber.StatusInternalServerError | |
| // Retrieve the custom status code if it's a *fiber.Error | |
| var e *fiber.Error | |
| if errors.As(err, &e) { | |
| code = e.Code | |
| } | |
| // Send custom error page | |
| return ctx.Status(code).JSON( | |
| schema.ErrorResponse{ | |
| Error: &schema.APIError{Message: err.Error(), Code: code}, | |
| }, | |
| ) | |
| } | |
| } else { | |
| // If OpaqueErrors are required, replace everything with a blank 500. | |
| fiberCfg.ErrorHandler = func(ctx *fiber.Ctx, _ error) error { | |
| return ctx.Status(500).SendString("") | |
| } | |
| } | |
| app := fiber.New(fiberCfg) | |
| app.Hooks().OnListen(func(listenData fiber.ListenData) error { | |
| scheme := "http" | |
| if listenData.TLS { | |
| scheme = "https" | |
| } | |
| log.Info().Str("endpoint", scheme+"://"+listenData.Host+":"+listenData.Port).Msg("LocalAI API is listening! Please connect to the endpoint for API documentation.") | |
| return nil | |
| }) | |
| // Have Fiber use zerolog like the rest of the application rather than it's built-in logger | |
| logger := log.Logger | |
| app.Use(fiberzerolog.New(fiberzerolog.Config{ | |
| Logger: &logger, | |
| })) | |
| // Default middleware config | |
| if !appConfig.Debug { | |
| app.Use(recover.New()) | |
| } | |
| if !appConfig.DisableMetrics { | |
| metricsService, err := services.NewLocalAIMetricsService() | |
| if err != nil { | |
| return nil, err | |
| } | |
| if metricsService != nil { | |
| app.Use(localai.LocalAIMetricsAPIMiddleware(metricsService)) | |
| app.Hooks().OnShutdown(func() error { | |
| return metricsService.Shutdown() | |
| }) | |
| } | |
| } | |
| // Health Checks should always be exempt from auth, so register these first | |
| routes.HealthRoutes(app) | |
| kaConfig, err := middleware.GetKeyAuthConfig(appConfig) | |
| if err != nil || kaConfig == nil { | |
| return nil, fmt.Errorf("failed to create key auth config: %w", err) | |
| } | |
| // Auth is applied to _all_ endpoints. No exceptions. Filtering out endpoints to bypass is the role of the Filter property of the KeyAuth Configuration | |
| app.Use(v2keyauth.New(*kaConfig)) | |
| if appConfig.CORS { | |
| var c func(ctx *fiber.Ctx) error | |
| if appConfig.CORSAllowOrigins == "" { | |
| c = cors.New() | |
| } else { | |
| c = cors.New(cors.Config{AllowOrigins: appConfig.CORSAllowOrigins}) | |
| } | |
| app.Use(c) | |
| } | |
| if appConfig.CSRF { | |
| log.Debug().Msg("Enabling CSRF middleware. Tokens are now required for state-modifying requests") | |
| app.Use(csrf.New()) | |
| } | |
| // Load config jsons | |
| utils.LoadConfig(appConfig.UploadDir, openai.UploadedFilesFile, &openai.UploadedFiles) | |
| utils.LoadConfig(appConfig.ConfigsDir, openai.AssistantsConfigFile, &openai.Assistants) | |
| utils.LoadConfig(appConfig.ConfigsDir, openai.AssistantsFileConfigFile, &openai.AssistantFiles) | |
| galleryService := services.NewGalleryService(appConfig) | |
| galleryService.Start(appConfig.Context, cl) | |
| routes.RegisterElevenLabsRoutes(app, cl, ml, appConfig) | |
| routes.RegisterLocalAIRoutes(app, cl, ml, appConfig, galleryService) | |
| routes.RegisterOpenAIRoutes(app, cl, ml, appConfig) | |
| if !appConfig.DisableWebUI { | |
| routes.RegisterUIRoutes(app, cl, ml, appConfig, galleryService) | |
| } | |
| routes.RegisterJINARoutes(app, cl, ml, appConfig) | |
| httpFS := http.FS(embedDirStatic) | |
| app.Use(favicon.New(favicon.Config{ | |
| URL: "/favicon.ico", | |
| FileSystem: httpFS, | |
| File: "static/favicon.ico", | |
| })) | |
| app.Use("/static", filesystem.New(filesystem.Config{ | |
| Root: httpFS, | |
| PathPrefix: "static", | |
| Browse: true, | |
| })) | |
| // Define a custom 404 handler | |
| // Note: keep this at the bottom! | |
| app.Use(notFoundHandler) | |
| return app, nil | |
| } | |