Looking for Starter Resources for the Soundcloud API in GoLang - rest

I've unsuccessfully tried to access the Soundcloud API with Go. For any language that isn't directly support by Soundcloud, their API is very convoluted. If anyone has any resources or code examples, I'd appreciate it if someone shared them with me.
My code is as follows:
func main() {
v := url.Values{}
v.Set("scope", "non-expiring")
v.Set("client_id", auth.ClientID)
v.Set("response_type", "code")
v.Set("redirect_uri", auth.RedirectURI)
c.AuthURL = AuthEndpoint + "?" + v.Encode()
c.Values = v.Encode()
res := c.Request("POST", url.Values{})
}
func (c *Client) Request(method string, params url.Values) []byte {
params.Set("client_id", "*************")
reqUrl := "https://api.soundcloud.com/oauth2/token"
req, _ := http.NewRequest(method, reqUrl, strings.NewReader(c.Values))
req.Header.Add("Accept", "application/json")
resp, _ := c.client.Do(req)
defer resp.Body.Close()
body, _ := ioutil.ReadAll(resp.Body)
return body
}

i'm active developing a package in go to access/work with Soundcloud API, it has OAuth2 support, and is already usable.
I invite you to look for it. https://github.com/njasm/gosoundcloud
Take in consideration that the package is still under heavy development, the API might change in the future.

You can have a look at yanatan16/golang-soundcloud, even though then authentication part isn't implemented yet (see issues)
There is an oauth class though.
Ad quite a few other calls to the API, for getting SoundCloud objects.

Related

How to make PUT request RESTful?

With a single API resource /, we have written only one handler that process GET & POST request on API resource /
POST we use to create a resource in database, byt sending data in request body
PUT we use to update an existing resource in database
My understanding is, RESTful best practice says, a handler need to serve an API resource(say /) for all requests GET, POST & PUT
We want the same handler to process PUT request, but the API resource will be something like /1234, where 1234 is existing id
Technically, API resource /1234 will also map to same handler that processes /, but,
From RESTful best practices, Does /1234 need to be handled without passing id as part of API resource URI? something like below...
func ServeHTTP(w http.ResponseWriter, r *http.Request) {
if r.Method == http.MethodGet { // for API resource '/'
p.getProducts(w, r)
return
}
if r.Method == http.MethodPost { // for API resource '/'
p.addProduct(w, r)
return
}
if r.Method == http.MethodPut { // for API resource '/'
p.updateProduct(w, r)
return
}
}
func updateProduct(w http.ResponseWriter, r *http.Request) {
var idString string
decoder := json.NewDecoder(r.Body)
decoder.Decode(idString)
id, err := findID(idString)
// do whatever with id
}
func findID(str string) (int, error) {
dfa := regexp.MustCompile(`/([0-9]+)`)
matches := dfa.FindAllStringSubmatch(str, -1) // returns [][]string
idString := matches[0][1]
id, err := strconv.Atoi(idString)
return id, nil
}
As I understood right you right.
You have two call which can be handle without Id for end point /.
One is POST when the back-end with generate you Id as a result.
Second is GET for all resources but this is up to you. Maybe because of secure reason you would not like to list all available resources.
One extra information is that PUT & 'POST' can use the same handler but logic in handler has to check if 'id' is provided and do extra more logic to create resource.

Find out current user name in golang server that uses Auth0

I am using auth0 and golang for a rest service that is similar implemented as shown here.
I wonder how I can find out the name of the user that is currently triggering a certain API call - for instance if someone requests http://localhost:3000/products - the go handler in this case looks like this:
var ProductsHandler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
payload, _ := json.Marshal(products)
w.Header().Set("Content-Type", "application/json")
w.Write([]byte(payload))
})
Does the request r contain more information about the current user?
Or do I need to find out the current user in the middleware authentication:
func authMiddleware(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
secret := []byte("{YOUR-AUTH0-API-SECRET}")
secretProvider := auth0.NewKeyProvider(secret)
audience := "{YOUR-AUTH0-API-AUDIENCE}"
configuration := auth0.NewConfiguration(secretProvider, audience, "https://{YOUR-AUTH0-DOMAIN}.auth0.com/", jose.HS256)
validator := auth0.NewValidator(configuration)
token, err := validator.ValidateRequest(r)
if err != nil {
fmt.Println(err)
fmt.Println("Token is not valid:", token)
w.WriteHeader(http.StatusUnauthorized)
w.Write([]byte("Unauthorized"))
} else {
next.ServeHTTP(w, r)
}
})
}
Does the token contain more information about the user?
I am a bit lost here. auth0 works perfectly to ensure that only registered persons can use the REST-API, but I want to deliver user specific information. So it depends on the current user what a REST call is handing back. Initially, I was thinking that auth0 would take care of this. Is there a simple way to achieve this?
Yes, you need to use token to get information about request issue.
To sort all you want you need to take a look to next:
Check out how token extracted in this method: token extraction
And the Claims here: Claims structure
And how combine it here: retrieve Claims
The claims have a field
Issuer string `json:"iss,omitempty"`
you are interested in.

