How to detect javascript alert using chromedp - go

I'm trying to identify that an alert popped up after navigating to a URL using chromedp. I tried using a listener as follows but I'm new to Golang so I'm not sure why it didn't work.
package main
import (
"context"
"log"
"fmt"
"github.com/chromedp/chromedp"
"github.com/chromedp/cdproto/page"
)
func main() {
// create context
url := "https://grey-acoustics.surge.sh/?__proto__[onload]=alert('hello')"
ctx, cancel := chromedp.NewContext(context.Background())
defer cancel()
chromedp.ListenTarget(ctx, func(ev interface{}) {
if ev, ok := ev.(*page.EventJavascriptDialogOpening); ok {
fmt.Println("Got an alert: %s", ev.Message)
}
})
// run task list
err := chromedp.Run(ctx,
chromedp.Navigate(url),
)
if err != nil {
log.Fatal(err)
}
}

For your specific URL it helped to wait for the iframe to load to receive the event, otherwise chromedp seems to stop because it is finished with its task list.
// run task list
err := chromedp.Run(ctx,
chromedp.Navigate(url),
chromedp.WaitVisible("iframe"),
)
}

Related

Partial succes on opentelemtry exporter in golang

I'm running a pod of open telemetry collector that is exposed to port 4318 (running node js demo working perfectly)
but running this basic code sample (which basically just running a simple program after initiating the Tracer and sending spans)
package main
import (
"context"
"fmt"
"log"
"os"
"os/signal"
"time"
"go.opentelemetry.io/otel"
"go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp"
// "go.opentelemetry.io/otel/propagation"
"go.opentelemetry.io/otel/sdk/resource"
sdktrace "go.opentelemetry.io/otel/sdk/trace"
semconv "go.opentelemetry.io/otel/semconv/v1.4.0"
)
func initProvider() func() {
ctx := context.Background()
_, err := resource.New(ctx,
resource.WithAttributes(
semconv.ServiceNameKey.String("test-service"),
),
)
handleErr(err, "failed to create resource")
traceExporter, err := otlptracehttp.New(ctx,
otlptracehttp.WithInsecure(),
otlptracehttp.WithEndpoint("localhost:4318"),
)
handleErr(err, "failed to create trace exporter")
bsp := sdktrace.NewBatchSpanProcessor(traceExporter)
tracerProvider := sdktrace.NewTracerProvider(
// sdktrace.WithSampler(sdktrace.AlwaysSample()),
// sdktrace.WithResource(res),
sdktrace.WithSpanProcessor(bsp),
)
otel.SetTracerProvider(tracerProvider)
// otel.SetTextMapPropagator(propagation.TraceContext{})
return func() {
handleErr(tracerProvider.Shutdown(ctx), "failed to shutdown TracerProvider")
}
}
func initialize() {
traceExp, err := otlptracehttp.New(
context.Background(),
otlptracehttp.WithEndpoint("127.0.0.1:8082"),
otlptracehttp.WithURLPath("v1/traces"),
otlptracehttp.WithInsecure(),
)
if err != nil {
fmt.Println(err)
}
bsp := sdktrace.NewBatchSpanProcessor(traceExp)
tracerProvider := sdktrace.NewTracerProvider(
sdktrace.WithSpanProcessor(bsp),
)
otel.SetTracerProvider(tracerProvider)
}
func main() {
log.Printf("Waiting for connection...")
ctx, cancel := signal.NotifyContext(context.Background(), os.Interrupt)
defer cancel()
// shutdown := initProvider()
// defer shutdown()
initProvider()
tracer := otel.Tracer("demo-client-tracer")
ctx, span := tracer.Start(context.TODO(), "span-name")
defer span.End()
for i := 0; i < 10; i++ {
_, iSpan := tracer.Start(ctx, fmt.Sprintf("Sample-%d", i))
log.Printf("Doing really hard work (%d / 10)\n", i+1)
<-time.After(time.Second)
iSpan.End()
}
log.Printf("Done!")
}
func handleErr(err error, message string) {
if err != nil {
log.Fatalf("%s: %v", message, err)
}
}
and Im getting :
OTLP partial success: empty message (0 spans rejected)
and no traces is being sent...
any ideas?
what am I missing ?

How Can I log-in Amazon with Golang Colly

