BUG: GM_xmlhttpRequest Fails With Multiple Redirects
Hey guys! It seems like we've stumbled upon a rather annoying bug in ScriptCat's GM_xmlhttpRequest
. Specifically, it's failing to properly handle multiple redirects. Let's dive into the details, replicate the issue, and figure out what's going on.
问题描述 (Problem Description)
The main problem is that the return result is not correct when there are multiple redirects. The script doesn't seem to handle these scenarios correctly, leading to errors. Let's take a closer look at the error message and the code that triggers it.
// ==UserScript==
// @name New Userscript I1331-2
// @namespace https://docs.scriptcat.org/
// @version 0.1.0
// @description try to take over the world!
// @author You
// @match https://*/*
// @connect bing.com
// @grant GM_xmlhttpRequest
// ==/UserScript==
(function() {
'use strict';
GM_xmlhttpRequest({
url: "https://www.bing.com/ck/a?!&&p=e01cc35a29772d4132ec96cd3cd160ce4937e50acaf013cafec89b06614e21fbJmltdHM9MTc2MDU3MjgwMA&ptn=3&ver=2&hsh=4&fclid=36450f50-14ee-6c9f-155e-19d815e66d52&u=a1aHR0cHM6Ly96aHVhbmxhbi56aGlodS5jb20vcC80Mzk4NDI0NzIjOn46dGV4dD3lvZPkvaDlnKjkvaDnmoTnlJ_ml6XogZrkvJrkuIrmlLbliLDkuIDku73npLznianvvIzkvaDlj6_ku6XnlKjov5nlj6Xor53mnaXooajovr7mhJ_osKLjgILku6XkuIvlj6XlrZDkuZ_lj6_nlKjkuo7lkIzmoLflnLrlkIjvvJo&ntb=1",
method: "GET",
onload: response => console.log(response),
onerror: e => console.error(e),
})
})();
Explanation:
The provided JavaScript code is a UserScript designed to make an HTTP request to a specific URL on bing.com
. This URL appears to be a tracking link that redirects to another page. Here’s a breakdown of what each part does:
// ==UserScript==
to// ==/UserScript==
: This block is metadata that Greasemonkey, Tampermonkey, or other UserScript managers use to understand the script.@name
: The name of the script.@namespace
: A unique identifier for the script.@version
: The version number of the script.@description
: A brief description of what the script does.@author
: The author of the script.@match
: Specifies the URLs where the script should run (in this case, all HTTPS pages).@connect
: Specifies the domains that the script is allowed to connect to.@grant
: Specifies the special permissions that the script needs (in this case,GM_xmlhttpRequest
).
(function() { ... })();
: This is an Immediately Invoked Function Expression (IIFE), which ensures that the script runs in its own scope.'use strict';
: Enables strict mode in JavaScript, which helps catch common coding errors.GM_xmlhttpRequest({ ... });
: This is the core of the script. It uses theGM_xmlhttpRequest
function to make an HTTP request.url
: The URL to which the request is sent. This URL is a long tracking link onbing.com
that redirects to a Zhihu article.method
: The HTTP method used for the request (in this case,GET
).onload
: A callback function that is executed when the request is successfully completed. It logs the response to the console.onerror
: A callback function that is executed when an error occurs during the request. It logs the error to the console.
The Problem:
The issue is that GM_xmlhttpRequest
in ScriptCat doesn't seem to handle multiple redirects correctly. The provided URL likely goes through several redirects before reaching the final destination. This can cause the request to fail or return unexpected results.
重现步骤 (Reproduction Steps)
To reproduce the issue, simply run the code provided above and observe the error in the console. You should see that the request fails due to the multiple redirects. This behavior is similar to issues seen in earlier versions of VM (Violentmonkey).
- Install the Script: Add the above script to ScriptCat.
- Run the Script: Ensure the script is enabled.
- Check the Console: Open the browser's developer console and check for error messages related to the
GM_xmlhttpRequest
call.
Currently, TM (Tampermonkey) and VM (Violentmonkey) handle this type of request without issues, suggesting that the problem is specific to ScriptCat's implementation of GM_xmlhttpRequest
.
脚本猫版本 (ScriptCat Version)
The version of ScriptCat being used is 1.1.2.
操作系统以及浏览器信息 (Operating System and Browser Information)
- Operating System: WIN11
补充信息 (Additional Information)
No additional information was provided.
Possible Causes and Solutions
Root Cause Analysis
-
Incomplete Redirect Handling:
- The most likely cause is that
GM_xmlhttpRequest
in ScriptCat doesn't fully implement the handling of HTTP redirects. When a server responds with a redirect (e.g., a 301 or 302 status code), the browser or the request library needs to follow theLocation
header to the new URL. If this process isn't correctly implemented for multiple redirects, the request might fail.
- The most likely cause is that
-
Security Restrictions:
- Browsers and UserScript managers implement security restrictions to prevent malicious scripts from accessing unintended resources. It's possible that the redirect behavior is being blocked due to these security measures, especially if the redirects cross different domains or protocols.
-
CORS Issues:
- Cross-Origin Resource Sharing (CORS) can also play a role, although it's less likely in this scenario since the initial request is to
bing.com
, which is listed in the@connect
directive. However, if subsequent redirects lead to domains not included in@connect
, CORS issues might arise.
- Cross-Origin Resource Sharing (CORS) can also play a role, although it's less likely in this scenario since the initial request is to
-
Bug in the Underlying Request Library:
- It's also possible that there's a bug in the underlying library or browser API that ScriptCat uses to make HTTP requests. This could cause unexpected behavior when handling redirects.
Potential Solutions
-
Implement Full Redirect Handling:
- Ensure that
GM_xmlhttpRequest
correctly handles multiple HTTP redirects. This involves checking the response status code, looking for theLocation
header, and making a new request to the URL specified in theLocation
header. This process should be repeated until a non-redirect status code is received.
- Ensure that
-
Review Security Policies:
- Check if there are any security policies or restrictions that might be interfering with the redirect process. Ensure that the script has the necessary permissions to follow redirects, especially if they cross different domains.
-
Handle CORS Issues:
- If CORS issues are suspected, ensure that all domains involved in the redirect chain are included in the
@connect
directive. Alternatively, the server hosting the resources could be configured to send appropriate CORS headers.
- If CORS issues are suspected, ensure that all domains involved in the redirect chain are included in the
-
Update or Replace the Request Library:
- If the issue is suspected to be in the underlying request library, consider updating it to the latest version or replacing it with a different library that has better support for redirects.
-
Add Error Logging and Debugging:
- Add more detailed error logging and debugging to the
GM_xmlhttpRequest
function. This can help identify exactly where the redirect process is failing and provide more information for troubleshooting.
- Add more detailed error logging and debugging to the
Code Example for Handling Redirects
Here’s an example of how you might implement redirect handling in JavaScript:
function httpRequestWithRedirects(url, method, onload, onerror, maxRedirects = 10, redirectsFollowed = 0) {
GM_xmlhttpRequest({
url: url,
method: method,
onload: function(response) {
if (response.status >= 300 && response.status < 400 && response.responseHeaders.includes('Location')) {
if (redirectsFollowed >= maxRedirects) {
onerror({ message: 'Too many redirects' });
return;
}
const redirectUrl = response.responseHeaders.match(/Location: (.*?)\n/)[1].trim();
httpRequestWithRedirects(redirectUrl, method, onload, onerror, maxRedirects, redirectsFollowed + 1);
} else {
onload(response);
}
},
onerror: onerror
});
}
// Usage
httpRequestWithRedirects(
"https://www.bing.com/ck/a?!&&p=e01cc35a29772d4132ec96cd3cd160ce4937e50acaf013cafec89b06614e21fbJmltdHM9MTc2MDU3MjgwMA&ptn=3&ver=2&hsh=4&fclid=36450f50-14ee-6c9f-155e-19d815e66d52&u=a1aHR0cHM6Ly96aHVhbmxhbi56aGlodS5jb20vcC80Mzk4NDI0NzIjOn46dGV4dD3lvZPkvaDlnKjkvaDnmoTnlJ_ml6XogZrkvJrkuIrmlLbliLDkuIDku73npLznianvvIzkvaDlj6_ku6XnlKjov5nlj6Xor53mnaXooajovr7mhJ_osKLjgILku6XkuIvlj6XlrZDkuZ_lj6_nlKjkuo7lkIzmoLflnLrlkIjvvJo&ntb=1",
"GET",
response => console.log(response),
e => console.error(e)
);
This code snippet provides a basic implementation of handling redirects. It checks the response status code and, if it's a redirect, extracts the new URL from the Location
header and makes another request. It also includes a check to prevent too many redirects.
Conclusion
The GM_xmlhttpRequest
failing to handle multiple redirects is a significant issue that needs addressing in ScriptCat. By implementing proper redirect handling, reviewing security policies, and ensuring CORS compatibility, the functionality of ScriptCat can be improved, and users can rely on it for more complex web requests. Keep us updated on the progress, and let's squash this bug together! I hope this helps in identifying and resolving the issue, and I look forward to any updates or further insights you might have.