GoLang: Send Mailjet email without Mailjet library

I am trying to send emails from my golang application using my Mailjet credentials, but I am trying to do it the normal golang way (yes, I know that their library is highly encouraged).
I have the emails working fine using the Mailjet library, but my boss made a really good point that we might not stay with Mailjet forever. If we switch to a different email solution, we don't want to have to rewrite all of our email code, we just want to change our hostname and credentials.
My printer sends emails just find through Mailjet using the same hostname and credentials, but for some reason my golang app won't!
My code was adopted from the golang smtp library SendEmail example.
Here it is (without my credentials, of course):
import (
"bytes"
"fmt"
"net/smtp"
)
func SendTestEmail() (bool, error) {
fmt.Println("Send Test Email: Enter")
success := false
hostname := "in-v3.mailjet.com"
auth := smtp.PlainAuth("", username, password, hostname)
to := []string{"me#example.com"}
msg := []byte("To: me#example.com\r\n" +
"Subject: discount Gophers!\r\n" +
"\r\n" +
"This is the email body.\r\n")
fmt.Println("Send Test Email: Sending Email")
err := smtp.SendMail(hostname+":587", auth, "sender#example.com", to, msg)
if err == nil {
fmt.Println("Send Test Email: Email successfully sent!")
success = true
} else {
fmt.Println("Send Test Email: Email failed to send", err)
}
fmt.Println("Send Test Email: Exit")
return success, err
}
Note that I am using port 587. I do not know if my printer is using 587 or 25, but it's working. I don't work when using port 25 either.
What is really weird is that smtp.SendEmail isn't returning any errors, but I still do not get any emails (yes, I am checking my junk folder)!
Also, when I log into Mailjet, I don't see that any emails were sent. I do see that an email was sent when I send something from the printer.
So, where is my email?!
Any help is greatly appreciated. Thanks!
First of all, thanks for choosing Mailjet as your email service provider! I'm leading the API Product and Developers Relations at Mailjet.
When it comes to send, you're right with SMTP. It's standard, widely supported and easy to switch (even if I don't hope we'll get there!). Our Go library will become handy when it comes to deal with our API to manage business processes.
I have several questions / feedback looking at your code:
I guess the "sender#example.com" from address used is not the one you use in your real code? Anyway, this email must have been validated on Mailjet side beforehands. See our dedicated guide
Seems you try to set some SMTP headers like Subject within the message, when it should be handled separately
Here's a working code I'm using to work with SMTP:
package main
import (
"log"
"net/smtp"
"fmt"
)
func main() {
auth := smtp.PlainAuth(
"",
"MAILJET_API_KEY",
"MAILJET_API_SECRET",
"in-v3.mailjet.com",
)
email := "foobar#test.com"
header := make(map[string]string)
header["From"] = email
header["To"] = email
header["Subject"] = "Hello Mailjet World!"
header["X-Mailjet-Campaign"] = "test"
message := ""
for k, v := range header {
message += fmt.Sprintf("%s: %s\r\n", k, v)
}
message += "\r\nHi! Thanks for using Mailjet."
err := smtp.SendMail(
"in-v3.mailjet.com:587",
auth,
email,
[]string{email},
[]byte(message),
)
if err != nil {
log.Printf("Error: %s", err)
} else {
log.Printf("Mail sent!")
}
}
Hope it helps! hAPI sending with Mailjet

URL Builder/Query builder in Go

