rod icon indicating copy to clipboard operation
rod copied to clipboard

navigation failed: net::ERR_INVALID_AUTH_CREDENTIALS

Open wAnFen1017 opened this issue 1 year ago • 11 comments
trafficstars

Rod Version: v0.114.5

我有一个隧道代理服务,支持http和https。他需要通过 http://user:pwd@ip:port 的形式通过验证,该服务测试过没有问题。

参照文档中 go browser.MustHandleAuth(user, pwd)() 成功设置了代理,并打开网站验证无误。但是同样的逻辑放在浏览器池browsePool中则报错,在创建browserPool之前设置browser.MustHandleAuth会报错 navigation failed: net::ERR_INVALID_AUTH_CREDENTIALS;创建后设置browser.MustHandleAuth则会报错 panic: {-32000 Invalid state for continueInterceptedRequest }。以下是我的代码

// Package main
// @Time      : 2023-12-06 09:47
// @Author    : wAnFen
// @File      : render.go
// @Go        : 1.21.3

package main

import (
	"github.com/go-rod/rod"
	"github.com/go-rod/rod/lib/launcher"
	"github.com/go-rod/rod/lib/proto"
	"log"
	"sync"
)

func RunRod(url string) {
	var rodUrl string
	l := launcher.New().
		Headless(false).
		Leakless(true).
		NoSandbox(true).
		Delete("enable-automation").
		Set("ignore-certificate-errors").
		Set("ignore-certificate-errors-spki-list").
		Set("ignore-ssl-errors").
		Set("disable-blink-features", "AutomationControlled").
		Set("disable-setuid-sandbox").
		Set("disable-gpu").
		Set("disable-dev-shm-usage").
		Set("unlimited-storage").
		Set("disable-accelerated-2d-canvas").
		Set("full-memory-crash-report")

	l = l.Proxy("127.0.0.1:6501")

	path, has := launcher.LookPath()
	if has == true {
		rodUrl = l.Bin(path).MustLaunch()
	} else {
		rodUrl = l.MustLaunch()
	}

	log.Println("StartURL : ", rodUrl)
	browser := rod.New().ControlURL(rodUrl).MustConnect()

	browser.MustIgnoreCertErrors(true)

	user := "user"
	pwd := "password"

	go browser.MustHandleAuth(user, pwd)()

	browsePool := rod.NewBrowserPool(20)
	create := func() *rod.Browser {
		//go browser.MustHandleAuth(user, pwd)()
		return browser.MustIncognito()
	}

	// 单一线程正常运行
	//b := browsePool.Get(create)
	//page, err := b.Page(proto.TargetCreateTarget{URL: url})
	//if err != nil {
	//	log.Println("browser.Page Err : ", err)
	//}
	//println(page.MustElement("html").MustText())

	// 在goroutine中运行报错 navigation failed: net::ERR_INVALID_AUTH_CREDENTIALS
	var wg sync.WaitGroup
	for i := 0; i <= 3; i++ {
		wg.Add(1)
		go func() {
			defer wg.Done()
			b := browsePool.Get(create)
			page, err := b.Page(proto.TargetCreateTarget{URL: url})
			if err != nil {
				log.Println("browser.Page Err : ", err)
			}
			println(page.MustElement("html").MustText())
		}()
	}
	wg.Wait()
}

func main() {
	RunRod("http://api.ipify.org")
}

wAnFen1017 avatar Dec 27 '23 06:12 wAnFen1017

Please fix the format of your markdown:

7 MD040/fenced-code-language Fenced code blocks should have a language specified [Context: "```"]

generated by check-issue

github-actions[bot] avatar Dec 27 '23 06:12 github-actions[bot]

用法的问题,create 里处理 auth

ysmood avatar Dec 27 '23 07:12 ysmood

用法的问题,create 里处理 auth

如果改成在create中处理时则会报 panic: {-32000 Invalid state for continueInterceptedRequest }

create := func() *rod.Browser {
		go browser.MustHandleAuth(user, pwd)()
		return browser.MustIncognito()
	}

wAnFen1017 avatar Dec 27 '23 08:12 wAnFen1017

如果在外围处理,需要处理每个 auth 事件,browser.MustHandleAuth 只处理碰到的第一个,你看看它的源代码就懂了

ysmood avatar Dec 27 '23 08:12 ysmood

如果在外围处理,需要处理每个 auth 事件,browser.MustHandleAuth 只处理碰到的第一个,你看看它的源代码就懂了

我在每个goroutine中做处理不可实现吗,或者如果在外围统一处理的话,我查到是使用EachEvent去控制全部活动,我改成这样,依旧报错 panic: {-32000 Invalid state for continueInterceptedRequest }

	go browser.EachEvent(func(e *proto.FetchAuthRequired) {
		fakeAuth := &proto.FetchAuthChallengeResponse{
			Response: proto.FetchAuthChallengeResponseResponseProvideCredentials,
			Username: user,
			Password: pwd,
		}
		err := proto.FetchContinueWithAuth{
			RequestID:             e.RequestID,
			AuthChallengeResponse: fakeAuth,
		}.Call(browser)
		if err!=nil{
			panic(err)
		}
	}, func(e *proto.FetchRequestPaused) {
		err := proto.FetchContinueRequest{
			RequestID: e.RequestID,
		}.Call(browser)
		if err!=nil{
			panic(err)
		}
	})()

	browsePool := rod.NewBrowserPool(20)
	create := func() *rod.Browser {
		return browser.MustIncognito()
	}
        // browser.MustPage()

