go-rod / rod

A Chrome DevTools Protocol driver for web automation and scraping.
https://go-rod.github.io
MIT License
5k stars 328 forks source link

Add must method security protection #1026

Closed linux-go closed 3 months ago

linux-go commented 3 months ago

Development guide

Link

Test on local before making the PR

go run ./lib/utils/simple-check
linux-go commented 3 months ago
c.page.Timeout(time.Second)..WithPanic(c.ef)
            MustElement(`body > ytd-app`).
            MustElement(`#content`).
            MustElement(`#page-manager > ytd-search`).
            MustElement(`#container > ytd-two-column-search-results-renderer`).
            MustElement(`#primary > ytd-section-list-renderer`).
            MustElement(`#contents > ytd-item-section-renderer`).
            MustElements(`#contents > ytd-video-renderer:nth-child`)

In this way, you only need to judge once after calling the method, and there is no need to judge every time it is called.

ysmood commented 3 months ago

Sorry, I don't understand the intention of this, could you provide more detailed examples and benefits of it?

linux-go commented 3 months ago

Sorry, I don't understand the intention of this, could you provide more detailed examples and benefits of it?

This is a simple sample code

package main

import (
    "errors"
    "log"
    "time"

    "github.com/go-rod/rod"
    "github.com/go-rod/rod/lib/launcher"
)

func init() {
    log.SetFlags(log.LstdFlags | log.Lshortfile)
}

func main() {
    var err error
    var ef = func(v any) {
        e, ok := v.(error)
        if ok {
            err = e
            return
        }
        err = errors.New("unknown error")
    }
    var launch string
    launch, err = launcher.NewUserMode().Launch()
    if err != nil {
        log.Println(err)
        return
    }
    page := rod.New().ControlURL(launch).WithPanic(ef).Timeout(time.Second).
        MustConnect().MustPage("https://www.baidu.com/").MustWaitStable()
    defer page.MustClose()
    page.Timeout(time.Second).
        MustElementX(`//*[@id="wrapper"]`).
        MustElementX(`//*[@id="head"]`).
        MustElementX(`//*[@id="head_wrapper"]`).
        MustElementX(`//*[@id="kw"]`).
        MustClick().MustInput(`images`)
    if err != nil {
        log.Println(err)
        return
    }
    page.Timeout(time.Second).
        MustElementX(`//*[@id="form"]/span[2]`).
        MustClick()
    if err != nil {
        log.Println(err)
        return
    }
}

If I have an error when calling the MustelementX method, the receiver of the MustLick method is empty value and panic will happen directly. So errors occur.

ysmood commented 3 months ago

Could you show us the difference between using your way and not using your way? I still don't get what it improves.

Have you read this? https://github.com/go-rod/rod/issues/166