I am interested in dynamically taking arguments from the user as input through a browser or a CLI to pass in those parameters to the REST API call and hence construct the URL dynamically using Go which is going to ultimately fetch me some JSON data.
I want to know some techniques in Go which could help me do that. One ideal way I thought was to use a map and populate it with arguments keys and corresponding values and iterate over it and append it to the URL string. But when it comes to dynamically taking the arguments and populating the map, I am not very sure how to do that in Go. Can someone help me out with some code snippet in Go?
Request example:
http://<IP>:port?api=fetchJsonData&arg1=val1&arg2=val2&arg3=val3.....&argn=valn
There's already url.URL that handles that kind of things for you.
For http handlers (incoming requests) it's a part of http.Request (access it with req.URL.Query()).
A very good example from the official docs:
u, err := url.Parse("http://bing.com/search?q=dotnet")
if err != nil {
log.Fatal(err)
}
u.Scheme = "https"
u.Host = "google.com"
q := u.Query()
q.Set("q", "golang")
u.RawQuery = q.Encode()
fmt.Println(u)
https://github.com/golang/go/issues/17340#issuecomment-251537687
https://play.golang.org/p/XUctl_odTSb
package main
import (
"fmt"
"net/url"
)
func someURL() string {
url := url.URL{
Scheme: "https",
Host: "example.com",
}
return url.String()
}
func main() {
fmt.Println(someURL())
}
returns:
https://example.com
url.Values{} provides an interface for building query params. You can construct inline and/or use .Add for dynamic properties:
queryParams := url.Values{
"checkin": {request.CheckIn},
"checkout": {request.CheckOut},
}
if request.ReservationId {
queryParams.Add("reservationId", request.ReservationId)
}
url := "https://api.example?" + queryParams.Encode() // checkin=...&checkout=...

WSDL/SOAP support on Go?

