2
// goamz - Go packages to interact with the Amazon Web Services.
4
// https://wiki.ubuntu.com/goamz
6
// Copyright (c) 2011 Memeo Inc.
8
// Written by Prudhvi Krishna Surapaneni <me@prudhvi.net>
10
// This package is in an experimental state, and does not currently
11
// follow conventions and style of the rest of goamz or common
12
// Go conventions. It must be polished before it's considered a
13
// first-class package in goamz.
16
// BUG(niemeyer): Package needs significant clean up.
18
// BUG(niemeyer): Topic values in responses are not being initialized
19
// properly, since they're supposed to reference *SNS.
21
// BUG(niemeyer): Package needs documentation.
23
// BUG(niemeyer): Message.Message should be "Payload []byte"
25
// BUG(niemeyer): Message.SNS must be dropped.
30
"launchpad.net/goamz/aws"
37
// The SNS type encapsulates operation with an SNS region.
41
private byte // Reserve the right of using private data.
49
func New(auth aws.Auth, region aws.Region) *SNS {
50
return &SNS{auth, region, 0}
60
type Subscription struct {
64
SubscriptionArn string
68
func (topic *Topic) Message(message [8192]byte, subject string) *Message {
69
return &Message{topic.SNS, topic, message, subject}
72
type ResponseMetadata struct {
73
RequestId string `xml:"ResponseMetadata>RequestId"`
74
BoxUsage float64 `xml:"ResponseMetadata>BoxUsage"`
77
type ListTopicsResp struct {
78
Topics []Topic `xml:"ListTopicsResult>Topics>member"`
83
type CreateTopicResp struct {
84
Topic Topic `xml:"CreateTopicResult"`
88
type DeleteTopicResp struct {
92
type ListSubscriptionsResp struct {
93
Subscriptions []Subscription `xml:"ListSubscriptionsResult>Subscriptions>member"`
98
type AttributeEntry struct {
99
Key string `xml:"key"`
100
Value string `xml:"value"`
103
type GetTopicAttributesResp struct {
104
Attributes []AttributeEntry `xml:"GetTopicAttributesResult>Attributes>entry"`
108
func makeParams(action string) map[string]string {
109
params := make(map[string]string)
110
params["Action"] = action
116
// See http://goo.gl/lfrMK for more details.
117
func (sns *SNS) ListTopics(NextToken *string) (resp *ListTopicsResp, err error) {
118
resp = &ListTopicsResp{}
119
params := makeParams("ListTopics")
120
if NextToken != nil {
121
params["NextToken"] = *NextToken
123
err = sns.query(nil, nil, params, resp)
129
// See http://goo.gl/m9aAt for more details.
130
func (sns *SNS) CreateTopic(Name string) (resp *CreateTopicResp, err error) {
131
resp = &CreateTopicResp{}
132
params := makeParams("CreateTopic")
133
params["Name"] = Name
134
err = sns.query(nil, nil, params, resp)
140
// See http://goo.gl/OXNcY for more details.
141
func (sns *SNS) DeleteTopic(topic Topic) (resp *DeleteTopicResp, err error) {
142
resp = &DeleteTopicResp{}
143
params := makeParams("DeleteTopic")
144
params["TopicArn"] = topic.TopicArn
145
err = sns.query(nil, nil, params, resp)
151
// Helper function for deleting a topic
152
func (topic *Topic) Delete() (resp *DeleteTopicResp, err error) {
153
return topic.SNS.DeleteTopic(*topic)
158
// See http://goo.gl/k3aGn for more details.
159
func (sns *SNS) ListSubscriptions(NextToken *string) (resp *ListSubscriptionsResp, err error) {
160
resp = &ListSubscriptionsResp{}
161
params := makeParams("ListSubscriptions")
162
if NextToken != nil {
163
params["NextToken"] = *NextToken
165
err = sns.query(nil, nil, params, resp)
169
// GetTopicAttributes
171
// See http://goo.gl/WXRoX for more details.
172
func (sns *SNS) GetTopicAttributes(TopicArn string) (resp *GetTopicAttributesResp, err error) {
173
resp = &GetTopicAttributesResp{}
174
params := makeParams("GetTopicAttributes")
175
params["TopicArn"] = TopicArn
176
err = sns.query(nil, nil, params, resp)
180
type PublishOpt struct {
182
MessageStructure string
187
type PublishResp struct {
188
MessageId string `xml:"PublishResult>MessageId"`
194
// See http://goo.gl/AY2D8 for more details.
195
func (sns *SNS) Publish(options *PublishOpt) (resp *PublishResp, err error) {
196
resp = &PublishResp{}
197
params := makeParams("Publish")
199
if options.Subject != "" {
200
params["Subject"] = options.Subject
203
if options.MessageStructure != "" {
204
params["MessageStructure"] = options.MessageStructure
207
if options.Message != "" {
208
params["Message"] = options.Message
211
if options.TopicArn != "" {
212
params["TopicArn"] = options.TopicArn
215
err = sns.query(nil, nil, params, resp)
219
type SetTopicAttributesResponse struct {
223
// SetTopicAttributes
225
// See http://goo.gl/oVYW7 for more details.
226
func (sns *SNS) SetTopicAttributes(AttributeName, AttributeValue, TopicArn string) (resp *SetTopicAttributesResponse, err error) {
227
resp = &SetTopicAttributesResponse{}
228
params := makeParams("SetTopicAttributes")
230
if AttributeName == "" || TopicArn == "" {
231
return nil, errors.New("Invalid Attribute Name or TopicArn")
234
params["AttributeName"] = AttributeName
235
params["AttributeValue"] = AttributeValue
236
params["TopicArn"] = TopicArn
238
err = sns.query(nil, nil, params, resp)
242
type SubscribeResponse struct {
243
SubscriptionArn string `xml:"SubscribeResult>SubscriptionArn"`
249
// See http://goo.gl/c3iGS for more details.
250
func (sns *SNS) Subscribe(Endpoint, Protocol, TopicArn string) (resp *SubscribeResponse, err error) {
251
resp = &SubscribeResponse{}
252
params := makeParams("Subscribe")
254
params["Endpoint"] = Endpoint
255
params["Protocol"] = Protocol
256
params["TopicArn"] = TopicArn
258
err = sns.query(nil, nil, params, resp)
262
type UnsubscribeResponse struct {
268
// See http://goo.gl/4l5Ge for more details.
269
func (sns *SNS) Unsubscribe(SubscriptionArn string) (resp *UnsubscribeResponse, err error) {
270
resp = &UnsubscribeResponse{}
271
params := makeParams("Unsubscribe")
273
params["SubscriptionArn"] = SubscriptionArn
275
err = sns.query(nil, nil, params, resp)
279
type ConfirmSubscriptionResponse struct {
280
SubscriptionArn string `xml:"ConfirmSubscriptionResult>SubscriptionArn"`
284
type ConfirmSubscriptionOpt struct {
285
AuthenticateOnUnsubscribe string
290
// ConfirmSubscription
292
// See http://goo.gl/3hXzH for more details.
293
func (sns *SNS) ConfirmSubscription(options *ConfirmSubscriptionOpt) (resp *ConfirmSubscriptionResponse, err error) {
294
resp = &ConfirmSubscriptionResponse{}
295
params := makeParams("ConfirmSubscription")
297
if options.AuthenticateOnUnsubscribe != "" {
298
params["AuthenticateOnUnsubscribe"] = options.AuthenticateOnUnsubscribe
301
params["Token"] = options.Token
302
params["TopicArn"] = options.TopicArn
304
err = sns.query(nil, nil, params, resp)
308
type Permission struct {
313
type AddPermissionResponse struct {
319
// See http://goo.gl/mbY4a for more details.
320
func (sns *SNS) AddPermission(permissions []Permission, Label, TopicArn string) (resp *AddPermissionResponse, err error) {
321
resp = &AddPermissionResponse{}
322
params := makeParams("AddPermission")
324
for i, p := range permissions {
325
params["AWSAccountId.member."+strconv.Itoa(i+1)] = p.AccountId
326
params["ActionName.member."+strconv.Itoa(i+1)] = p.ActionName
329
params["Label"] = Label
330
params["TopicArn"] = TopicArn
332
err = sns.query(nil, nil, params, resp)
336
type RemovePermissionResponse struct {
342
// See http://goo.gl/wGl5j for more details.
343
func (sns *SNS) RemovePermission(Label, TopicArn string) (resp *RemovePermissionResponse, err error) {
344
resp = &RemovePermissionResponse{}
345
params := makeParams("RemovePermission")
347
params["Label"] = Label
348
params["TopicArn"] = TopicArn
350
err = sns.query(nil, nil, params, resp)
354
type ListSubscriptionByTopicResponse struct {
355
Subscriptions []Subscription `xml:"ListSubscriptionsByTopicResult>Subscriptions>member"`
359
type ListSubscriptionByTopicOpt struct {
364
// ListSubscriptionByTopic
366
// See http://goo.gl/LaVcC for more details.
367
func (sns *SNS) ListSubscriptionByTopic(options *ListSubscriptionByTopicOpt) (resp *ListSubscriptionByTopicResponse, err error) {
368
resp = &ListSubscriptionByTopicResponse{}
369
params := makeParams("ListSbubscriptionByTopic")
371
if options.NextToken != "" {
372
params["NextToken"] = options.NextToken
375
params["TopicArn"] = options.TopicArn
377
err = sns.query(nil, nil, params, resp)
388
func (err *Error) Error() string {
392
type xmlErrors struct {
394
Errors []Error `xml:"Errors>Error"`
397
func (sns *SNS) query(topic *Topic, message *Message, params map[string]string, resp interface{}) error {
398
params["Timestamp"] = time.Now().UTC().Format(time.RFC3339)
399
u, err := url.Parse(sns.Region.SNSEndpoint)
404
sign(sns.Auth, "GET", "/", params, u.Host)
405
u.RawQuery = multimap(params).Encode()
406
r, err := http.Get(u.String())
412
//dump, _ := http.DumpResponse(r, true)
413
//println("DUMP:\n", string(dump))
416
if r.StatusCode != 200 {
419
err = xml.NewDecoder(r.Body).Decode(resp)
423
func buildError(r *http.Response) error {
424
errors := xmlErrors{}
425
xml.NewDecoder(r.Body).Decode(&errors)
427
if len(errors.Errors) > 0 {
428
err = errors.Errors[0]
430
err.RequestId = errors.RequestId
431
err.StatusCode = r.StatusCode
432
if err.Message == "" {
433
err.Message = r.Status
438
func multimap(p map[string]string) url.Values {
439
q := make(url.Values, len(p))
440
for k, v := range p {