Functionality of Beego syntax 'Ctx.Input.GetData('<variable-name>')' - go

I am new to beego and goLang. I came across a code. If someone could explain the flow it would be very helpful. It is a GET API. I think Prepare() is like a filter. What I don't understand is c.Ctx.Input.GetData("customerid") and c.Ctx.Input.GetData("customergroupid") functions. Can someone explain me what GetData is doing and how we can pass values to them?
// URLMapping ...
func (c *CampusHomeController) URLMapping() {
c.Mapping("GetOne", c.GetOne)
}
func (c *CampusHomeController) Prepare() {
if c.Ctx.Input.GetData("customerid") == "" {
returnJSON := postCampusHomeJSON{}
returnJSON.Code = 403
returnJSON.Msg = "Invalid Session"
c.Data["json"] = &returnJSON
c.ServeJSON()
c.StopRun()
}
if c.Ctx.Input.GetData("customergroupid") == "" ||
c.Ctx.Input.GetData("customergroupid") == nil {
returnJSON := postCampusHomeJSON{}
returnJSON.Code = 404
returnJSON.Msg = "User not a campus manager"
c.Data["json"] = &returnJSON
c.ServeJSON()
c.StopRun()
}
}

GetData is used to get data from filters in your controllers. It allows you to pass values other than just strings.
From the Beego documentation:
GetData
Get value of Data in Input
SetData
Set value of Data in Input. GetData and SetData is used to pass data from Filter to Controller
https://beego.me/docs/module/context.md

Related

Spring cache for specific values #Cacheable annotation

