Dies ist die offizielle Go-Bibliothek zum Senden von Benachrichtigungen mit der Courier REST API.
Eine vollständige Beschreibung der Anforderungs- und Antwortnutzlasten und -eigenschaften finden Sie in den offiziellen Courier-API-Dokumenten.
Für dieses Modul ist eine Go-Version >= 1.13 erforderlich.
Führen Sie den folgenden Befehl aus, um die Go-Bibliothek in Ihrem Go-Modul zu verwenden:
go get github.com/trycourier/courier-go/v3
import (
"context"
"fmt"
courierclient "github.com/trycourier/courier-go/v3/client"
option "github.com/trycourier/courier-go/v3/option"
)
client := courierclient . NewClient (
option . WithAuthorizationToken ( "" ),
)
import ( "context" "fmt" courier "github.com/trycourier/courier-go/v3" courierclient "github.com/trycourier/courier-go/v3/client" option "github.com/trycourier/courier-go/v3/option" ) client := courierclient . NewClient ( option . WithAuthorizationToken ( "" ), ) sendResponse , err := client . Send ( context . TODO (), & courier. SendMessageRequest { Message : courier. NewMessageFromTemplateMessage ({ Template : "" , }), }, ) if err != nil { return err } fmt . Printf ( "Sent message %s n " , sendResponse . RequestId )
Unsere API, insbesondere die Sendemethode, verwendet mehrere Unions. Unser Go SDK definiert Strukturen zum Aufbau dieser Unions, wie zum Beispiel courier.Message
, wie unten gezeigt:
import (
courier "github.com/trycourier/courier-go/v3"
)
request := & courier. SendMessageRequest {
// Construct a content message.
Message : & courier. Message {
ContentMessage : & courier. ContentMessage {
// Construct a single recepient that is a user recepient.
To : & courier. MessageRecipient {
Recipient : & courier. Recipient {
UserRecipient : & courier. UserRecipient {
Email : courier . String ( "[email protected]" ),
Data : & courier. MessageData {
"name" : "Marty" ,
},
},
},
},
// Construct content from elemental content sugar.
Content : & courier. Content {
ElementalContentSugar : & courier. ElementalContentSugar {
Title : "Back to the Future" ,
Body : "Oh my {{name}}, we need 1.21 Gigawatts!" ,
},
},
},
},
}
Mit 3.0.8 haben wir eine bessere Erfahrung beim Gewerkschaftsaufbau eingeführt. Beispielsweise wurde der Typ courier.Message
zuvor wie folgt erstellt:
import (
courier "github.com/trycourier/courier-go/v3"
)
request := courier. SendMessageRequest {
// Construct a content message.
Message : courier . NewMessageFromContentMessage (
& courier. ContentMessage {
// Construct a single recepient that is a user recepient.
To : courier . NewMessageRecipientFromRecipient (
courier . NewRecipientFromUserRecipient (
& courier. UserRecipient {
Email : courier . String ( "[email protected]" ),
Data : & courier. MessageData {
"name" : "Marty" ,
},
},
),
),
// Construct content from elemental content sugar.
Content : courier . NewContentFromElementalContentSugar (
& courier. ElementalContentSugar {
Title : "Back to the Future" ,
Body : "Oh my {{name}}, we need 1.21 Gigawatts!" ,
},
),
},
),
}
Obwohl die Konstruktion ziemlich ähnlich aussieht, erforderte der alte Ansatz die Navigation durch eine Vielzahl umständlicher Konstruktorfunktionsnamen (z. B. courier.NewContentFromElementalContentSugar
).
Der neue Ansatz verzichtet vollständig auf diese Konstruktoren, was die Erfahrung erheblich vereinfacht. Die Migration vom alten Ansatz ist so einfach wie das Festlegen des konkreten Typs auf das entsprechende Feld wie folgt:
Vor
...
Content : courier . NewContentFromElementalContentSugar (
& courier. ElementalContentSugar {
Title : "Back to the Future" ,
Body : "Oh my {{name}}, we need 1.21 Gigawatts!" ,
},
),
...
Nach
...
Content : & courier. Content {
ElementalContentSugar : & courier. ElementalContentSugar {
Title : "Back to the Future" ,
Body : "Oh my {{name}}, we need 1.21 Gigawatts!" ,
},
},
...
Das Festlegen eines Timeouts für jede einzelne Anfrage ist so einfach wie die Verwendung der context
. Das Festlegen eines Zeitlimits von einer Sekunde für einen einzelnen API-Aufruf sieht wie folgt aus:
ctx , cancel := context . WithTimeout ( context . TODO (), time . Second )
defer cancel ()
response , err := client . Send (
ctx ,
& courier. SendMessageRequest {
Message : ...
},
)
Zur Anpassung des Verhaltens der Bibliothek sind verschiedene Client-Optionen enthalten. Dazu gehört die Konfiguration von Autorisierungstokens, die bei jeder Anfrage gesendet werden, oder die Bereitstellung Ihres eigenen instrumentierten *http.Client
. Beide Optionen werden unten dargestellt:
client := courierclient . NewClient (
option . WithAuthorizationToken ( "" ),
option . WithHTTPClient (
& http. Client {
Timeout : 5 * time . Second ,
},
),
)
Es wird empfohlen, einen eigenen
*http.Client
bereitzustellen. Andernfalls wirdhttp.DefaultClient
verwendet und Ihr Client wartet unbegrenzt auf eine Antwort (es sei denn, das kontextbasierte Timeout pro Anfrage wird verwendet).
Strukturierte Fehlertypen werden von API-Aufrufen zurückgegeben, die nicht erfolgreiche Statuscodes zurückgeben. Sie können beispielsweise wie folgt überprüfen, ob der Fehler auf eine fehlerhafte Anfrage (z. B. Statuscode 400) zurückzuführen ist:
response , err := client . Send (
context . TODO (),
& courier. SendMessageRequest {},
)
if err != nil {
if apiErr , ok := err .( * core. APIError ); ok && apiErr . StatusCode == http . StatusBadRequest {
// Do something with the bad request ...
}
return err
}
Diese Fehler sind auch mit den APIs errors.Is
und errors.As
kompatibel, sodass Sie wie folgt auf den Fehler zugreifen können:
response , err := client . Send (
context . TODO (),
& courier. SendMessageRequest {},
)
if err != nil {
var apiErr * core. APIError
if errors . As ( err , apiError ); ok {
switch apiErr . StatusCode {
case http . StatusBadRequest :
// Do something with the bad request ...
}
}
return err
}
Wenn Sie die Fehler mit zusätzlichen Informationen umschließen und dennoch die Möglichkeit behalten möchten, mit errors.Is
und errors.As
auf den Typ zuzugreifen, können Sie die %w
Direktive verwenden:
response , err := client . Send (
context . TODO (),
& courier. SendMessageRequest {},
)
if err != nil {
return fmt . Errorf ( "failed to list employees: %w" , err )
}
Obwohl wir Open-Source-Beiträge zu diesem SDK schätzen, wird diese Bibliothek programmgesteuert generiert. Direkt an dieser Bibliothek vorgenommene Ergänzungen müssten in unseren Generierungscode übernommen werden, andernfalls würden sie bei der nächsten generierten Version überschrieben. Fühlen Sie sich frei, eine PR als Proof of Concept zu eröffnen, aber seien Sie sich darüber im Klaren, dass wir sie nicht so wie sie ist zusammenführen können. Wir empfehlen, zuerst ein Problem zu eröffnen, um es mit uns zu besprechen!
Andererseits sind Beiträge zur README immer sehr willkommen!