So I'm receiving a request to my server that looks a little something like this
http://localhost:8080/#access_token=tokenhere&scope=scopeshere
and I can't seem to find a way to parse the token from the url.
If the # were a ? I could just parse it a standard query param.
I tried to just getting everything after the / and even the full URL, but with no luck.
Any help is greatly appreciated.
edit:
So I've solved the issue now, and the correct answer is you can't really do it in GO. So I made a simple package that will do it on the browser side and then send the token back to the server.
Check it out if you're trying to do local twitch API stuff in GO:
https://github.com/SimplySerenity/twitchOAuth
Anchor part is not even (generally) sent by a client to the server.
Eg, browsers don't send it.
For parse urls use the golang net/url package: https://golang.org/pkg/net/url/
OBS: You should use the Authorization header for send auth tokens.
Example code with extracted data from your example url:
package main
import (
"fmt"
"net"
"net/url"
)
func main() {
// Your url with hash
s := "http://localhost:8080/#access_token=tokenhere&scope=scopeshere"
// Parse the URL and ensure there are no errors.
u, err := url.Parse(s)
if err != nil {
panic(err)
}
// ---> here is where you will get the url hash #
fmt.Println(u.Fragment)
fragments, _ := url.ParseQuery(u.Fragment)
fmt.Println("Fragments:", fragments)
if fragments["access_token"] != nil {
fmt.Println("Access token:", fragments["access_token"][0])
} else {
fmt.Println("Access token not found")
}
// ---> Others data get from URL:
fmt.Println("\n\nOther data:\n")
// Accessing the scheme is straightforward.
fmt.Println("Scheme:", u.Scheme)
// The `Host` contains both the hostname and the port,
// if present. Use `SplitHostPort` to extract them.
fmt.Println("Host:", u.Host)
host, port, _ := net.SplitHostPort(u.Host)
fmt.Println("Host without port:", host)
fmt.Println("Port:",port)
// To get query params in a string of `k=v` format,
// use `RawQuery`. You can also parse query params
// into a map. The parsed query param maps are from
// strings to slices of strings, so index into `[0]`
// if you only want the first value.
fmt.Println("Raw query:", u.RawQuery)
m, _ := url.ParseQuery(u.RawQuery)
fmt.Println(m)
}
// part of this code was get from: https://gobyexample.com/url-parsing
Related
I'm trying to create a document in firestore using golang sdk
How can I check the error code returned by the call to DocumentRef.Get() ?
Right now I'm checking if the error contains "NotFound"... Definitely not ideal but can't seem to find anything else
Current Code:
doc := firestoreClient.Collection("users").Doc(id)
userSnapshot, err := doc.Get(ctx)
var u *User
if err != nil {
isNotFound := strings.Contains(err.Error(), "NotFound")
if isNotFound {
// create the document
}
}
Ideally I would like to do something like if err.Code == NotFound // handle appropriately
Or even better, if there's a right pattern for how to GetOrCreate an item in Firestore (using golang)
I just found this in the official docs(https://pkg.go.dev/cloud.google.com/go/firestore#DocumentRef.Get)
import (
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
)
status.Code(err) == codes.NotFound
Thanks for the pointer here! What is the idomatic way to get a single document from Firestore using Go?
Another thread: https://github.com/googleapis/google-cloud-go/issues/861
My Go gRPC server is instrumented with
Google Tracing span exporter:
import texporter "github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/trace"
...
gcp, err := texporter.NewExporter()
...
tracer := trace.NewTracerProvider(trace.WithSyncer(traceExporter),
trace.WithSampler(trace.AlwaysSample()))
otel.SetTracerProvider(tracer)
otelgrpc interceptors registered on the gRPC server.
unaryInterceptors := grpc_middleware.WithUnaryServerChain(
otelgrpc.UnaryServerInterceptor(),
)
streamInterceptors := grpc_middleware.WithStreamServerChain(
otelgrpc.StreamServerInterceptor(),
)
Now I'm trying to create a trace span inside the RPC implementation so I can have child spans for the method e.g.:
func (s *srv) Test(ctx context.Context, req *pb.Request) (*pb.TestResponse, error) {
// create a span here
span1 := [??????].Start()
doWork1()
span1.End()
span2 := [??????].Start()
doWork2()
span2.End()
...
}
However it is wildly unclear from the OpenTelemetry docs how does one do that.
Closest I've gotten is otel.GetTracerProvider().Tracer("some string here???") providing a Start(ctx)(ctx,Span). But it is not clear to me what string to provide here (my exporter doesn't have a url like the docs indicate) and this seems quite inconvenient.
I'm thinking there's something like a otelgrpc.SpanFromCtx(ctx) method somewhere that pulls the tracer+creates a span with the rpc ctx that I'm not finding. Sadly the docs are quite lacking on OT+gRPC+Go.
Since you are using github.com/GoogleCloudPlatform/opentelemetry-operations-go, you should use itself to create span rather than opentelemetry.
You can create a new span like this:
// Create custom span.
tracer := otel.TraceProvider().Tracer("example.com/trace")
err = func(ctx context.Context) error {
ctx, span := tracer.Start(ctx, "foo")
defer span.End()
// Do some work.
return nil
}(ctx)
For more detail, you can reference OpenTelemetry Google Cloud Trace Exporter
Hello fellow developers.
I am trying to learn GO while constructing a simple web API using sqlite3. I got stuck at somepoint where i am unable to delete rows from my table by sending a DELETE request from postman. I am trying to use the code below to delete a row. I have already verified that I have access to db and I can also delete rows by using command tool of sqlite3. I do not understand what is wrong!
func deleteArticle(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
params := mux.Vars(r) // get any params
db := connectToDB(dbName)
defer db.Close()
_, err := db.Query("DELETE FROM article WHERE id=" + params["id"])
if err != nil {
fmt.Fprintf(w, "article couldn't be found in db")
}
}
Here is the navigation part:
myRouter.HandleFunc("/articles/{id}", deleteArticle).Methods("DELETE")
No mather what I do I cannot delete an article from db using postman.
Thanks bunches.
Thanks to #mkopriva 's comments I have learned that
1.
It is very important that you do not use Query nor QueryRow for SQL
queries that do not return any rows, for these cases use the Exec
method. When you use Query you always have to assign the result to a
non-blank identifier, i.e. anything but _, and then invoke the Close
method on that once you're done with the result. If you do not do that
then your application will leak db connections and very soon will
start crashing.
2.
when you want to pass user input (including record ids) to your
queries you have to utilize, at all times, the parameter-reference
syntax supported by the sql dialect and/or dirver you are using, and
then pass the input separately. That means that you should never do
Exec("DELETE FROM article WHERE id=" + params["id"]),
instead you should always do
Exec("DELETE FROM article WHERE id= ?",params["id"])
If you do not do it the proper way and instead continue
using plain string concatenation your app will be vulnerable to SQL
injection attacks.
Regarding this information I have changed my code into:
func deleteArticle(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
params := mux.Vars(r) // get any params
db := connectToDB(dbName)
defer db.Close()
fmt.Printf("%q\n", params["id"])
statement, err := db.Prepare("DELETE FROM article WHERE id= ?")
if err != nil {
fmt.Fprintf(w, "article couldn't be found in db")
}
statement.Exec(params["id"])
}
Which has solved my problem. So thank you #mkopriva
I'm trying to do a request like this:
http://example.com/hello?name=username
But in the Docs I can't find a way to pass the payload parameter. (http.Get() only receives the url)
How can I do this request?
The simplest way it to simply add it to the URL:
http.Get("http://example.com/hello?name=username")
The way I prefer to do it is to use url.Values to build the query string:
v := url.Values{}
v.Set("name", "username")
url := fmt.Sprintf("http://example.com/hello?%s", v.Encode())
http.Get(url)
Here is my console:
GET http://localhost:8080/api/photos.json?token=ABCDEFGHIJKLMNOPQRSTUVWXYZ
200 OK
0
jquery.js (line 8526)
|Params| Headers Response JSON
token ABCDEFGHIJKLMNOPQRSTUVWXYZ
I am in the params tab. How do I access this and, for example log token to my terminal window.
In node: request.param('token')
Just use func (*Request) FormValue
FormValue returns the first value for the named component of the query. POST and PUT body parameters take precedence over URL query string values. FormValue calls ParseMultipartForm and ParseForm if necessary. To access multiple values of the same key use ParseForm.
Simple Server
package main
import (
"fmt"
"net/http"
)
func main() {
http.HandleFunc("/", home)
http.ListenAndServe(":4000", nil)
}
func home(w http.ResponseWriter , r *http.Request) {
fmt.Fprint(w, "<html><body><h1>Hello ", r.FormValue("token") , "</h1></body></html>")
}
Visit localhost:4000/photos.json?token=ABCDEFGHIJKLMNOPQRSTUVWXYZ you would get
Hello ABCDEFGHIJKLMNOPQRSTUVWXYZ
I suppose you have a http.Request. Let's suppose it's called hr.
Then you can do
hr.ParseForm()
and after that you may use hr.Form which is defined like this :
// Form contains the parsed form data, including both the URL
// field's query parameters and the POST or PUT form data.
// This field is only available after ParseForm is called.
// The HTTP client ignores Form and uses Body instead.
Form url.Values
where url.Values is a map :
type Values map[string][]string
Here's an example of use of a parsed form where I'm only interested in the first value for a given name :
func getFormValue(hr *http.Request, name string) string {
if values := hr.Form[name]; len(values) > 0 {
return values[0]
}
return ""
}