Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Read body from NetworkResponseReceived event #864

Closed
FrenchGithubUser opened this issue Apr 19, 2023 · 18 comments
Closed

Read body from NetworkResponseReceived event #864

FrenchGithubUser opened this issue Apr 19, 2023 · 18 comments
Labels
question Questions related to rod

Comments

@FrenchGithubUser
Copy link

Rod Version: v0.112.8

The code to demonstrate your question

	go page.EachEvent(func(e *proto.PageLoadEventFired) {
                //some stuff
		wg.Done()
	}, func(e *proto.NetworkResponseReceived) {
		if e.Response.URL == "https://thotsbay.ac/search/search" {
                        // how can I get the response body here ?
			fmt.Println(e.Response)
		}
	})()

What you got

The NetworkResponseReceived object, but I'm looking for the body of the response (which in this case is some json)

What have you tried to solve the question

Searching in the doc, the internet, ask chatGPT

@FrenchGithubUser FrenchGithubUser added the question Questions related to rod label Apr 19, 2023
@github-actions
Copy link

Please fix the format of your markdown:

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

generated by check-issue

@ysmood
Copy link
Collaborator

ysmood commented Apr 19, 2023

g.Eq("{\"text\":\"test\"}", ctx.Response.Body())

@FrenchGithubUser
Copy link
Author

FrenchGithubUser commented Apr 19, 2023

Thanks for your answer ! However, I felt like it would make sense to have access to the response body from the NetworkResponseReceived object...

@ysmood
Copy link
Collaborator

ysmood commented Apr 19, 2023

Then I think it's not related to Rod, you can ask the chromium team to support it: https://developer.chrome.com/docs/devtools/

@FrenchGithubUser
Copy link
Author

right, thanks for the details !

@TangMonk
Copy link

TangMonk commented Aug 19, 2023

ctx.Res

	go page.EachEvent(func(e *proto.NetworkResponseReceived) {
		fmt.Println("got event:", e.Type)
		if e.Response.URL == "https://www.dextools.io/shared/analytics/tokens/social-network-updates?chain=ether" {
			body := e.Response.Body
		}
	})()

e.Response.Body not works

image

@ischeck
Copy link

ischeck commented Aug 20, 2023

maybe you need this
#764

image

@lukeed
Copy link

lukeed commented Nov 5, 2023

Sorry to resurrect, but I'm trying to get the response body from a Service Worker that intercepted the request. I'm using NetworkGetResponseBody and see the e.Response fine, but @ysmood's reply is for the Hijacking Router, which I'm not using.

I had to use @ischeck's approach, which results in this error:

e.requestID 70503.6
ERROR:  {-32000 No resource with given identifier found }

Any ideas?

@ysmood
Copy link
Collaborator

ysmood commented Nov 6, 2023

@lukeed You can use -rod=cdp flag to print out all the events, and check if the id exists.

go run main.go -rod=cdp

@lukeed
Copy link

lukeed commented Nov 6, 2023

@ysmood Thanks for the info. The RequestID does, in fact, exist:

fetch := fmt.Sprintf(`function() { return fetch(%q, %s) }`, r.URL, string(bytes))
fmt.Printf("\nFETCH:\n%s\n\n", fetch)

e := proto.NetworkResponseReceived{}
wait := page.WaitEvent(&e)

if _, err := page.Eval(fetch); err != nil {
	fmt.Printf("\nEVAL ERROR:\n%v\n\n", err)
}

fmt.Println("\nWAITING...")
wait()
fmt.Println("\nWAITED!")

fmt.Println("e.res.url", e.Response.URL)
fmt.Println("e.requestID", e.RequestID)

reply, err := (proto.NetworkGetResponseBody{RequestID: e.RequestID}).Call(page)
if err != nil {
	fmt.Println("ERROR: ", err)
	return
}
[cdp] 2023/11/06 10:48:02 <- @0DBD4410 Network.responseReceived {"requestId":"76033.4","loaderId":"A2626D7C9FAC9F4F0953DF267774849D","timestamp":2222573.643943,"type":"Fetch","response":{"url":"http://localhost:53509/hello","status":200,"statusText":"","headers":{"content-type":"text/plain;charset=UTF-8"},"mimeType":"text/plain","connectionReused":false,"connectionId":0,"fromDiskCache":false,"fromServiceWorker":true,"fromPrefetchCache":false,"encodedDataLength":-1,"timing":{"requestTime":2222573.642628,"proxyStart":-1,"proxyEnd":-1,"dnsStart":-1,"dnsEnd":-1,"connectStart":-1,"connectEnd":-1,"sslStart":-1,"sslEnd":-1,"workerStart":0.003,"workerReady":0.186,"workerFetchStart":0.186,"workerRespondWithSettled":1.037,"sendStart":0.004,"sendEnd":0.004,"pushStart":0,"pushEnd":0,"receiveHeadersStart":1.161,"receiveHeadersEnd":1.161},"serviceWorkerResponseSource":"fallback-code","responseTime":1.699296482932593e+12,"protocol":"http/1.1","alternateProtocolUsage":"alternativeJobWonWithoutRace","securityState":"secure"},"hasExtraInfo":false,"frameId":"AE231E4C2DFF511F5F1F0FA6D9161B94"}
[cdp] 2023/11/06 10:48:02 <= #20 {"result":{"type":"object","value":{}}}
[cdp] 2023/11/06 10:48:02 <- @0DBD4410 Network.dataReceived {"requestId":"76033.4","timestamp":2222573.644177,"dataLength":15,"encodedDataLength":0}

