I'm developing a Chrome extension that sends a POST request from the content script to the background script using chrome.runtime.sendMessage
. The background script processes the request and sends the response back to the content script using sendResponse. However, I'm getting a "The message port closed before a response was received" error.
Here's the code for the chrome.runtime.onMessage event listener in my background script:
chrome.runtime.onMessage.addListener(async (message, sender, sendResponse) => {
let res = await fetch(message.endpoint, {
'method': 'POST',
'headers': message.headers,
'body': message.body
})
let json = await res.json();
console.log('json data:' + json);
sendResponse({
'status': true,
'url': json.url
});
});
And here's the code for sending the message from the content script:
chrome.runtime.sendMessage({
endpoint: 'https://example.com/api',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({ key: 'value' })
}, (response) => {
console.log(response);
});
I've tried adding return true at the end of the chrome.runtime.onMessage event listener, as suggested in other answers, but it doesn't solve the problem.
How can I fix this issue? Thanks in advance.
This is my solution
I was able to solve the issue with the following code:
Content script:
// 1. Send data to backend.
chrome.runtime.sendMessage({
endpoint: 'https://example.com/api',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({ key: 'value' })
}, (response) => {
console.log(response);
});
// 4. listen chrome.tabs.sendMessage from backend.
chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
if (request.message === "audio_url") {
console.log('audio_url:' + request.audio_url);
sendResponse({
'status': true,
});
}
});
Background script:
// 2. Listen chrome.runtime.sendMessage from content script.
chrome.runtime.onMessage.addListener(async (message, sender, sendResponse) => {
sendResponse({ 'status': true });
let res = await fetch(message.endpoint, {
'method': 'POST',
'headers': message.headers,
'body': message.body
});
let json = await res.json();
console.log('json data:' + json);
console.log('url:' + json.url);
if (sender.tab === undefined || sender.tab.id === undefined) return;
// 3. Send post result to content script by chrome.tabs.sendMessage
chrome.tabs.sendMessage(sender.tab.id, { message: "audio_url", audio_url: json.url }, function (response) {
console.log(`status:`, response.status);
});
return true;
});
The issue was that I was trying to use sendResponse
in the background script to send a response back to the content script, but this was causing the The message port closed before a response was received
error.
runtime.sendMessage() cannot send messages to content scripts
To solve this, I switched to using chrome.tabs.sendMessage
to send the response back to the content script, and added a message listener in the content script to handle the response.
This way, the response is sent directly from the background script to the content script without going through the message port, avoiding the error.