Это официальная библиотека Go для отправки уведомлений с помощью Courier REST API.
Полное описание полезных данных и свойств запросов и ответов см. в официальной документации Courier API.
Для этого модуля требуется версия Go >= 1.13.
Запустите следующую команду, чтобы использовать библиотеку Go в вашем модуле Go:
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 )
Наш API, особенно метод send, использует несколько объединений. Наш Go SDK определяет структуры для создания этих объединений, такие как courier.Message
, показанные ниже:
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!" ,
},
},
},
},
}
В версии 3.0.8 мы представили улучшенный опыт создания профсоюзов. Например, тип courier.Message
ранее был создан с помощью следующего:
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!" ,
},
),
},
),
}
Хотя конструкция выглядит довольно похожей, старый подход требовал навигации по множеству громоздких имен функций-конструкторов (например, courier.NewContentFromElementalContentSugar
).
Новый подход полностью исключает использование этих конструкторов, что значительно упрощает работу. Перейти со старого подхода так же просто, как установить конкретный тип в соответствующем поле, например:
До
...
Content : courier . NewContentFromElementalContentSugar (
& courier. ElementalContentSugar {
Title : "Back to the Future" ,
Body : "Oh my {{name}}, we need 1.21 Gigawatts!" ,
},
),
...
После
...
Content : & courier. Content {
ElementalContentSugar : & courier. ElementalContentSugar {
Title : "Back to the Future" ,
Body : "Oh my {{name}}, we need 1.21 Gigawatts!" ,
},
},
...
Установить таймаут для каждого отдельного запроса так же просто, как использовать стандартную библиотеку context
. Установка тайм-аута в одну секунду для отдельного вызова API выглядит следующим образом:
ctx , cancel := context . WithTimeout ( context . TODO (), time . Second )
defer cancel ()
response , err := client . Send (
ctx ,
& courier. SendMessageRequest {
Message : ...
},
)
Для адаптации поведения библиотеки включены различные клиентские параметры, включая настройку токенов авторизации для отправки при каждом запросе или предоставление собственного *http.Client
с инструментами. Оба эти варианта показаны ниже:
client := courierclient . NewClient (
option . WithAuthorizationToken ( "" ),
option . WithHTTPClient (
& http. Client {
Timeout : 5 * time . Second ,
},
),
)
Рекомендуется предоставить собственный
*http.Client
. В противном случае будет использоватьсяhttp.DefaultClient
, и ваш клиент будет бесконечно ждать ответа (если не используется контекстно-зависимый тайм-аут для каждого запроса).
Типы структурированных ошибок возвращаются из вызовов API, которые возвращают коды состояния неудачи. Например, вы можете проверить, произошла ли ошибка из-за неправильного запроса (т. е. кода состояния 400), выполнив следующие действия:
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
}
Эти ошибки также совместимы с errors.Is
и errors.As
Как API, поэтому вы можете получить доступ к ошибке следующим образом:
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
}
Если вы хотите обернуть ошибки дополнительной информацией и при этом сохранить возможность доступа к типу с помощью errors.Is
и errors.As
, вы можете использовать директиву %w
:
response , err := client . Send (
context . TODO (),
& courier. SendMessageRequest {},
)
if err != nil {
return fmt . Errorf ( "failed to list employees: %w" , err )
}
Хотя мы ценим вклад открытого исходного кода в этот SDK, эта библиотека создается программным способом. Дополнения, внесенные непосредственно в эту библиотеку, должны быть перенесены в наш код генерации, иначе они будут перезаписаны при следующем сгенерированном выпуске. Не стесняйтесь открывать PR в качестве доказательства концепции, но знайте, что мы не сможем объединить его как есть. Мы предлагаем сначала открыть вопрос, чтобы обсудить его с нами!
С другой стороны, вклад в README всегда приветствуется!