Decode JSON from URL query param - go

I am a newbie for golang proto. I need to decrypt the string that I was getting from the query param.
This is my string.
%7B%22predicates%22%3A%5B%7B%22key%22%3A%22name%22%2C%22op%22%3A%22IS_SUBSTRING%22%2C%22string_value%22%3A%22123%22%7D%2C%7B%22key%22%3A%22storage_state%22%2C%22op%22%3A%22NOT_EQUALS%22%2C%22string_value%22%3A%22STORAGESTATE_ARCHIVED%22%7D%5D%7D
I couldn't find how to decrypt this string.
Can anyone provide me an idea to decrypt this string using golang
Thanks in advance

Using urldecode and result like this:
{"predicates":[{"key":"name","op":"IS_SUBSTRING","string_value":"123"},{"key":"storage_state","op":"NOT_EQUALS","string_value":"STORAGESTATE_ARCHIVED"}]}
You can using 3rd lib or online website to decode it:https://www.urldecoder.org/

You may use url.PathUnescape(s) from std lib (try it online):
package main
import (
"fmt"
"log"
"net/url"
)
func main() {
s := `%7B%22predicates%22%3A%5B%7B%22key%22%3A%22name%22%2C%22op%22%3A%22IS_SUBSTRING%22%2C%22string_value%22%3A%22123%22%7D%2C%7B%22key%22%3A%22storage_state%22%2C%22op%22%3A%22NOT_EQUALS%22%2C%22string_value%22%3A%22STORAGESTATE_ARCHIVED%22%7D%5D%7D`
st, err := url.PathUnescape(s)
if err != nil {
log.Fatal(err)
}
fmt.Println(st)
}
Output:
{"predicates":[{"key":"name","op":"IS_SUBSTRING","string_value":"123"},{"key":"storage_state","op":"NOT_EQUALS","string_value":"STORAGESTATE_ARCHIVED"}]}
You may Unmarshal:
var m map[string]interface{}
err = json.Unmarshal([]byte(st), &m)
if err != nil {
log.Fatal(err)
}
Or decode:
d := json.NewDecoder(strings.NewReader(st))
var m map[string]interface{}
err = d.Decode(&m)
if err != nil {
log.Fatal(err)
}
fmt.Println(m)

Related

Semantic way of http.Response receiver functions in Go

I just started learning GO and wrote this piece of code that writes an http.Response.Body to os.Stdout or to a file, but I'm not happy about the semantics of this.
I want the http.Response struct to have these receiver functions, so I can use it more easily throughout the entire app.
I know that the answers might get flagged as opinionated, but I still wonder, is there a better way of writing this?
Is there some sort of best practice?
package main
import (
"fmt"
"io"
"io/ioutil"
"net/http"
"os"
)
type httpResp http.Response
func main() {
res, err := http.Get("http://www.stackoverflow.com")
if err != nil {
fmt.Println("Error: ", err)
os.Exit(1)
}
defer res.Body.Close()
response := httpResp(*res)
response.toFile("stckovrflw.html")
response.toStdOut()
}
func (r httpResp) toFile(filename string) {
str, err := ioutil.ReadAll(r.Body)
if err != nil {
panic(err)
}
ioutil.WriteFile(filename, []byte(str), 0666)
}
func (r httpResp) toStdOut() {
_, err := io.Copy(os.Stdout, r.Body)
if err != nil {
panic(err)
}
}
On a side note, is there a way to make the http.Get method spit out a custom type that already has access to these receiver functions without the need for casting? So i could do something like this:
func main() {
res, err := http.Get("http://www.stackoverflow.com")
if err != nil {
fmt.Println("Error: ", err)
os.Exit(1)
}
defer res.Body.Close()
res.toFile("stckovrflw.html")
res.toStdOut()
}
Thanks!
You don't have to implement these functions. *http.Response already implements io.Writer:
Write writes r to w in the HTTP/1.x server response format, including the status line, headers, body, and optional trailer.
package main
import (
"net/http"
"os"
)
func main() {
r := &http.Response{}
r.Write(os.Stdout)
}
In the example above, the zero value prints:
HTTP/0.0 000 status code 0
Content-Length: 0
Playground: https://play.golang.org/p/2AUEAUPCA8j
In case you need additional business logic in the write methods, you can embed *http.Response in your defined type:
type RespWrapper struct {
*http.Response
}
func (w *RespWrapper) toStdOut() {
_, err := io.Copy(os.Stdout, w.Body)
if err != nil {
panic(err)
}
}
But then you must construct a variable of type RespWrapper with the *http.Response:
func main() {
// resp with a fake body
r := &http.Response{Body: io.NopCloser(strings.NewReader("foo"))}
// or r, _ := http.Get("example.com")
// construct the wrapper
wrapper := &RespWrapper{Response: r}
wrapper.toStdOut()
}
is there a way to make the http.Get method spit out a custom type
No, the return types of http.Get are (resp *http.Response, err error), that's part of the function signature, you can't change it.

Generate .pb file without using protoc in golang

I'm trying to generate .pb.go file using service.proto as file input in Go.
Is there a way to do it without using protoc binary (like directly using package github.com/golang/protobuf/protoc-gen-go)?
If you have a detail.proto like this:
message AppDetails {
optional string version = 4;
}
You can parse it into a message like this:
package main
import (
"fmt"
"github.com/golang/protobuf/proto"
"github.com/jhump/protoreflect/desc/protoparse"
"github.com/jhump/protoreflect/dynamic"
)
func parse(file, msg string) (*dynamic.Message, error) {
var p protoparse.Parser
fd, err := p.ParseFiles(file)
if err != nil {
return nil, err
}
md := fd[0].FindMessage(msg)
return dynamic.NewMessage(md), nil
}
func main() {
b := []byte("\"\vhello world")
m, err := parse("detail.proto", "AppDetails")
if err != nil {
panic(err)
}
if err := proto.Unmarshal(b, m); err != nil {
panic(err)
}
fmt.Println(m) // version:"hello world"
}
However you may notice, this package is still using the old Protobuf V1. I did
find a Pull Request for V2:
https://github.com/jhump/protoreflect/pull/354

