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
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.
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
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)
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())
}
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.