The request body does not reach golang fiber - rest

When I send a POST request, the server does not receive the request body. Only the id is added to the database
"package lists
import (
"github.com/fishkaoff/fiber-todo-list/pkg/common/models"
"github.com/gofiber/fiber/v2"
)
type AddTaskRequestBody struct {
title string `json:"title"`
description string `json:"description"`
}
func (h handler) Addtask(c *fiber.Ctx) error {
body := AddTaskRequestBody{}
if err := c.BodyParser(&body); err != nil {
return fiber.NewError(fiber.StatusBadRequest, err.Error())
}
title := body.title
description := body.title
if title == "" || description == "" {
return fiber.NewError(fiber.StatusBadRequest)
}
task := models.NewList(title, description)
if result := h.DB.Create(&task); result.Error != nil {
return fiber.NewError(fiber.StatusNotFound,
}
return c.Status(fiber.StatusCreated).JSON(&task)
}"
postman request:
enter image description here

the fields of the structure AddTaskRequestBody are not being exported. That may be the problem. Shouldn't title and description be uppercase - (https://golangbyexample.com/exported-unexported-fields-struct-go/)
type AddTaskRequestBody struct {
title string json:"title"
description string json:"description"
}

Related

GORM database colum with json data

I am trying to write an email service, where I want to store some data related to email into a Postgres DB using gorm. I have a field which needs to be stored as a JSON blob, which in request passed as a JSON object. When I am trying to migrate, it errors keep saying unsupported type map. When manually add the DB, then run gorm, it doesn't write the row to the database.
I have seen some example where it's using postgres.Json as field types, but I want the field loaded from the request as map[string]string.
// Email : Base with injected fields `UUID`, `CreatedAt`, `UpdatedAt`
type Email struct {
gorm.Model
Status string `grom:"type:varchar(32);not null"`
TemplateID string `grom:"type:varchar(256)"`
ToEmai string `grom:"type:varchar(256);not null"`
FromEmail string `grom:"type:varchar(256);not null"`
ToName string `grom:"type:varchar(256);not null"`
FromName string `grom:"type:varchar(256);not null"`
Subject string `grom:"type:varchar(256)"`
Message string `grom:"type:varchar"`
DynamicData *map[string]string `grom:"type:json"`
}
this is my model.
then I do a gin request:
// SendEmail : sends an email
func SendEmail(c *gin.Context) {
body, err := ioutil.ReadAll(c.Request.Body)
if err != nil {
log.Error("Error reading request body to get rate estimates")
}
var newEmail = models.Email{
Status: "PENDING",
}
jsonErr := json.Unmarshal(body, &newEmail)
if jsonErr != nil {
log.Error(jsonErr)
}
database.DB.Create(&newEmail)
defer c.Request.Body.Close()
err = newEmail.SendSendgridEmail()
if err != nil {
c.JSON(http.StatusBadRequest, err)
} else {
c.JSON(http.StatusOK, "Successfully sent email")
}
}
which then looks into this function
func (e Email) dynamicTemplateEmailBody() []byte {
newMail := mail.NewV3Mail()
emailFrom := mail.NewEmail(e.FromName, e.FromEmail)
newMail.SetFrom(emailFrom)
newMail.SetTemplateID(e.TemplateID)
p := mail.NewPersonalization()
tos := []*mail.Email{
mail.NewEmail(e.ToName, e.ToEmai),
}
p.AddTos(tos...)
if e.DynamicData != nil {
for key, value := range *e.DynamicData {
log.Infof("%s %s", key, value)
p.SetDynamicTemplateData(key, value)
}
}
newMail.AddPersonalizations(p)
return mail.GetRequestBody(newMail)
}
I would like to be able to run DB.AutoMigrate(&models.Email{}) and automatically migrate the objects, or and when I make a request to the endpoint, the row gets added to my email table.

MutableSideEffect() panics when setting second value

We're in the process of writing a .NET Cadence client and are a bit confused with how MutableSideEffect() is supposed to work. We've been thinking of the ID being passed as essentially a variable name and that developers should be able to update mutable values in a workflow. When we try this though, the second MutableSideEffect() call fails with this panic:
panic: adding duplicate decision DecisionType: Marker, ID: MutableSideEffect_value-1, state=Created, isDone()=false, history=[Created]
We munged the greetings workflow sample to make these calls:
package main
import (
"fmt"
"math/rand"
"time"
"go.uber.org/cadence/activity"
"go.uber.org/cadence/workflow"
"go.uber.org/zap"
)
/**
* This greetings sample workflow executes 3 activities in sequential. It gets greeting and name from 2 different activities,
* and then pass greeting and name as input to a 3rd activity to generate final greetings.
*/
// ApplicationName is the task list for this sample
const ApplicationName = "greetingsGroup"
// This is registration process where you register all your workflows
// and activity function handlers.
func init() {
workflow.Register(SampleGreetingsWorkflow)
activity.Register(getGreetingActivity)
activity.Register(getNameActivity)
activity.Register(sayGreetingActivity)
}
// SampleGreetingsWorkflow Workflow Decider.
func SampleGreetingsWorkflow(ctx workflow.Context) error {
// Get Greeting.
ao := workflow.ActivityOptions{
ScheduleToStartTimeout: time.Minute,
StartToCloseTimeout: time.Minute,
HeartbeatTimeout: time.Second * 20,
}
ctx = workflow.WithActivityOptions(ctx, ao)
logger := workflow.GetLogger(ctx)
var greetResult string
err := workflow.ExecuteActivity(ctx, getGreetingActivity).Get(ctx, &greetResult)
if err != nil {
logger.Error("Get greeting failed.", zap.Error(err))
return err
}
f := func(ctx workflow.Context) interface{} {
return rand.Intn(100)
}
e := func(a, b interface{}) bool {
if a == b {
return true
}
return false
}
var result int
sideEffectValue := workflow.MutableSideEffect(ctx, "value-1", f, e)
err = sideEffectValue.Get(&result)
if err != nil {
panic(err)
}
logger.Debug("MutableSideEffect-1", zap.Int("Value", result))
//************** THIS CALL FAILS **************
sideEffectValue = workflow.MutableSideEffect(ctx, "value-1", f, e)
err = sideEffectValue.Get(&result)
if err != nil {
panic(err)
}
logger.Debug("MutableSideEffect-2", zap.Int("Value", result))
// Get Name.
var nameResult string
err = workflow.ExecuteActivity(ctx, getNameActivity).Get(ctx, &nameResult)
if err != nil {
logger.Error("Get name failed.", zap.Error(err))
return err
}
// Say Greeting.
var sayResult string
err = workflow.ExecuteActivity(ctx, sayGreetingActivity, greetResult, nameResult).Get(ctx, &sayResult)
if err != nil {
logger.Error("Marshalling failed with error.", zap.Error(err))
return err
}
logger.Info("Workflow completed.", zap.String("Result", sayResult))
return nil
}
// Get Name Activity.
func getNameActivity() (string, error) {
return "Cadence", nil
}
// Get Greeting Activity.
func getGreetingActivity() (string, error) {
return "Hello", nil
}
// Say Greeting Activity.
func sayGreetingActivity(greeting string, name string) (string, error) {
result := fmt.Sprintf("Greeting: %s %s!\n", greeting, name)
return result, nil
}
Are we thinking about this correctly?
This is a bug in the Go client library. It happens when a MutableSideEffect with the same id is used multiple times during a single decision.
If you force a separate decision by putting workflow.Sleep(ctx, time.Second) just before the second MutableSideEffect call the problem disappears.
I filed an issue to get this fixed.
Thanks a lot for reporting!

Insert data in Go API using nested objects(structs)

I'm creating a Golang API, but hit a blocker. For every POST, this is what I get:
"error": "sql: converting argument $2 type: unsupported type main.Data, a struct"
I'd like my data to be of format
"name": "test",
"other": {
"age": "",
"height": ""
}
}
How can I achieve this? See the code below, what I've tried so far.
model.go
type Data struct {
ID int `json:"id"`
Name string `json:"name,omitempty"`
Other *Other `json:"other,omitempty"`
}
type Other struct {
Age string `json:"host,omitempty"`
Height string `json:"database,omitempty"`
}
func (d *Data) Create(db *sql.DB) error {
err := db.QueryRow(
"INSERT INTO configs(name, other) VALUES($1, $2) RETURNING id",
d.Name, &d.Other).Scan(&d.ID)
if err != nil {
return err
}
return nil
}
controller.go
...
func (a *App) createData(w http.ResponseWriter, r *http.Request) {
var d Data
decoder := json.NewDecoder(r.Body)
if err := decoder.Decode(&d); err != nil {
fmt.Print(err)
fatalError(w, http.StatusBadRequest, "Invalid request")
return
}
defer r.Body.Close()
if err := d.Create(a.DB); err != nil {
fatalError(w, http.StatusInternalServerError, err.Error())
return
}
jsonResponse(w, http.StatusCreated, d)
}
I expected the db to be populated with the data of format
"name": "test",
"other": {
"age": "",
"height": ""
}
}
But fails with error:
"error": "sql: converting argument $2 type: unsupported type main.Data, a struct"
You can make this modification:
import "encoding/json"
func (d *Data) Create(db *sql.DB) error {
var jsonOther string
if d.Other != nil {
jsonOther, _ = json.Marshal(d.Other)
err := db.QueryRow(
"INSERT INTO configs(name, other) VALUES($1, $2) RETURNING id",
d.Name, jsonOther).Scan(&d.ID)
if err != nil {
return err
}
return nil
}
Notice that the Other object is explicitly serialized to JSON and passed as a string

MongoDB bson.M query

I am trying to query using bison all JSON data in MongoDB with two fields but am getting null as result.
{
"allowedList": [
{
"List": [
{
"allow": {
"ss": 1,
},
"Information": [
{
"Id": "Id1"
}
]
}
]
}
]
}
I was able to filter all using the MongoDB at command line using
db.slicedb.find({"allowedList.List.allow.ss":1,"allowedList.List.Information.nsiId":"Id-Id21"})
but using
query := bson.M{"allowedList.List.allow": bson.M{"ss": sst}, "allowedList.List.Information": bson.M{"Id": Id}}
sst and Id are integer and string input to the query function
err := db.C(COLLECTION).Find(query).All(&specificSlices)
but is not working, am getting null even though there are json data that match the two field. Can someone help point out what was wrong with my query?
Server and database config
type SliceDataAccess struct {
Server string
Database string
}
var db *mgo.Database
const (
COLLECTION = "slicedb"
)
Establish a connection to database
func (m *SliceDataAccess) Connect() {
session, err := mgo.DialWithTimeout(m.Server, 20*time.Second)
if err != nil {
log.Fatal(err)
}
db = session.DB(m.Database)
}
Structs fields
type InstanceInfo struct {
ID string `json:"nfId" bson:"_id"`
AllowedList []AllowedNssai `json:"allowedList" bson:"allowedList"`
}
type AllowedNssai struct {
List []AllowedSnssai `json:"List,omitempty" bson:"List"`
...
}
type AllowedSnssai struct {
Allow *Snssai `json:"allow,omitempty" bson:"allow"`
Information []NsiInformation `json:"Information,omitempty" bson:"Information"`
}
type NsiInformation struct {
Id string `json:"Id" bson:"Id"`
}
type Snssai struct {
Ss int32 `json:"sst" bson:"ss"`
}
Query function defined
func (m *SliceDataAccess) FindAll(sst int32, nsiId string ([]InstanceInfo, error) {
var specificSlices []InstanceInfo
query := bson.M{"allowedList.List.allow": bson.M{"ss": sst}, "allowedList.List.Information": bson.M{"Id": nsiId}}
err := db.C(COLLECTION).Find(query).All(&specificSlices)
if err != nil {
return specificSlices, err
}
return specificSlices, nil
}
HTTP handler function for request and response
func AvailabilityGet(w http.ResponseWriter, r *http.Request)
var slice InstanceInfo
err := json.NewDecoder(r.Body).Decode(&slice)
if err != nil {
respondWithError(w, http.StatusBadRequest, "Object body not well decoded")
return
}
sst := slice.AllowedList[0].List[0].Allow.Sst
nsiId := slice.AllowedList[0].List[0].Information[0].Id
specificSlices, err := da.FindAll(sst, nsiId)
json.NewEncoder(w).Encode(specificSlices)
}
Attached is my the full go code i have done.
this worked
query := bson.M{"allowedNssaiList.allowedSnssaiList.allowedSnssai.sst": sst, "allowedNssaiList.allowedSnssaiList.nsiInformationList.nsiId": nsiId}

How to assign BSON _Id to a cookie (Go, Mongodb)

I was trying to create a go cookie. I want to assign Id from Mongodb to be stored in the Cookie. But while compiling I am getting an error as follows:-
"unknown http.Cookie field 'Id' in struct literal"
The following is my code:-
getUser := user.CheckDB()
expiration := time.Now().Add(365 * 24 * time.Hour)
//The Error is Caused by the Next Line
cookie := http.Cookie{Id: getUser[0].Id, Name: getUser[0].Email, Value: getUser[0].Password, Expires: expiration}
http.SetCookie(w, &cookie)
func (this *User) CheckDB() []User {
var results []User
sess, db := GetDatabase()
defer sess.Close()
c := db.C("user")
uname := &this.Email
err := c.Find(bson.M{"email": *uname}).Sort("-id").All(&results)
if err != nil {
panic(err)
} else {
fmt.Println("Results All: ", results)
return results
}
}
type Cookie struct {
Id bson.ObjectId `bson:"_id,omitempty"`
Name string
Value string
Path string
Domain string
Expires time.Time
RawExpires string
MaxAge int
Secure bool
HttpOnly bool
Raw string
Unparsed []string
}
Thanks in advance.
Here is a solution for this problem.
Cookie struct below:
type Cookie struct {
Name string
Value string
Path string
Domain string
Expires time.Time
RawExpires string
MaxAge int
Secure bool
HttpOnly bool
Raw string
Unparsed []string
}
Cookie Creation
value := map[string]string{
"id": cookieId,
}
if encoded, err := ckieHandler.Encode("session", value); err == nil {
cookie := &http.Cookie{
Name: "session",
Value: encoded,
Path: "/",
}
http.SetCookie(response, cookie)
}
Cookie Call
if cookie, err := request.Cookie("session"); err == nil {
cookieValue := make(map[string]string)
if err = ckieHandler.Decode("session", cookie.Value, &cookieValue); err == nil {
id = cookieValue["id"] // **Pass BSON ID here**
}
}
For more details Click Here. This link helped me a lot. Hoping someone will find this answer useful.