How to pass variadic functions into another function

i am working with aws-sdk-v2 and I want to make a minimum working example using "secretsmanager" service.
I am trying to follow the steps in this similiar example which is using "kms" service.
here is my script:
package main
import (
"context"
"fmt"
"log"
"github.com/aws/aws-sdk-go-v2/aws"
"github.com/aws/aws-sdk-go-v2/config"
"github.com/aws/aws-sdk-go-v2/feature/ec2/imds"
"github.com/aws/aws-sdk-go-v2/service/secretsmanager"
)
func main() {
cfg, err := config.LoadDefaultConfig(context.TODO())
if err != nil {
log.Printf("error: %v", err)
return
}
client := imds.NewFromConfig(cfg)
region, err := client.GetRegion(context.TODO(), &imds.GetRegionInput{})
if err != nil {
log.Printf("Unable to retrieve the region from the EC2 instance %v\n", err)
}
fmt.Printf(region.Region)
svc := secretsmanager.NewFromConfig(cfg)
input := &secretsmanager.CreateSecretInput{Name: aws.String("test")}
opts := &secretsmanager.Options{Region: region.Region}
result, err := svc.CreateSecret(context.TODO(), input, opts)
if err != nil {
fmt.Println(err)
}
fmt.Println(result)
}
error:
./main.go:38:46: cannot use opts (type *secretsmanager.Options) as type func(*secretsmanager.Options) in argument to svc.CreateSecret
so the error is obviously in those line:
opts := &secretsmanager.Options{Region: region.Region}
result, err := svc.CreateSecret(context.TODO(), input, opts)
from the documentation, the function CreateSecret takes these input types:
func (c *Client) CreateSecret(ctx context.Context, params *CreateSecretInput, optFns ...func(*Options)) (*CreateSecretOutput, error)
I can't find out how can I create this ...func(*Options) part in my context. Can someone please help me with this part?
I figured it out:
opts := func(o *secretsmanager.Options) {
o.Region = region.Region
}
result, err := svc.CreateSecret(context.TODO(), input, opts)

unicode character in result execute template

I have this template
<data><datos name={{.Name}} phone={{.Phone}} email={{.Email}}></data>
And I'm running it like this:
buf := &bytes.Buffer{}
t := template.Must(template.New("dataPdf").Parse("<data><datos name={{.Name}} phone={{.Phone}} email={{.email}}></data>"))
err := t.Execute(buf, data)
if err != nil {
panic(err)
}
return buf.String()
All values ​​are overridden, but for some reason the < and > characters remain in unicode
\u003cdatos\u003e\
I update:
Verify and the error doesn't occur until this string value is assigned to a specific Struct object and then I try to convert it to json.
I cannot reproduce this. See a working example on the Go Playground https://play.golang.org/p/xKmjgzZxeES.
The output of the code below is
<data><datos name=Joe phone=123-456-7890 email=hunter2#a.com></data>
package main
import (
"bytes"
"fmt"
"text/template"
)
type Person struct {
Name string
Phone string
Email string
}
func main() {
buf := &bytes.Buffer{}
t := template.Must(template.New("dataPdf").Parse("<data><datos name={{.Name}} phone={{.Phone}} email={{.Email}}></data>"))
data := Person{Name: "Joe", Phone: "123-456-7890", Email: "hunter2#a.com"}
err := t.Execute(buf, data)
if err != nil {
panic(err)
}
fmt.Printf(buf.String())
}

How to serialize a nested struct with GOB encoding in GoLang?

I have a couple of example nested structs and need to serialize them. I am using the encoding/gob library, which should convert the struct data to bytes and the encoding/base64 library to convert the bytes to a readable base64 format. However, when I run my example code I get a serialization error error. I don't understand why this happens and how to fix the problem.
I followed this example: Golang serialize and deserialize back
Here is the code:
package main
import (
"bytes"
"encoding/base64"
"encoding/gob"
"errors"
"fmt"
)
type Hello struct {
greeting string
}
type Bye struct {
helloSaid Hello
byesaid Hello
}
func (b1 Bye) Serialize() (string, error) {
b := bytes.Buffer{}
e := gob.NewEncoder(&b)
err := e.Encode(b1)
if err != nil {
return string(b.Bytes()[:]), errors.New("serialization failed")
}
return base64.StdEncoding.EncodeToString(b.Bytes()), nil
}
func DeserializeBye(str string) (Bye, error) {
m := Bye{}
by, err := base64.StdEncoding.DecodeString(str)
if err != nil {
return m, errors.New("deserialization failed")
}
b := bytes.Buffer{}
b.Write(by)
d := gob.NewDecoder(&b)
err = d.Decode(&m)
if err != nil {
return m, errors.New("deserialization failed")
}
return m, nil
}
func main() {
h := Hello{greeting: "hello"}
b := Bye{helloSaid: h, byesaid: h}
serialized, err := b.Serialize()
if err != nil {
fmt.Println(err)
}
fmt.Println(serialized)
}
Please, make the fields of the Hello and Bye structures public. Please see the documentation for the gob package:
Structs encode and decode only exported fields.

Resources