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.
		
		
		
		
		
			
		
			
				
					
					
						
							93 lines
						
					
					
						
							2.0 KiB
						
					
					
				
			
		
		
		
			
			
			
		
		
	
	
							93 lines
						
					
					
						
							2.0 KiB
						
					
					
				| package webhook | |
| 
 | |
| import ( | |
| 	"bytes" | |
| 	"context" | |
| 	"encoding/json" | |
| 	"errors" | |
| 	"fmt" | |
| 	"io" | |
| 	"net/http" | |
| 	"time" | |
| 
 | |
| 	"github.com/seaweedfs/seaweedfs/weed/glog" | |
| 	util_http "github.com/seaweedfs/seaweedfs/weed/util/http" | |
| ) | |
| 
 | |
| type httpClient struct { | |
| 	endpoint string | |
| 	token    string | |
| 	timeout  time.Duration | |
| } | |
| 
 | |
| func newHTTPClient(cfg *config) (*httpClient, error) { | |
| 	return &httpClient{ | |
| 		endpoint: cfg.endpoint, | |
| 		token:    cfg.authBearerToken, | |
| 		timeout:  time.Duration(cfg.timeoutSeconds) * time.Second, | |
| 	}, nil | |
| } | |
| 
 | |
| func (h *httpClient) sendMessage(message *webhookMessage) error { | |
| 	// Serialize the protobuf message to JSON for HTTP payload | |
| 	notificationData, err := json.Marshal(message.Notification) | |
| 	if err != nil { | |
| 		return fmt.Errorf("failed to marshal notification: %w", err) | |
| 	} | |
| 
 | |
| 	payload := map[string]interface{}{ | |
| 		"key":        message.Key, | |
| 		"event_type": message.EventType, | |
| 		"message":    json.RawMessage(notificationData), | |
| 	} | |
| 
 | |
| 	jsonData, err := json.Marshal(payload) | |
| 	if err != nil { | |
| 		return fmt.Errorf("failed to marshal message: %w", err) | |
| 	} | |
| 
 | |
| 	req, err := http.NewRequest(http.MethodPost, h.endpoint, bytes.NewBuffer(jsonData)) | |
| 	if err != nil { | |
| 		return fmt.Errorf("failed to create request: %w", err) | |
| 	} | |
| 
 | |
| 	req.Header.Set("Content-Type", "application/json") | |
| 	if h.token != "" { | |
| 		req.Header.Set("Authorization", "Bearer "+h.token) | |
| 	} | |
| 
 | |
| 	if h.timeout > 0 { | |
| 		ctx, cancel := context.WithTimeout(context.Background(), h.timeout) | |
| 		defer cancel() | |
| 		req = req.WithContext(ctx) | |
| 	} | |
| 
 | |
| 	resp, err := util_http.Do(req) | |
| 	if err != nil { | |
| 		if err = drainResponse(resp); err != nil { | |
| 			glog.Errorf("failed to drain response: %v", err) | |
| 		} | |
| 
 | |
| 		return fmt.Errorf("failed to send request: %w", err) | |
| 	} | |
| 	defer resp.Body.Close() | |
| 
 | |
| 	if resp.StatusCode < 200 || resp.StatusCode >= 300 { | |
| 		return fmt.Errorf("webhook returned status code: %d", resp.StatusCode) | |
| 	} | |
| 
 | |
| 	return nil | |
| } | |
| 
 | |
| func drainResponse(resp *http.Response) error { | |
| 	if resp == nil || resp.Body == nil { | |
| 		return nil | |
| 	} | |
| 
 | |
| 	_, err := io.ReadAll(resp.Body) | |
| 
 | |
| 	return errors.Join( | |
| 		err, | |
| 		resp.Body.Close(), | |
| 	) | |
| }
 |