WAITING...
[cdp] 2023/11/06 10:48:02 => #21 @0DBD4410 Network.disable null
[cdp] 2023/11/06 10:48:02 <= #21 {}

WAITED!
e.res.url http://localhost:53509/hello
e.requestID 76033.4
[cdp] 2023/11/06 10:48:02 => #22 @0DBD4410 Network.getResponseBody {"requestId":"76033.4"}
[cdp] 2023/11/06 10:48:02 <= #22 error: {"code":-32000,"message":"No resource with given identifier found","data":""}
ERROR:  {-32000 No resource with given identifier found }

@ysmood
Copy link
Collaborator

ysmood commented Nov 8, 2023

@lukeed I think you need to find out the correct page for the service worker, a service worker usually uses a different background page.

@lukeed
Copy link

lukeed commented Nov 8, 2023

I was on the correct page. What I needed was to wait for the NetworkLoadingFinished event & then ask for the Network.getResponseBody in that callback. Not sure if thats expected behavior or not, but thats what I saw during the -rod=cdp debugging.

Similarly I only randomly see NetworkDataReceived event, which (to me) means that I can't reliably forward streamed responses from the SW to my server, and instead I need to wait for NetworkLoadingFinished and send the response body in 1 w.Write call

@ysmood
Copy link
Collaborator

ysmood commented Nov 10, 2023

We'd better raise another issue for service worker, I confirmed that it's not easy to get the request events from it.

@duolabmeng6
Copy link

How to get the body

@duolabmeng6
Copy link

您需要为 Service Worker 找出正确的内容,Service Worker

maybe you need this #764

image

Your code will not run in the latest version without Body

@duolabmeng6
Copy link

duolabmeng6 commented Dec 1, 2023

I hope it helps others

package main

import (
	"fmt"
	"github.com/go-rod/rod"
	"github.com/go-rod/rod/lib/launcher"
	"github.com/go-rod/rod/lib/proto"
	"time"
)

func main() {
	url := launcher.New().Headless(false).MustLaunch()
	browser := rod.New().ControlURL(url).MustConnect()
	page := browser.MustPage("")

	go func() {
		page.EachEvent(func(e *proto.NetworkRequestWillBeSent) {
			fmt.Printf("Request: %s %s\n", e.Request.Method, e.Request.URL)
		}, func(e *proto.NetworkResponseReceived) {
			reply, err := (proto.NetworkGetResponseBody{RequestID: e.RequestID}).Call(page)
			if err != nil {
				fmt.Println(err)
			}
			fmt.Println(reply.Body)
		})()
	}()
	time.Sleep(3 * time.Second)
	page.MustNavigate("https://www.baidu.com")
	select {}
}

@KingWu
Copy link

KingWu commented Feb 22, 2024

@duolabmeng6 i still face the issue by using your sample code
ERROR: {-32000 No resource with given identifier found }

any idea?

@KingWu
Copy link

KingWu commented Feb 22, 2024

Googling how ppl to solve the issue

https://www.appsloveworld.com/google-chrome-extension/4/chrome-extension-quotno-resource-with-given-identifier-foundquot-when-trying

Refactor to use the event NetworkLoadingFinished. To be more stable

var targetUrl = "xxxx"
page.EachEvent(func(e *proto.NetworkRequestWillBeSent) {
			fmt.Printf("Request: %s %s\n", e.Request.Method, e.Request.URL)
			if strings.Contains(e.Request.URL, targetUrl) {
				requestId = e.RequestID
			}
		}, func(e *proto.NetworkLoadingFinished) {
			if e.RequestID == requestId {
				fmt.Println("NetworkLoadingFinished")
				reply, err := (proto.NetworkGetResponseBody{RequestID: requestId}).Call(page)
				if err != nil {
					fmt.Println(err)
				}
				fmt.Println(reply.Body)
			}
		})()

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
question Questions related to rod
Projects
None yet
Development

No branches or pull requests

7 participants