I am trying login to my amazon buyer account for getting tracking info. I made wordpress-woocommerce login and getting infos but I could not for Amazon.
package main
import (
"fmt"
"log"
"github.com/gocolly/colly"
)
func main() {
// create a new collector
c := colly.NewCollector()
login_link := "https://www.amazon.de/-/en/ap/signin?openid.pape.max_auth_age=0&openid.return_to=https%3A%2F%2Fwww.amazon.de%2F%3Flanguage%3Den_GB%26ref_%3Dnav_signin&openid.identity=http%3A%2F%2Fspecs.openid.net%2Fauth%2F2.0%2Fidentifier_select&openid.assoc_handle=deflex&openid.mode=checkid_setup&openid.claimed_id=http%3A%2F%2Fspecs.openid.net%2Fauth%2F2.0%2Fidentifier_select&openid.ns=http%3A%2F%2Fspecs.openid.net%2Fauth%2F2.0&"
// authenticate
err := c.Post(login_link, map[string]string{"username": "mail#example.com", "password": "123qwerty"})
if err != nil {
log.Fatal(err)
}
// attach callbacks after login
c.OnResponse(func(r *colly.Response) {
log.Println("response received", r.StatusCode) //response received 200
})
c.OnHTML("div", func(h *colly.HTMLElement) {
fmt.Println("PRINT ALL: ", h.Text)
})
// start scraping
c.Visit("https://www.amazon.de/-/en/gp/your-account/order-history?ref_=ya_d_c_yo")
}
Wordpress Login One Page - Amazon Login Two Page. We probably need to scroll 2 pages for Amazon
https://i.stack.imgur.com/4TNj5.png -> Wordpress Login (One Page)
https://i.stack.imgur.com/bhE4m.png -> Amazon Login(Page #1 - Mail)
https://i.stack.imgur.com/0BFcA.png -> Amazon Login(Page #1 - Password)
chromedp is a very useful library in such cases. You may try the following snipet;
package main
import (
"context"
"os"
"time"
"github.com/chromedp/chromedp"
)
func main() {
var res []byte
ctx, cancel := chromedp.NewContext(context.Background(), chromedp.WithBrowserOption())
defer cancel()
err := chromedp.Run(ctx,
chromedp.Navigate("https://www.amazon.com"),
chromedp.WaitReady("body"),
chromedp.Click(`a[data-nav-role="signin"]`, chromedp.ByQuery),
chromedp.Sleep(time.Second*2),
chromedp.SetValue(`ap_email`, "youramazonemail", chromedp.ByID),
chromedp.Click(`continue`, chromedp.ByID),
chromedp.Sleep(time.Second*1),
chromedp.SetValue(`ap_password`, "youramazonpassword", chromedp.ByID),
chromedp.Click(`signInSubmit`, chromedp.ByID),
chromedp.Sleep(time.Second*2),
chromedp.CaptureScreenshot(&res),
)
if err != nil {
log.Fatal(err)
}
os.WriteFile("loggedin.png", res, 0644)
}
The example given above is basically navigates trough all steps required for login process. After successful login, you can use context (ctx) to navigate and get the information whatever you want by using same function.
chromedp.Run(ctx,
chromedp.Navigate(url),
...)

Issue parsing ed25519v1 keys generated by mkp224o

I used mkp224o to generate a key. Afterwards I tried to use Go to parse the key and start a service with Bine. Unfortunately I can't seem to be able to generate the same v3 onion address as mkp224o.
package main
import (
"bytes"
"context"
"crypto/ed25519"
"fmt"
"log"
"net/http"
"os"
"time"
"github.com/cretz/bine/tor"
"github.com/ipsn/go-libtor"
"github.com/pkg/errors"
)
func main() {
log.SetOutput(os.Stdout)
if len(os.Args) != 2 {
check(errors.New("need 1 argument"))
}
var known ed25519.PrivateKey
buf, _ := os.ReadFile("/home/user/mkp224o/onions/rocin4w356yd7jadjppabxivaz56z4k2wfvy5xpxieirenda3yt2aiqd.onion/hs_ed25519_secret_key")
known = bytes.TrimLeft(buf, "== ed25519v1-secret: type0 ==\x00\x00\x00")
fmt.Println("Starting and registering onion service, please wait a bit...")
t, err := tor.Start(context.Background(), &tor.StartConf{ProcessCreator: libtor.Creator, DebugWriter: nil})
check(errors.Wrap(err, "Failed to start tor"))
defer t.Close()
ctx, cancel := context.WithTimeout(context.Background(), 3*time.Minute)
defer cancel()
onion, err := t.Listen(ctx, &tor.ListenConf{Version3: true, RemotePorts: []int{80}, Key: known})
check(errors.Wrap(err, "Failed to create tor service"))
defer onion.Close()
fmt.Printf("Please open a Tor capable browser and navigate to http://%v.onion\n", onion.ID)
http.HandleFunc("/", pathHandler())
http.Serve(onion, nil)
}
func check(err error) {
if err != nil {
fmt.Fprintf(os.Stderr, "Error: %v\n", err)
os.Exit(1)
}
}
func pathHandler() http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
}
}
Returns:
Starting and registering onion service, please wait a bit...
Please open a Tor capable browser and navigate to http://r3jvsuoxe37pn6ik5vjvcxrky37bxsuopo5yn436r5pamjfkz2mkytqd.onion
when it should be returning the rocin4w356yd7jadjppabxivaz56z4k2wfvy5xpxieirenda3yt2aiqd.onion address that mkp224o generated. What am I missing?