I want to cache a result of a method only when the attribute of the result contains specific values. For example
Class APIOutput(code: Int, message: String)
sealed class Response<out T : Any> : Serializable {
data class Success<out T : Any>(val data: T) : Response<T>()
data class Error(val errorText: String, val errorCode: Int) : Response<Nothing>()
}
#Cacheable(
key = "api-key",
unless = "do something here"
)
fun doApicall(uniqueId: Long): Response<APIOutput> {
//make API call
val output = callAPI(uniqueId)
return Response.Success(output)
}
In the above method, I want to cache the response only when Response.Success.data.code == (long list of codes).
Please note, in the previous line data is nothing but APIOutput object. How could I achieve it using unless or any other approach. I was thinking of writing a function that takes a doApicall method result as input and would return true or false and call that method it as unless="call a method". But I'm not sure how to do it. Any help is highly appreciated.
You can specify an expression to be evaluated in unless using SpEL. The returned value is available as result so you can do something like -
#Cacheable(
key = "api-key",
unless = "#result!=null or #result.success.data.code!=200"
)
fun doApicall(uniqueId: Long): Response<APIOutput> {
//make API call
val output = callAPI(uniqueId)
return Response.Success(output)
}
You can even use Regex in SpEL and can create custom Expression parsers if the existing functionality is not enough for your usecase.
Thanks Yatharth and John! Below is the condition that worked for me. resultcodes in the below expression is a list
#Cacheable(
key = "api-key",
unless = "!(#result instanceof T(com.abc.Response\$Success))
or (#result instanceof T(com.abc.Response\$Success)
and !(T(com.abc.APIStatus).resultCodes.contains(#result.data.code)))"
)
fun doApicall(uniqueId: Long): Response<APIOutput> {
//make API call
val output = callAPI(uniqueId)
return Response.Success(output)
}

How to get all fields in a response in graphql without passing any field names in a query

I'm building a graphql interface using golang. I'm using gqlgen package to implement it.
Here I need to pass all field names in a query to get it in response, But the problem is my data is huge, it is having more than 30 fields it would be difficult to pass all fields in a query.
This is my query
{Model{id, name, email, mobile,...............}}
Like this I need to pass all fields name.
Instead Im looking for a result which will return all fields without passing any fields. I mean if not passing any field names it should return all.
For example
{Model{}}
First, you really should list out all the fields in your query. That is the nature of graphql. It is verbose, but most client libraries get the fields from your data structure anyway, so it's not that bad.
So I recommend listing out all fields manually!
Using Scalars (must be on v0.11.3 or below, see https://github.com/99designs/gqlgen/issues/1293)
But if you insist, if there is a will, there is way. You can use GraphQL's scalar types and make your own. See this doc for how to make them with gqlgen: https://gqlgen.com/reference/scalars/
In your schema, you can make a JSON scalar:
scalar JSON
type Query {
random: JSON!
}
Make a model for this
// in your own models.go
// You can really play with this to make it better, easier to use
type JSONScalar json.RawMessage
// UnmarshalGQL implements the graphql.Unmarshaler interface
func (y *JSONScalar) UnmarshalGQL(v interface{}) error {
data, ok := v.(string)
if !ok {
return fmt.Errorf("Scalar must be a string")
}
*y = []byte(data)
return nil
}
// MarshalGQL implements the graphql.Marshaler interface
func (y JSONScalar) MarshalGQL(w io.Writer) {
_, _ = w.Write(y)
}
Then link the scalar to your custom type in the gql.yml
models:
JSON:
model: github.com/your-project/path/graph/model.JSONScalar
When you run the generate (use gqlgen v0.11.3 or below, gqlgen version), your resolvers will now use the custom type you made. And it's easy to use:
func (r *queryResolver) random(ctx context.Context) (model.JSONScalar, error) {
// something is the data structure you want to return as json
something := struct {
Value string
}{
Value: "Hello World",
}
d, _ := json.Marshal(something)
return model1.JSONScalar(d), nil
}
The resulting query of
// Query
{
random
}
// Response
{
"random" : {
"Value": "Hello World!"
}
}

Declared but not used

I am new to Golang. I am confused why I got the error that partial is not used in the code below?
// Using var keyword
var partial string
for i, request := range requestVec {
if i == (len(requestVec)-1) && !strings.Contains(request, "\r\n\r\n") {
partial = request
break
}
}
I assign request to partial in the if statement.
It is a compiler error in Go to declare a variable without using it.
In the code in you're example the variable partial is never used, only assigned, so is seen as unused. If you added additional code that read the variable then the error would be resolved. For example
var partial string
for i, request := range requestVec {
if i == (len(requestVec)-1) && !strings.Contains(request, "\r\n\r\n") {
partial = request
break
}
}
fmt.Println(partial) // We are now using `partial`

How to parse array inside form post

I currently have a form post that is coming in like
{
"stuff":"cool text",
"otherthing":"neat thing",
"captions":[
{"first":"the list",
"second":"how are you"},
{"first":"wow",
etc....
]
}
Now I don't know how many captions there will be. It might be one in the array, it might be twenty.
I have set up two structures as well
type ThingContext struct {
Stuff string `json:"stuff"`
OtherThing string `json:"otherthing"`
Captions []ArrayText `json:"captions"`
}
type ArrayText struct {
First string `json:"first"`
Second string `json:"second"`
}
And in my golang function I have something like this
func (c *ThingContext) SetThingContext(rw web.ResponseWriter, req *web.Request, next web.NextMiddlewareFunc) {
if err := req.ParseForm(); err != nil {
}
c.Stuff = req.FormValue("stuff")
c.OtherThing = req.FormValue("otherthing")
}
This works fine till I try and parse the array.
When I do something along the lines of c.Captions = req.ParseForm("captions")
I get the error
.cannot use req.Request.ParseForm("captions") (type error) as type []ArrayText in assignment
You're doing it right, except for the assignment. When you run req.Request.ParseForm(), rather than returning a value, or passing in a reference to a buffer, it populates the req.Request.Form and req.Request.PostForm structures.
The related GoDoc explaining said function
So rather than
c.Captions = req.Request.ParseForm()
It would look more like
err := req.Request.ParseForm()
//check for errors as usual here
c.Captions = req.Request.Form
//or
c.Captions = req.Request.PostForm
Approaching it from this direction should put you on the right track.
Cheers!
Taylor

Initializing structures dynamically

I have a couple of structures, like:
type SomeObject struct {
sample int
}
I want to fill the sample variable based on what I get in the request body. To do this, I want to create a function, pass request body as a string to it, create an empty structure inside, fill the structure with data, return it, and replace chosen structure with this.
How do I do this? What do I return from the function? Is there a way to do this?
If you're dealing with multiple types then you should make your method return an interface{}. For all of the applicable types, create a convenience method like;
func NewSomeObject(reqBody string) *SomeObject {
return &SomeObject{sample:reqBody}
}
Which takes a string and returns a new instance of the type with that field set to whatever was passed in. Your question is missing information about how you determine which type should be instantiated but assuming you have a few, you'll likely need an if/else or a switch in the method which receives the request body so to give a very vague example it would be something like;
func ProcessRequest(reqBody string) interface{} {
if someCondition {
return NewSomeObject(reqBody)
} else if otherCondition {
return NewSomeOtherObject(reqBody)
} // potentially several other statements like this
return nil // catch all, if no conditions match
}
How about
func foo (s *SomeObject) {
s.sample = 123
}
or
func (s *SomeObject) foo() {
s.sample = 123
}

Resources