wAnFen1017 avatar Dec 27 '23 08:12 wAnFen1017

那你可能需要自己 debug 一下,应该是用法的问题,这方面 chromium cdp 缺少文档说明,只能猜测用法,让我来和让你来是一样的。

你这里报错的意思是 FetchContinueRequest 用法错误

ysmood avatar Dec 27 '23 08:12 ysmood

我看了您另外的一个回答 https://github.com/go-rod/rod/issues/654 ,我感觉我和他的问题应该是差不多的,但是我这里使用了BrowserPool,所以我猜测是不是BrowserPool的问题,以下是我的完整代码,此时报错信息是 navigation failed: net::ERR_INVALID_AUTH_CREDENTIALS

// Package main
// @Time      : 2023-12-06 09:47
// @Author    : wAnFen
// @File      : render.go
// @Go        : 1.21.3

package main

import (
	"github.com/go-rod/rod"
	"github.com/go-rod/rod/lib/launcher"
	"github.com/go-rod/rod/lib/proto"
	"log"
	"sync"
)

func RunRod(url string) {
	var rodUrl string
	l := launcher.New().
		Headless(false).
		Leakless(true).
		NoSandbox(true).
		Delete("enable-automation").
		Set("ignore-certificate-errors").
		Set("ignore-certificate-errors-spki-list").
		Set("ignore-ssl-errors").
		Set("disable-blink-features", "AutomationControlled").
		Set("disable-setuid-sandbox").
		Set("disable-gpu").
		Set("disable-dev-shm-usage").
		Set("unlimited-storage").
		Set("disable-accelerated-2d-canvas").
		Set("full-memory-crash-report")

	l = l.Proxy("http://127.0.0.1:6501")

	path, has := launcher.LookPath()
	if has == true {
		rodUrl = l.Bin(path).MustLaunch()
	} else {
		rodUrl = l.MustLaunch()
	}

	log.Println("StartURL : ", rodUrl)
	browser := rod.New().ControlURL(rodUrl).MustConnect()

	browser.MustIgnoreCertErrors(true)

	user := "user"
	pwd := "pwd"

	go browser.EachEvent(func(e *proto.FetchAuthRequired) {
		fakeAuth := &proto.FetchAuthChallengeResponse{
			Response: proto.FetchAuthChallengeResponseResponseProvideCredentials,
			Username: user,
			Password: pwd,
		}
		err := proto.FetchContinueWithAuth{
			RequestID:             e.RequestID,
			AuthChallengeResponse: fakeAuth,
		}.Call(browser)
		if err != nil {
			panic(err)
		}
	}, func(e *proto.FetchRequestPaused) {
		err := proto.FetchContinueRequest{
			RequestID: e.RequestID,
		}.Call(browser)
		if err != nil {
			panic(err)
		}
	})()

	browsePool := rod.NewBrowserPool(20)
	create := func() *rod.Browser {
		return browser.MustIncognito()
	}

	var wg sync.WaitGroup
	for i := 0; i <= 3; i++ {
		wg.Add(1)
		go func() {
			defer wg.Done()
			b := browsePool.Get(create)
			page, err := b.Page(proto.TargetCreateTarget{URL: url})
			if err != nil {
				log.Println("browser.Page Err : ", err)
			}
			println(page.MustElement("html").MustText())
		}()
	}
	wg.Wait()
}

func main() {
	RunRod("http://api.ipify.org")
}

wAnFen1017 avatar Dec 27 '23 09:12 wAnFen1017

I'm encountering this issue as well. Not sure what I'm doing wrong here.

I have a proxy that doesn't return HTTP/1.1 407 Proxy Authentication Required and still passes through. However, my proxy provider allows sticky-sessions when a username:pass is sent.

What would be the correct pattern? I know it's not proto.FetchAuthRequired, but I am struggling to find such a use-case in the docs. I tried using HijackRouter and setting the Proxy-Authorization header for the request, but that forwards the header to the fetched URL rather than for the proxy connection.

This code does not work:

	go browser.EachEvent(func(e *proto.FetchAuthRequired) {
		fakeAuth := &proto.FetchAuthChallengeResponse{
			Response: proto.FetchAuthChallengeResponseResponseProvideCredentials,
			Username: "user",
			Password: "pass",
		}
		err := proto.FetchContinueWithAuth{
			RequestID:             e.RequestID,
			AuthChallengeResponse: fakeAuth,
		}.Call(browser)
		if err != nil {
			panic(err)
		}
	}, func(e *proto.FetchRequestPaused) {
		err := proto.FetchContinueRequest{
			RequestID: e.RequestID,
		}.Call(browser)
		if err != nil {
			panic(err)
		}
	})()

lc avatar Feb 20 '24 15:02 lc

following code is worked

  1. create page
  2. auth handle
browser.Page(proto.TargetCreateTarget{})
go browser.MustHandleAuth(username, password)()

xujinzheng avatar Mar 12 '24 09:03 xujinzheng

Switched my proxy provider and it worked.

lc avatar Mar 18 '24 01:03 lc

following code is worked

  1. create page
  2. auth handle
browser.Page(proto.TargetCreateTarget{})
go browser.MustHandleAuth(username, password)()

Thank you for your answer. This is indeed effective under normal requests, but it does not work in browser pools

wAnFen1017 avatar Mar 18 '24 01:03 wAnFen1017