go build doesn't recognise methods

I try to setup a small Golang Microservice for users with Gin and Mongodb.
package main
import (
"context"
"fmt"
"github.com/wzslr321/artiver/entity"
"github.com/wzslr321/artiver/settings"
"go.mongodb.org/mongo-driver/mongo"
"go.mongodb.org/mongo-driver/mongo/options"
"log"
"os"
"os/signal"
"syscall"
"time"
)
type application struct {
users *entity.UserCollection
}
var app *application
func init() {
initMongo()
}
func initMongo() {
oc := options.Client().ApplyURI(settings.MongodbSettings.Uri)
client, err := mongo.NewClient(oc)
if err != nil {
log.Fatalf("Error occured while initializing a new mongo client: %v", err)
}
ctx, cancel := context.WithTimeout(context.Background(), 15*time.Second)
defer cancel()
err = client.Connect(ctx)
if err != nil {
log.Fatalf("Errorr occurred while connecting to a client: %v", err)
}
defer func() {
if err = client.Disconnect(ctx); err != nil {
panic(err)
}
}()
log.Println("Successfully connected to the database!")
app = &application{
users: &entity.UserCollection{
C: client.Database("artiver").Collection("users"),
},
}
}
func main() {
router := app.InitRouter()
It doesn't show any errors in my IDE ( GoLand ), but when I try to build it I get an error:
# command-line-arguments
users/cmd/app/main.go:67:15: app.InitRouter undefined (type *application has no field or method InitRouter)
It it easily visible on the image above, that I do have access to such a method. It is defined in the same package.
package main
import (
"github.com/gin-gonic/gin"
cors "github.com/rs/cors/wrapper/gin"
"net/http"
)
func (app *application) InitRouter() *gin.Engine {
r := gin.New()
r.Use(gin.Recovery())
r.Use(cors.Default())
r.GET("/", func(ctx *gin.Context) {
ctx.String(http.StatusOK, "Hello World")
})
user := r.Group("/api/user")
{
user.POST("/add", app.CreateUser)
}
return r
}
I have no idea how am I supposed to fix it and what is done wrong. I'd appreciate any hint about what isn't done correctly.
Answer based on #mkopriva help in comments.
The issue was related to not running all needed .go files.
In my case, the solution was to build it this way in my Makefile:
go build -o $(path)users cmd/app/*
In similar cases, go run . most likely will do the job.

Making Golang TCP server concurrent

New to Go and trying to make a TCP server concurrent. I found multiple examples of this, including this one, but what I am trying to figure out is why some changes I made to a non concurrent version are not working.
This is the original sample code I started from
package main
import "bufio"
import "fmt"
import "log"
import "net"
import "strings" // only needed below for sample processing
func main() {
fmt.Println("Launching server...")
fmt.Println("Listen on port")
ln, err := net.Listen("tcp", "127.0.0.1:8081")
if err != nil {
log.Fatal(err)
}
defer ln.Close()
fmt.Println("Accept connection on port")
conn, err := ln.Accept()
if err != nil {
log.Fatal(err)
}
fmt.Println("Entering loop")
// run loop forever (or until ctrl-c)
for {
// will listen for message to process ending in newline (\n)
message, _ := bufio.NewReader(conn).ReadString('\n')
// output message received
fmt.Print("Message Received:", string(message))
// sample process for string received
newmessage := strings.ToUpper(message)
// send new string back to client
conn.Write([]byte(newmessage + "\n"))
}
}
The above works, but it is not concurrent.
This is the code after I modified it
package main
import "bufio"
import "fmt"
import "log"
import "net"
import "strings" // only needed below for sample processing
func handleConnection(conn net.Conn) {
fmt.Println("Inside function")
// run loop forever (or until ctrl-c)
for {
fmt.Println("Inside loop")
// will listen for message to process ending in newline (\n)
message, _ := bufio.NewReader(conn).ReadString('\n')
// output message received
fmt.Print("Message Received:", string(message))
// sample process for string received
newmessage := strings.ToUpper(message)
// send new string back to client
conn.Write([]byte(newmessage + "\n"))
}
}
func main() {
fmt.Println("Launching server...")
fmt.Println("Listen on port")
ln, err := net.Listen("tcp", "127.0.0.1:8081")
if err != nil {
log.Fatal(err)
}
//defer ln.Close()
fmt.Println("Accept connection on port")
conn, err := ln.Accept()
if err != nil {
log.Fatal(err)
}
fmt.Println("Calling handleConnection")
go handleConnection(conn)
}
I based my code on several other examples I found of concurrent servers, but yet when I run the above the server seems to exit instead of running the handleConnection function
Launching server...
Listen on port
Accept connection on port
Calling handleConnection
Would appreciate any feedback as similar code examples I found and tested using the same approach, concurrently calling function to handle connections, worked; so, would like to know what is different with my modified code from the other samples I saw since they seem to be the same to me.
I was not sure if it was the issue, but I tried commenting the defer call to close. That did not help.
Thanks.
Your main function is returning immediately after accepting a new connection, so your program exits before the connection can be handled. Since you probably also want to receive more than one single connection (or else there would be no concurrency), you should put this in a for loop.
You are also creating a new buffered reader in each iteration of the for loop, which would discard any buffered data. You need to do that outside the for loop, which I demonstrate here by creating a new bufio.Scanner which is a simpler way to read newline delimited text.
import (
"bufio"
"fmt"
"log"
"net"
"strings"
)
func handleConnection(conn net.Conn) {
defer conn.Close()
scanner := bufio.NewScanner(conn)
for scanner.Scan() {
message := scanner.Text()
fmt.Println("Message Received:", message)
newMessage := strings.ToUpper(message)
conn.Write([]byte(newMessage + "\n"))
}
if err := scanner.Err(); err != nil {
fmt.Println("error:", err)
}
}
func main() {
ln, err := net.Listen("tcp", "127.0.0.1:8081")
if err != nil {
log.Fatal(err)
}
fmt.Println("Accept connection on port")
for {
conn, err := ln.Accept()
if err != nil {
log.Fatal(err)
}
fmt.Println("Calling handleConnection")
go handleConnection(conn)
}
}
The reason you see this behavior is the fact that your main method exits even though your go routine is still running. Make sure to block the main method to achieve what you are trying to achieve.
May be add something like this in the main:
c := make(chan os.Signal)
signal.Notify(c, os.Interrupt, syscall.SIGTERM)
<-c // This will block until you manually exists with CRl-C
Also you can bring back your defer
When you run function using go func() syntax, you are executing a new goroutine without blocking the main one. However, the program will exit when the main goroutine finishes, so in short, you need to block the main goroutine for as long as you want your child goroutines to execute.
I often find myself checking how similar problems are solved in go standard library. For example, Server.Serve() from http package does something similar. Here is the extracted version (shortened, follow the link to see full version):
func (srv *Server) Serve(l net.Listener) error {
defer l.Close()
ctx := context.Background()
for {
rw, e := l.Accept()
if e != nil {
select {
case <-srv.getDoneChan():
return ErrServerClosed
default:
}
if ne, ok := e.(net.Error); ok && ne.Temporary() {
// handle the error
}
return e
}
c := srv.newConn(rw)
c.setState(c.rwc, StateNew) // before Serve can return
go c.serve(ctx)
}
}
To stop the above function, we could close the listener (e.g. via interrupt signal), which in turn would generate an error on Accept(). The above implementation checks whether serv.GetDoneChan() channel returns a value as an indicator that the error is expected and the server is closed.
This is what you want
Server
package main
import (
"bufio"
)
import "fmt"
import "log"
import "net"
import "strings" // only needed below for sample processing
func handleConnection(conn net.Conn) {
fmt.Println("Inside function")
// will listen for message to process ending in newline (\n)
message, _ := bufio.NewReader(conn).ReadString('\n')
// output message received
fmt.Print("Message Received:", string(message))
// sample process for string received
newmessage := strings.ToUpper(message)
// send new string back to client
conn.Write([]byte(newmessage + "\n"))
conn.Close()
}
func main() {
fmt.Println("Launching server...")
fmt.Println("Listen on port")
ln, err := net.Listen("tcp", "127.0.0.1:8081")
if err != nil {
log.Fatal(err)
}
fmt.Println("Accept connection on port")
for {
conn, err := ln.Accept()
if err != nil {
log.Fatal(err)
}
fmt.Println("Calling handleConnection")
go handleConnection(conn)
}
}
Client
package main
import (
"bufio"
"fmt"
"net"
)
func main() {
addr, _ := net.ResolveTCPAddr("tcp", ":8081")
conn, err := net.DialTCP("tcp", nil, addr)
if err != nil {
panic(err.Error())
}
fmt.Fprintf(conn, "From the client\n")
message, _ := bufio.NewReader(conn).ReadString('\n')
fmt.Print(message)
conn.Close()
}

Resources