github.com/Venafi/vcert/v5@v5.10.2/pkg/webclient/notificationservice/notificationservice.go (about) 1 package notificationservice 2 3 import ( 4 "encoding/json" 5 "fmt" 6 "io" 7 "log" 8 "net/http" 9 "net/url" 10 "strings" 11 "time" 12 13 "github.com/go-http-utils/headers" 14 "github.com/gorilla/websocket" 15 16 "github.com/Venafi/vcert/v5/pkg/domain" 17 "github.com/Venafi/vcert/v5/pkg/util" 18 ) 19 20 type NotificationServiceClient struct { 21 baseURL string 22 accessToken string 23 apiKey string 24 } 25 26 func NewNotificationServiceClient(baseURL string, accessToken string, apiKey string) *NotificationServiceClient { 27 return &NotificationServiceClient{ 28 baseURL: baseURL, 29 accessToken: accessToken, 30 apiKey: apiKey, 31 } 32 } 33 34 func (ns *NotificationServiceClient) Subscribe(wsClientId string) (*websocket.Conn, error) { 35 36 _, host, found := strings.Cut(ns.baseURL, "https://") 37 if !found { 38 return nil, fmt.Errorf("failed to parse baseURL") 39 } 40 41 if strings.HasSuffix(host, "/") && len(host) > 0 { 42 host = host[:len(host)-1] 43 } 44 45 notificationsUrl := url.URL{Scheme: "wss", Host: host, Path: fmt.Sprintf("ws/notificationclients/%s", wsClientId)} 46 httpHeader := http.Header{} 47 if ns.accessToken != "" { 48 httpHeader = http.Header{headers.Authorization: {fmt.Sprintf("%s %s", util.OauthTokenType, ns.accessToken)}} 49 } else if ns.apiKey != "" { 50 httpHeader = http.Header{util.HeaderTpplApikey: {ns.apiKey}} 51 } 52 53 // nolint:bodyclose // TODO: figure out better way to close the body response so it is detected by the linter 54 wsConn, resp, err := websocket.DefaultDialer.Dial(notificationsUrl.String(), httpHeader) 55 if err != nil { 56 return nil, err 57 } 58 defer func(Body io.ReadCloser) { 59 tempErr := Body.Close() 60 if tempErr != nil { 61 err = tempErr 62 } 63 }(resp.Body) 64 65 if resp.StatusCode != http.StatusSwitchingProtocols { 66 return nil, fmt.Errorf("failed switch protocols") 67 } 68 log.Print("successfully switched to websocket connection") 69 70 time.Sleep(5 * time.Second) 71 return wsConn, nil 72 } 73 74 func (ns *NotificationServiceClient) ReadResponse(wsConn *websocket.Conn) (*domain.WorkflowResponse, error) { 75 _, msg, err := wsConn.ReadMessage() 76 if err != nil { 77 return nil, err 78 } 79 80 defer func() { 81 _ = wsConn.Close() 82 }() 83 log.Printf("<---- Workflow Response:\n%s", msg) 84 85 workflowResponse := domain.WorkflowResponse{} 86 err = json.Unmarshal(msg, &workflowResponse) 87 if err != nil { 88 log.Printf("failed to unmarshal response %s", err.Error()) 89 return nil, err 90 } 91 92 return &workflowResponse, nil 93 }