I am developing an API in Golang (with Buffalo library).
I have my route set to point to :
func (ur UserResource) Create(c buffalo.Context) error {
// new User
u := &models.User{}
if err := c.Bind(u); err != nil {
return c.Render(500, r.String(err.Error()))
}
id, _ := uuid.NewV4()
u.ID = id
db[u.ID] = *u
return c.Render(201, r.JSON(u))
}
The problem is that when I test my api I have the following error :
(and my header Content-Type is set to multipart/form-data)
If I change the way values are passed to form-url-encoded and set no header, I have this error :
invalid character 'i' in literal false (expecting 'a')
Related
I have written a controller GetUser to get a particular user from Database(Firestore) on the basis of id I put in the query. If the user is not present in the database then it should give the message that "User not found". But along with this message I am getting nil keyword also in response.
The response I am getting:
{
"message": "User not found"
}null
When I hover on dsnap.Data() I get the information that
(firestore.DocumentSnapshot).Data on pkg.go.dev
Data returns the DocumentSnapshot's fields as a map. It is equivalent to
var m map[string]interface{}
d.DataTo(&m)
except that it returns nil if the document does not exist.
Controller:
func GetUser(c *gin.Context) {
paramID := c.Params.ByName("id")
........
........
........
dsnap, err := client.Collection("users").Doc(paramID).Get(ctx)
if err != nil {
fmt.Print(err)
c.IndentedJSON(http.StatusNotFound, gin.H{
"message": "User not found",
})
}
m := dsnap.Data()
c.IndentedJSON(http.StatusNotFound, gin.H(m))
}
Firestore reference link: https://pkg.go.dev/cloud.google.com/go/firestore#v1.6.1#DocumentSnapshot.Data
Can you guys please tell me how can I remove nil from the response?
Thank you.
This problem is solved now. I write "return" after the User not found response.
I am trying to create a charge in Stripe following API documentation but without success :
jsnObj := TJSONObject.Create;
jsnObj.AddPair('amount', TJSONNumber.Create('111'));
jsnObj.AddPair('currency', 'eur');
jsnObj.AddPair('customer', 'cus_JL30ptApR3U2gL');
jsnObj.AddPair('description', 'My First Test');
ss := TStringStream.Create(jsnObj.ToString);
rs := TStringStream.Create;
IdHTTP1.Request.BasicAuthentication := True;
IdHTTP1.Request.Username := ApiKey ; // test private key
IdHTTP1.Post('https://api.stripe.com/v1/charges', ss, rs);
StatusBar1.SimpleText := IdHTTP1.ResponseText;
the result is always error :
{
"error": {
"code": "parameter_missing",
"doc_url": "https://stripe.com/docs/error-codes/parameter-missing",
"message": "Must provide source or customer.",
"type": "invalid_request_error"
}
}
Http returns 400 bad request.
All data is correct but the source parameter is missing as Stripe documentation states that it is optional so I include customer parameter instead and it should work.
Other calls to the Stripe API are successful with the same code (connect, retrieve objects etc.)
Thanks for any tips..
I am trying to retrieve Stripe datas and parse them into a CSV file.
Here is my code:
package main
import (
"github.com/stripe/stripe-go"
"github.com/stripe/stripe-go/invoice"
"fmt"
"os"
"encoding/csv"
)
func main() {
stripe.Key = "" // I can't share the API key
params := &stripe.InvoiceListParams{}
params.Filters.AddFilter("limit", "", "3")
params.Filters.AddFilter("status", "", "paid")
i := invoice.List(params)
// Create a CSV file
csvdatafile, err := os.Create("./mycsvfile.csv")
if err != nil {
fmt.Println(err)
}
defer csvdatafile.Close()
// Write Unmarshaled json data to CSV file
w := csv.NewWriter(csvdatafile)
//Column title
var header []string
header = append(header, "ID")
w.Write(header)
for i.Next() {
in := i.Invoice()
fmt.Printf(in.ID) // It is working
w.Write(in) // It is not working
}
w.Flush()
fmt.Println("Appending succed")
}
When I am running my program with go run *.go I obtain the following error:
./main.go:35:10: cannot use in (type *stripe.Invoice) as type []string in argument to w.Write
I think I am not far from the solution.
I just need to understand how to write correctly in the CSV file thank's to w.Write() command.
According to the doc, the Write function is:
func (w *Writer) Write(record []string) error
That is, it is expecting you to pass a slice of strings representing a line of CSV data with each string being a slice. So, if you have only one field, you have to pass a string slice of 1:
w.Write([]string{in.ID})
I'm doing a simple rest API which does the following:
get base64 encoded image
decode it
stores it on on specific google bucket
Now, on the GET verb, my api returns a signed url targeting the bucket image.
I've coded a test that works:
initialization stuff
...
BeforeEach(func() {
mockStringGenerator.On("GenerateUuid").Return("image1")
// First store
image, _ = ioutil.ReadFile("test_data/DSCF6458.JPG")
encodedImage = b64.RawStdEncoding.EncodeToString(image)
fileName, storeError = storage.Store(ctx, encodedImage, "image/jpeg")
// Then get
uri, getError = storage.Get(ctx, fileName)
getResponse, _ = http.Get(uri)
// Finally delete
deleteError = storage.Delete(ctx, fileName)
})
// Only 1 test to avoid making too much connexion
It("should create, get and delete the image", func() {
// Store
Expect(storeError).To(BeNil())
Expect(fileName).To(Equal("image1.jpg"))
// Get
Expect(getError).To(BeNil())
Expect(getResponse.StatusCode).To(Equal(http.StatusOK))
b, _ := ioutil.ReadAll(getResponse.Body)
Expect(b).To(Equal(image))
// Delete
Expect(deleteError).To(BeNil())
})
But when I run the .exe and try to make ssome request with postman, I get a 403 error in the signed url:
<?xml version='1.0' encoding='UTF-8'?>
<Error>
<Code>AccessDenied</Code>
<Message>Access denied.</Message>
<Details>Anonymous caller does not have storage.objects.get access to teddycare-images/08d8c508-d97d-48d3-947b-a7f216f622db.jpg.</Details>
</Error>
Any ideas ? I really don't understand...
Save me guys
[EDIT] Here after the code I use to create signedUrl:
func (s *GoogleStorage) Get(ctx context.Context, fileName string) (string, error) {
url, err := storage.SignedURL(s.Config.BucketImagesName, fileName, &storage.SignedURLOptions{
GoogleAccessID: s.Config.BucketServiceAccountDetails.ClientEmail,
PrivateKey: []byte(s.Config.BucketServiceAccountDetails.PrivateKey),
Method: http.MethodGet,
Expires: time.Now().Add(time.Second * 180),
})
if err != nil {
return "", err
}
return url, nil
}
Ok, after I woke up, I found the answer.
It turns out that when the json is marshalized into string, all the special characters are encoded.
Example: & -> \u0026
So the url I tested in my UT had &, while the url returned by the api had \u0026, and google does not seem to have the same behaviour on both cases.
So the solution is to disable HTML escaping:
encoder := json.NewEncoder(w)
encoder.SetEscapeHTML(false)
return encoder.Encode(response)
I tried to get the ebay user token.
I've alreay gotten auth code in ebay, but can't get user token with auth code.
Code is following:
status := ctx.UserValue("status").(string)
applicationToken := string(ctx.QueryArgs().Peek("code"))
log.Println("ApplicationToken: ", applicationToken)
log.Println("Status: ", status)
if status == "declined" {
fmt.Printf("User doesn't give permission. Go back to your dashboard.")
ctx.Redirect("/dashboard", fasthttp.StatusSeeOther)
}
//var appConfig = config.Config()
client := &http.Client{}
applicationTokenURLEncoded, _ := url.Parse(applicationToken)
body := url.Values{
"grant_type": {"authorization_code"},
"code": {applicationTokenURLEncoded.String()},
"redirect_uri": {Runame},
}
reqBody := bytes.NewBufferString(body.Encode())
log.Println("Reqbody: ", reqBody)
req, _ := http.NewRequest("POST", "https://api.sandbox.ebay.com/identity/v1/oauth2/token", reqBody)
authorization := “AppID” + ":" + “CertID”
authorizationBase64 := base64.StdEncoding.EncodeToString([]byte(authorization))
req.Header.Add("Authorization", "Basic "+authorizationBase64)
req.Header.Add("Content-Type", "application/x-www-form-urlencoded")
log.Println("Body: ", req)
resp, _ := client.Do(req)
log.Println("resp: ", resp)
log.Println("ResBody: ", resp.Body)
And the error is like that:
Bad Request 400
I looks like the message isn't formed correctly (which is why the server returns 400).
When you're setting your headers you write:
req.Header.Add("Authorization", "Basic "+authorizationBase64)
req.Header.Add("Content-Type", "application/x-www-form-urlencoded")
Golang has a nice built in way to add Authorization to a Header: SetBasicAuth, which is a method of http.Request.
func (r *Request) SetBasicAuth(username, password string)
SetBasicAuth sets the request's Authorization header to use HTTP Basic Authentication with the provided username and password.
With HTTP Basic Authentication the provided username and password are not encrypted.
So instead of setting the Authorization Header manually, you could try:
req.SetBasicAuth("AppID”, “CertID”)
You were using something called CertID, but I think you meant ClientId and ClientSecret -- respectively user and password
I don't know if this is the cause of your problem :). One way to help find out, is consistent error checking, see your line:
applicationTokenURLEncoded, _ := url.Parse(applicationToken)