gemini.go 1.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869
  1. package render
  2. import (
  3. "errors"
  4. "fmt"
  5. "net/http"
  6. "github.com/bytedance/sonic"
  7. "github.com/gin-gonic/gin"
  8. )
  9. type GeminiSSE struct {
  10. Data []byte
  11. }
  12. func (r *GeminiSSE) Render(w http.ResponseWriter) error {
  13. r.WriteContentType(w)
  14. for _, bytes := range [][]byte{
  15. dataBytes,
  16. r.Data,
  17. nnBytes,
  18. } {
  19. // nosemgrep:
  20. // go.lang.security.audit.xss.no-direct-write-to-responsewriter.no-direct-write-to-responsewriter
  21. if _, err := w.Write(bytes); err != nil {
  22. return err
  23. }
  24. }
  25. return nil
  26. }
  27. func (r *GeminiSSE) WriteContentType(w http.ResponseWriter) {
  28. WriteSSEContentType(w)
  29. }
  30. func GeminiBytesData(c *gin.Context, data []byte) {
  31. if len(c.Errors) > 0 {
  32. return
  33. }
  34. if c.IsAborted() {
  35. return
  36. }
  37. c.Render(-1, &GeminiSSE{Data: data})
  38. c.Writer.Flush()
  39. }
  40. func GeminiObjectData(c *gin.Context, object any) error {
  41. if len(c.Errors) > 0 {
  42. return c.Errors.Last()
  43. }
  44. if c.IsAborted() {
  45. return errors.New("context aborted")
  46. }
  47. jsonData, err := sonic.Marshal(object)
  48. if err != nil {
  49. return fmt.Errorf("error marshalling object: %w", err)
  50. }
  51. c.Render(-1, &GeminiSSE{Data: jsonData})
  52. c.Writer.Flush()
  53. return nil
  54. }