Are there any packages to support SOAP/WSDL on Go?
There isn't support for WSDL in Go. Support in other languages are either static or dynamic: Either structs are pre-generated from the WSDL, or it's done on the fly with hash tables.
You can, however, encode and decode SOAP requests manually. I found that the standard encoding/xml package to be insufficient for SOAP. There are so many quirks in different servers, and the limitations in encoding/xml make it difficult generate a request these servers are happy with.
For example, some servers need xsi:type="xsd:string" on every string tag. In order to do this properly your struct needs to look like this for encoding/xml:
type MethodCall struct {
One XSI
Two XSI
}
type XSI struct {
Type string `xml:"xsi:type,attr"`
Vaue string `xml:",chardata"`
}
And you construct it like this:
MethodCall{
XSI{"xsd:string", "One"},
XSI{"xsd:string", "Two"},
}
Which gives you:
<MethodCall>
<One xsi:type="xsd:string">One</One>
<Two xsi:type="xsd:string">Two</Two>
</MethodCall>
Now this might be ok. It certainly gets the job done. But what if you needed more than just a string? encoding/xml currently doesn't support interface{}.
As you can see this gets complicated. If you had one SOAP API to integrate, this probably wouldn't be too bad. What if you had several, each with their own quirks?
Wouldn't it be nice if you could just do this?
type MethodCall struct {
One string
Two string
}
Then say to encoding/xml: "This server want xsi types".
To solve this problem I created github.com/webconnex/xmlutil. It's a work in progress. It doesn't have all the features of encoding/xml's encoder/decoder, but it has what is needed for SOAP.
Here's a working example:
package main
import (
"bytes"
"encoding/xml"
"fmt"
"github.com/webconnex/xmlutil"
"log"
//"net/http"
)
type Envelope struct {
Body `xml:"soap:"`
}
type Body struct {
Msg interface{}
}
type MethodCall struct {
One string
Two string
}
type MethodCallResponse struct {
Three string
}
func main() {
x := xmlutil.NewXmlUtil()
x.RegisterNamespace("http://www.w3.org/2001/XMLSchema-instance", "xsi")
x.RegisterNamespace("http://www.w3.org/2001/XMLSchema", "xsd")
x.RegisterNamespace("http://www.w3.org/2003/05/soap-envelope", "soap")
x.RegisterTypeMore(Envelope{}, xml.Name{"http://www.w3.org/2003/05/soap-envelope", ""},
[]xml.Attr{
xml.Attr{xml.Name{"xmlns", "xsi"}, "http://www.w3.org/2001/XMLSchema-instance"},
xml.Attr{xml.Name{"xmlns", "xsd"}, "http://www.w3.org/2001/XMLSchema"},
xml.Attr{xml.Name{"xmlns", "soap"}, "http://www.w3.org/2003/05/soap-envelope"},
})
x.RegisterTypeMore("", xml.Name{}, []xml.Attr{
xml.Attr{xml.Name{"http://www.w3.org/2001/XMLSchema-instance", "type"}, "xsd:string"},
})
buf := new(bytes.Buffer)
buf.WriteString(`<?xml version="1.0" encoding="utf-8"?>`)
buf.WriteByte('\n')
enc := x.NewEncoder(buf)
env := &Envelope{Body{MethodCall{
One: "one",
Two: "two",
}}}
if err := enc.Encode(env); err != nil {
log.Fatal(err)
}
// Print request
bs := buf.Bytes()
bs = bytes.Replace(bs, []byte{'>', '<'}, []byte{'>', '\n', '<'}, -1)
fmt.Printf("%s\n\n", bs)
/*
// Send response, SOAP 1.2, fill in url, namespace, and action
var r *http.Response
if r, err = http.Post(url, "application/soap+xml; charset=utf-8; action="+namespace+"/"+action, buf); err != nil {
return
}
dec := x.NewDecoder(r.Body)
*/
// Decode response
dec := x.NewDecoder(bytes.NewBufferString(`<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope>
<soap:Body>
<MethodCallResponse>
<Three>three</Three>
</MethodCallResponse>
</soap:Body>
</soap:Envelope>`))
find := []xml.Name{
xml.Name{"", "MethodCallResponse"},
xml.Name{"http://www.w3.org/2003/05/soap-envelope", "Fault"},
}
var start *xml.StartElement
var err error
if start, err = dec.Find(find); err != nil {
log.Fatal(err)
}
if start.Name.Local == "Fault" {
log.Fatal("Fault!") // Here you can decode a Soap Fault
}
var resp MethodCallResponse
if err := dec.DecodeElement(&resp, start); err != nil {
log.Fatal(err)
}
fmt.Printf("%#v\n\n", resp)
}
With the above example I use the Find method to get the response object, or a Fault. This isn't strictly necessary. You can also do it like this:
x.RegisterType(MethodCallResponse{})
...
// Decode response
dec := x.NewDecoder(bytes.NewBufferString(`<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope>
<soap:Body>
<MethodCallResponse>
<Three>three</Three>
</MethodCallResponse>
</soap:Body>
</soap:Envelope>`))
var start *xml.StartElement
var resp Envelope
if err := dec.DecodeElement(&resp, start); err != nil {
log.Fatal(err)
}
fmt.Printf("%#v\n\n", resp)
You'll find the Find method useful when your data looks like this:
<soap:Envelope>
<soap:Body>
<MethodResponse>
<MethodResult>
<diffgr:diffgram>
<NewDataSet>
<Table1 diffgr:id="Table1" msdata:rowOrder="0" diffgr:hasChanges="inserted">
<Three>three</Three>
</Table1>
</NewDataSet>
</diffgr:diffgram>
</MethodResult>
</MethodResponse>
</soap:Body>
</soap:Envelope>
This is a DiffGram, part of Microsoft .NET. You can use the Find method to get to Table1. The Decode and DecodeElement method also works on slices. So you can pass in a []MethodCallResponse if NewDataSet happens to contain more than one result.
I do agree with Zippower that SOAP does suck. But unfortunately a lot of enterprises use SOAP, and you're sometimes forced to use these APIs. With the xmlutil package I hope to make it a little less painful to work with.
Nope.
SOAP sucks, but I had to implement a server of an already-defined protocol that uses SOAP, so I listened with net/http and decoded/encoded envelopes with encoding/xml. In few minutes, I already served my first envelope with Go.
While there's still nothing in Go itself, there is gowsdl. So far, it seems to work well enough for me to interface with several SOAP services.
I don't use the SOAP proxy it provides, which I believe doesn't support auth, but gowsdl generates the structs and code I need from the WSDL to marshal requests and unmarshal responses--a big win.
one option is to use gsoap which produces a C WSDL client
and then use that client through GO with cgo