How to disable javascript in chromedp? - go

I want to disable javascript in https://github.com/chromedp/chromedp
any allocator flag can I put in the config? thank you!

There is a command line option: --blink-settings=scriptEnabled=false.
package main
import (
"context"
"log"
"os"
"github.com/chromedp/chromedp"
)
func main() {
opts := append(chromedp.DefaultExecAllocatorOptions[:],
chromedp.Flag("blink-settings", "scriptEnabled=false"),
)
ctx, cancel := chromedp.NewExecAllocator(context.Background(), opts...)
defer cancel()
ctx, cancel = chromedp.NewContext(ctx)
defer cancel()
var res []byte
err := chromedp.Run(ctx,
chromedp.Navigate(`https://twitter.com/`),
chromedp.FullScreenshot(&res, 100),
)
if err != nil {
log.Fatal(err)
}
os.WriteFile("screenshot.png", res, 0644)
}
FYI, the list of available blink-settings can be found here: https://source.chromium.org/chromium/chromium/src/+/09372ea8ec2ab6363ccad6a4847a1c9da560b29d:out/Debug/gen/third_party/blink/renderer/core/settings_macros.h;l=1535

Related

Different result when run io.Copy(os.Stdout, &r) consecutively in Golang

I am playing around Golang. About io.Copy
I put 2 consecutive io.Copy in the code, but i expect it output twice result(testtesttest). But the 2nd one is nil. Can anyone help explain why? tks
package main
import (
"io"
"os"
"strings"
"fmt"
)
type testReader struct {
w io.Reader
str string
}
func (tt *testReader) Read (b []byte) (n int, err error) {
io.Copy(os.Stdout, tt.w)
n, err = tt.w.Read(b)
if tt.w !=nil {
return 0,io.EOF
}
return
}
func main() {
s := strings.NewReader("testtesttest!!!")
r := testReader{s,"ttthhh"}
fmt.Println(&r)
io.Copy(os.Stdout, &r)
// s.Seek(0,0) // solution from Poy's answer
io.Copy(os.Stdout, &r)
}
I'm going to prune down the given example to (as there is a bit of noise):
package main
import (
"io"
"os"
"strings"
)
func main() {
s := strings.NewReader("testtesttest")
io.Copy(os.Stdout, s) // Will print "testtesttest"
io.Copy(os.Stdout, s) // Won't print anything
}
The reason the second copy won't output anything is the io.Reader (s) has already been read. Reading from a io.Reader is not idempotent (you can't call it twice to get the same results). It also doesn't have a way to "reset" it or anything.
As #JRLambert pointed out you have s.Seek() and s.Reset() to allow you to start reading again.
Quick addition to all the correct answers (#poy and #JRLambert) provided so far... Use io.TeeReader or io.MultiWriter for times when you would want to use io.Copy more than once. Below are some examples of using each.
Using io.TeeReader
package main
import (
"bytes"
"crypto/md5"
"encoding/hex"
"fmt"
"io"
"io/ioutil"
"os"
)
func main() {
sourceFile, _ := os.Open("source/ebook.pdf")
var buf bytes.Buffer
tee := io.TeeReader(sourceFile, &buf)
process := func(sourceReader io.Reader) {
targetFile, _ := os.Create("target/ebook.pdf")
defer targetFile.Close()
if _, err := io.Copy(targetFile, sourceReader); err != nil {
fmt.Println(err)
}
}
process(tee)
fmt.Println(checksum(&buf))
}
func checksum(buf *bytes.Buffer) string {
h := md5.New()
b, _ := ioutil.ReadAll(buf)
if _, err := h.Write(b); err != nil {
fmt.Println(err)
}
return hex.EncodeToString(h.Sum(nil)[:16])
}
Using io.MultiWriter
package main
import (
"bytes"
"crypto/md5"
"encoding/hex"
"fmt"
"io"
"io/ioutil"
"os"
)
func main() {
sourceFile, _ := os.Open("source/ebook.pdf")
process := func(sourceReader io.Reader) {
targetFile, _ := os.Create("target/ebook.pdf")
defer targetFile.Close()
var buf1, buf2 bytes.Buffer
w := io.MultiWriter(targetFile, &buf1, &buf2)
if _, err := io.Copy(w, sourceReader); err != nil {
fmt.Println(err)
}
fmt.Println(checksum(&buf1))
fmt.Println(checksum(&buf2))
}
process(sourceFile)
}
func checksum(buf *bytes.Buffer) string {
h := md5.New()
b, _ := ioutil.ReadAll(buf)
if _, err := h.Write(b); err != nil {
fmt.Println(err)
}
return hex.EncodeToString(h.Sum(nil)[:16])
}

How to connect xml decoder to stdoutPipe() of go exec

I'm having some trouble linking things up here.
What am I doing incorrectly?
package main
import (
"encoding/xml"
"fmt"
"log"
"os/exec"
)
func checkError(err error) {
if err != nil {
log.Fatalf("Error: %s", err)
}
}
func metrics() {
cmd := exec.Command(
"nvidia-smi",
"--query",
"--xml-format")
out, err := cmd.StdoutPipe()
checkError(err)
cmd.Start()
defer cmd.Wait()
go func() {
var data interface{}
dec := xml.NewDecoder(out)
dec.Decode(&data)
fmt.Printf("Data: %+v\n", data)
}()
//go io.Copy(os.Stdout, out)
}
func main() {
metrics()
}
Result after running program is:
Data:
Things seem to be "linked" correctly.
Problem is likely to be here:
var data interface{}
You then do:
dec.Decode(&data)
But that won't work.
You need to pass in a struct that can actually be used to decode the fields in the XML that the nvidia-smi command returns.
Find below a modified example (replacing your nvidia-smi for an echo command to make it return a sample XML).
You should adjust the struct to be able to map to the actual XML you'll receive.
By the way:
You should check the error returned by decode just in case
I don't understand why you are decoding in a separate goroutine. I left it like that in the modified example, but it would work if you do it right in the same goroutine as well.
Example:
package main
import (
"log"
"os/exec"
"fmt"
"encoding/xml"
)
func checkError(err error) {
if err != nil {
log.Fatalf("Error: %s", err)
}
}
type Result struct {
Value int `xml:"value"`
}
func metrics() {
cmd := exec.Command(
"echo", "-n",
`<result><value>1</value></result>`)
out, err := cmd.StdoutPipe()
checkError(err)
cmd.Start()
defer cmd.Wait()
go func() {
var data Result
dec := xml.NewDecoder(out)
err = dec.Decode(&data)
checkError(err)
fmt.Printf("Data: %+v\n", data)
}()
//go io.Copy(os.Stdout, out)
}
func main() {
metrics()
}

Writing buffer to file doesn't return error, so why is file empty afterwords?

I'm trying to read all standard input and write it to a file. It's writing nothing to the file provided. Why is it not working?
package main
import (
"os"
"bytes"
"fmt"
"bufio"
)
func main() {
fn := os.Args[1]
var input bytes.Buffer
scanner := bufio.NewScanner(os.Stdin)
for scanner.Scan() {
fmt.Fprintf(&input, scanner.Text())
fmt.Fprintf(&input, "\n")
}
fi, _ := os.Open(fn)
defer fi.Close()
fi.Write(input.Bytes())
}
And then...
touch writetothis.txt
echo "input text" | go run main.go writetothis.txt
# writetothis.txt is empty
Open opens a file in read-only mode.
Refer to documentation: https://golang.org/pkg/os/#Open
Instead, use OpenFile.
Also, always check for errors whenever you code. It'll save you at least weeks of work-hours in your lifetime.
Here is a working code:
package main
import (
"bufio"
"bytes"
"fmt"
"os"
)
func main() {
fn := os.Args[1]
var input bytes.Buffer
scanner := bufio.NewScanner(os.Stdin)
for scanner.Scan() {
fmt.Fprintf(&input, scanner.Text())
fmt.Fprintf(&input, "\n")
}
fmt.Println(input.Bytes())
fi, err := os.OpenFile(fn, os.O_RDWR|os.O_CREATE, 0755)
if err != nil {
fmt.Println("Error with Open()",err)
}
defer fi.Close()
n, err := fi.Write(input.Bytes())
if err != nil {
fmt.Println("Error with Write()", err)
}
fmt.Println("Bytes written to file: ",n)
}
In your code you can silently fail because you aren't checking the error. It's likely a path issue. You can change your code slightly and let ioutil handle file creation so that paths aren't so much of an issue. Remember to always check the errs
package main
import (
"bufio"
"bytes"
"fmt"
"io/ioutil"
"log"
"os"
)
func main() {
fn := os.Args[1]
var input bytes.Buffer
scanner := bufio.NewScanner(os.Stdin)
for scanner.Scan() {
fmt.Fprintf(&input, scanner.Text())
fmt.Fprintf(&input, "\n")
}
err := ioutil.WriteFile(fn, input.Bytes(), 0644)
if err != nil {
log.Fatal(err)
}
}

The best way to set the timeout on built-in HTTP request

What is the best way to setup a timeout on built-in http NewRequest? Currently, I'm using http.Client.Timeout which is cover the entire exchange, but is there something better for example context.WithDeadline or context.WithTimeout. If yes how is it working, how can I setup a context.WithDeadline solution for the http.NewRequest?
There is my current solution:
func (c *Client) post(resource string, data url.Values, timeout time.Duration) ([]byte, error) {
url := c.getURL(resource)
client := &http.Client{
Timeout: timeout * time.Millisecond,
}
req, err := http.NewRequest("POST", url, strings.NewReader(data.Encode()))
if err != nil {
return nil, err
}
req.Header.Add("Content-Type", "application/x-www-form-urlencoded")
resp, err := client.Do(req)
if err != nil {
return nil, err
}
return ioutil.ReadAll(resp.Body)
}
Get new context from context.WithDeadline. See documentation.
WithTimeout just returns WithDeadline(parent, time.Now().Add(timeout)).
package main
import (
"context"
"io"
"log"
"net/http"
"os"
"time"
)
func getContent(ctx context.Context) {
req, err := http.NewRequest("GET", "http://example.com", nil)
if err != nil {
log.Fatal(err)
}
ctx, cancel := context.WithDeadline(ctx, time.Now().Add(3 * time.Second))
defer cancel()
req.WithContext(ctx)
resp, err := http.DefaultClient.Do(req)
if err != nil {
log.Fatal(err)
}
defer resp.Body.Close()
io.Copy(os.Stdout, resp.Body)
}
func main() {
ctx := context.Background()
getContent(ctx)
}
If you want to make cancel trigger on main:
func main() {
ctx := context.Background()
ctx, cancel := context.WithCancel(ctx)
sc := make(chan os.Signal, 1)
signal.Notify(sc, os.Interrupt)
go func(){
<-sc
cancel()
}()
getContent(ctx)
}

How to dynamically set a variable in a defer call

Example code:
package main
import (
"errors"
"fmt"
)
func main() {
err := errors.New("error 1")
defer fmt.Println(err)
err = errors.New("error 2")
}
In this case, I want fmt.Println to print out error 2.
err is already defined when you set the defer so what you what you likely want to do is wrap it in a func like below. Hope this helps.
package main
import (
"errors"
"fmt"
)
func main() {
err := errors.New("error 1")
defer func() {
fmt.Println(err)
}()
err = errors.New("error 2")
}

Resources