mirror of
				https://github.com/superseriousbusiness/gotosocial.git
				synced 2025-10-31 14:52:30 -05:00 
			
		
		
		
	- github.com/KimMachineGun/automemlimit v0.7.2 => v0.7.3
- github.com/gin-contrib/cors v1.7.5 => v1.7.6
- github.com/minio/minio-go/v7 v7.0.92 => v7.0.94
- github.com/spf13/cast v1.8.0 => v1.9.2
- github.com/uptrace/bun{,/*} v1.2.11 => v1.2.14
- golang.org/x/image v0.27.0 => v0.28.0
- golang.org/x/net v0.40.0 => v0.41.0
- code.superseriousbusiness.org/go-swagger v0.31.0-gts-go1.23-fix => v0.32.3-gts-go1.23-fix
Reviewed-on: https://codeberg.org/superseriousbusiness/gotosocial/pulls/4304
Co-authored-by: kim <grufwub@gmail.com>
Co-committed-by: kim <grufwub@gmail.com>
		
	
			
		
			
				
	
	
		
			120 lines
		
	
	
	
		
			2.5 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			120 lines
		
	
	
	
		
			2.5 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| // Copyright 2014 Manu Martinez-Almeida.  All rights reserved.
 | |
| // Use of this source code is governed by a MIT style
 | |
| // license that can be found in the LICENSE file.
 | |
| 
 | |
| package sse
 | |
| 
 | |
| import (
 | |
| 	"encoding/json"
 | |
| 	"fmt"
 | |
| 	"io"
 | |
| 	"net/http"
 | |
| 	"reflect"
 | |
| 	"strconv"
 | |
| 	"strings"
 | |
| )
 | |
| 
 | |
| // Server-Sent Events
 | |
| // W3C Working Draft 29 October 2009
 | |
| // http://www.w3.org/TR/2009/WD-eventsource-20091029/
 | |
| 
 | |
| const ContentType = "text/event-stream;charset=utf-8"
 | |
| 
 | |
| var (
 | |
| 	contentType = []string{ContentType}
 | |
| 	noCache     = []string{"no-cache"}
 | |
| )
 | |
| 
 | |
| var fieldReplacer = strings.NewReplacer(
 | |
| 	"\n", "\\n",
 | |
| 	"\r", "\\r")
 | |
| 
 | |
| var dataReplacer = strings.NewReplacer(
 | |
| 	"\n", "\ndata:",
 | |
| 	"\r", "\\r")
 | |
| 
 | |
| type Event struct {
 | |
| 	Event string
 | |
| 	Id    string
 | |
| 	Retry uint
 | |
| 	Data  interface{}
 | |
| }
 | |
| 
 | |
| func Encode(writer io.Writer, event Event) error {
 | |
| 	w := checkWriter(writer)
 | |
| 	writeId(w, event.Id)
 | |
| 	writeEvent(w, event.Event)
 | |
| 	writeRetry(w, event.Retry)
 | |
| 	return writeData(w, event.Data)
 | |
| }
 | |
| 
 | |
| func writeId(w stringWriter, id string) {
 | |
| 	if len(id) > 0 {
 | |
| 		_, _ = w.WriteString("id:")
 | |
| 		_, _ = fieldReplacer.WriteString(w, id)
 | |
| 		_, _ = w.WriteString("\n")
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func writeEvent(w stringWriter, event string) {
 | |
| 	if len(event) > 0 {
 | |
| 		_, _ = w.WriteString("event:")
 | |
| 		_, _ = fieldReplacer.WriteString(w, event)
 | |
| 		_, _ = w.WriteString("\n")
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func writeRetry(w stringWriter, retry uint) {
 | |
| 	if retry > 0 {
 | |
| 		_, _ = w.WriteString("retry:")
 | |
| 		_, _ = w.WriteString(strconv.FormatUint(uint64(retry), 10))
 | |
| 		_, _ = w.WriteString("\n")
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func writeData(w stringWriter, data interface{}) error {
 | |
| 	_, _ = w.WriteString("data:")
 | |
| 
 | |
| 	bData, ok := data.([]byte)
 | |
| 	if ok {
 | |
| 		_, _ = dataReplacer.WriteString(w, string(bData))
 | |
| 		_, _ = w.WriteString("\n\n")
 | |
| 		return nil
 | |
| 	}
 | |
| 
 | |
| 	switch kindOfData(data) { //nolint:exhaustive
 | |
| 	case reflect.Struct, reflect.Slice, reflect.Map:
 | |
| 		err := json.NewEncoder(w).Encode(data)
 | |
| 		if err != nil {
 | |
| 			return err
 | |
| 		}
 | |
| 		_, _ = w.WriteString("\n")
 | |
| 	default:
 | |
| 		_, _ = dataReplacer.WriteString(w, fmt.Sprint(data))
 | |
| 		_, _ = w.WriteString("\n\n")
 | |
| 	}
 | |
| 	return nil
 | |
| }
 | |
| 
 | |
| func (r Event) Render(w http.ResponseWriter) error {
 | |
| 	r.WriteContentType(w)
 | |
| 	return Encode(w, r)
 | |
| }
 | |
| 
 | |
| func (r Event) WriteContentType(w http.ResponseWriter) {
 | |
| 	header := w.Header()
 | |
| 	header["Content-Type"] = contentType
 | |
| 
 | |
| 	if _, exist := header["Cache-Control"]; !exist {
 | |
| 		header["Cache-Control"] = noCache
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func kindOfData(data interface{}) reflect.Kind {
 | |
| 	value := reflect.ValueOf(data)
 | |
| 	valueType := value.Kind()
 | |
| 	if valueType == reflect.Ptr {
 | |
| 		valueType = value.Elem().Kind()
 | |
| 	}
 | |
| 	return valueType
 | |
| }
 |