endpoint.go 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  1. package server
  2. import (
  3. "errors"
  4. "github.com/langgenius/dify-plugin-daemon/internal/utils/cache"
  5. "strings"
  6. "time"
  7. "github.com/gin-gonic/gin"
  8. "github.com/langgenius/dify-plugin-daemon/internal/db"
  9. "github.com/langgenius/dify-plugin-daemon/internal/service"
  10. "github.com/langgenius/dify-plugin-daemon/internal/types/app"
  11. "github.com/langgenius/dify-plugin-daemon/internal/types/exception"
  12. "github.com/langgenius/dify-plugin-daemon/internal/types/models"
  13. "github.com/langgenius/dify-plugin-daemon/internal/utils/log"
  14. "github.com/langgenius/dify-plugin-daemon/pkg/entities/endpoint_entities"
  15. "github.com/langgenius/dify-plugin-daemon/pkg/entities/plugin_entities"
  16. )
  17. // DifyPlugin supports register and use endpoint to improve the plugin's functionality
  18. // you can use it to do some magics, looking forward to your imagination, Ciallo~(∠·ω< )⌒
  19. // - Yeuoly
  20. // EndpointHandler is a function type that can be used to handle endpoint requests
  21. type EndpointHandler func(ctx *gin.Context, hookId string, maxExecutionTime time.Duration, path string)
  22. func (app *App) Endpoint(config *app.Config) func(c *gin.Context) {
  23. return func(c *gin.Context) {
  24. hookId := c.Param("hook_id")
  25. path := c.Param("path")
  26. // set X-Original-Host
  27. if c.Request.Header.Get(endpoint_entities.HeaderXOriginalHost) == "" {
  28. c.Request.Header.Set(endpoint_entities.HeaderXOriginalHost, c.Request.Host)
  29. }
  30. if app.endpointHandler != nil {
  31. app.endpointHandler(c, hookId, time.Duration(config.PluginMaxExecutionTimeout)*time.Second, path)
  32. } else {
  33. app.EndpointHandler(c, hookId, time.Duration(config.PluginMaxExecutionTimeout)*time.Second, path)
  34. }
  35. }
  36. }
  37. func (app *App) EndpointHandler(ctx *gin.Context, hookId string, maxExecutionTime time.Duration, path string) {
  38. endpointCacheKey := strings.Join(
  39. []string{
  40. "hook_id",
  41. hookId,
  42. },
  43. ":",
  44. )
  45. endpoint, err := cache.AutoGetWithGetter[models.Endpoint](
  46. endpointCacheKey,
  47. func() (*models.Endpoint, error) {
  48. v, err := db.GetOne[models.Endpoint](
  49. db.Equal("hook_id", hookId),
  50. )
  51. return &v, err
  52. })
  53. if err == db.ErrDatabaseNotFound {
  54. ctx.JSON(404, exception.BadRequestError(errors.New("endpoint not found")).ToResponse())
  55. return
  56. }
  57. if err != nil {
  58. log.Error("get endpoint error %v", err)
  59. ctx.JSON(500, exception.InternalServerError(errors.New("internal server error")).ToResponse())
  60. return
  61. }
  62. // get plugin installation
  63. pluginInstallationCacheKey := strings.Join(
  64. []string{
  65. "plugin_id",
  66. endpoint.PluginID,
  67. "tenant_id",
  68. endpoint.TenantID,
  69. },
  70. ":",
  71. )
  72. pluginInstallation, err := cache.AutoGetWithGetter[models.PluginInstallation](
  73. pluginInstallationCacheKey,
  74. func() (*models.PluginInstallation, error) {
  75. v, err := db.GetOne[models.PluginInstallation](
  76. db.Equal("plugin_id", endpoint.PluginID),
  77. db.Equal("tenant_id", endpoint.TenantID),
  78. )
  79. return &v, err
  80. },
  81. )
  82. if err != nil {
  83. ctx.JSON(404, exception.BadRequestError(errors.New("plugin installation not found")).ToResponse())
  84. return
  85. }
  86. pluginUniqueIdentifier, err := plugin_entities.NewPluginUniqueIdentifier(
  87. pluginInstallation.PluginUniqueIdentifier,
  88. )
  89. if err != nil {
  90. ctx.JSON(400, exception.UniqueIdentifierError(
  91. errors.New("invalid plugin unique identifier"),
  92. ).ToResponse())
  93. return
  94. }
  95. // check if plugin exists in current node
  96. if ok, originalError := app.cluster.IsPluginOnCurrentNode(pluginUniqueIdentifier); !ok {
  97. app.redirectPluginInvokeByPluginIdentifier(ctx, pluginUniqueIdentifier, originalError)
  98. } else {
  99. service.Endpoint(ctx, endpoint, pluginInstallation, maxExecutionTime, path)
  100. }
  101. }