当提交GET表单时,查询字符串将从操作URL中删除

考虑这个形式:

<form action="http://www.blabla.com?a=1&b=2" method="GET">
<input type="hidden" name="c" value="3" />
</form>
当提交这个GET表单时,参数ab将消失。< br / > 这有什么原因吗?< br / > 有没有办法避免这种行为?< / p >
423685 次浏览

这不是隐藏参数开始的目的吗?

<form action="http://www.example.com" method="GET">
<input type="hidden" name="a" value="1" />
<input type="hidden" name="b" value="2" />
<input type="hidden" name="c" value="3" />
<input type="submit" />
</form>

我不会指望任何浏览器在操作URL中保留任何现有的查询字符串。

作为规范(RFC1866,第46页;HTML 4. x节17.13.3)说明:

如果方法是"get"action是一个HTTP URI,用户代理获取action的值,追加一个' ?,然后追加表单数据集,使用“application/x-www-form-urlencoded"内容类型。

也许可以对action-URL进行百分比编码,以嵌入问号和参数,然后祈祷所有浏览器都能保留该URL(并验证服务器也能理解它)。但我绝不会依赖于此。

顺便说一下:对于非隐藏表单字段也没有什么不同。对于POST,操作URL可以包含一个查询字符串。

您应该包括两个项目(a和b)作为隐藏的输入元素以及C。

我有一个非常相似的问题,在form action中,我有这样的东西:

<form action="http://www.example.com/?q=content/something" method="GET">
<input type="submit" value="Go away..." />&nbsp;
</form>

该按钮将用户带到站点,但查询信息消失了,因此用户登录到主页而不是所需的内容页面。在我的案例中,解决方案是找出如何在不需要查询的情况下对URL进行编码,从而使用户能够访问所需的页面。在这种情况下,我的目标是Drupal网站,所以它证明/content/something也工作。我也可以使用节点号(即/node/123)。

你的建筑是违法的。不能在表单的操作值中包含参数。如果您尝试这样做,结果将取决于浏览器的特性。如果它只适用于一种浏览器而不适用于另一种浏览器,我不会感到惊讶。即使它看起来可以工作,我也不会依赖它,因为浏览器的下一个版本可能会改变这种行为。

“但是假设我在查询字符串和隐藏输入中有参数,我能做什么?”你能做的就是修复错误。不是讽刺,但这有点像问,“但是假设我的URL使用百分号而不是斜杠,我能做什么?”唯一可能的答案是,您可以修复URL。

您可以对包含GET信息的表使用简单的foreach。例如在PHP中:

foreach ($_GET as $key => $value) {
$key = htmlspecialchars($key);
$value = htmlspecialchars($value);
echo "<input type='hidden' name='$key' value='$value'/>";
}

由于GET值来自用户,我们应该在打印到屏幕之前转义它们。

在HTML5中,这是按规范的行为。

看到控件和表单的关联。表单提交算法

请看“4.10.22.3表单提交算法”,第17步。对于带有查询字符串的http/s URI的GET表单:

让destination是一个新的URL,它等于action 它的<query>组件被query替换(添加一个U+003F QUESTION 标记字符(?)(如果合适的话)

因此,您的浏览器将丢弃URI中现有的"?..."部分,并根据您的表单将其替换为新的部分。

在HTML 4.01中,规范产生了无效的uri -大多数浏览器实际上并没有这样做…

参见表单——处理表单数据,第四步——URI将追加?,即使它已经包含了?

如果你需要变通,因为这个表单可以放在第三方系统中,你可以像这样使用Apache mod_rewrite:

RewriteRule ^dummy.link$ index.php?a=1&b=2 [QSA,L]

然后你的新表单将是这样的:

<form ... action="http:/www.blabla.com/dummy.link" method="GET">
<input type="hidden" name="c" value="3" />
</form>

Apache将附加第3个参数到查询

<form ... action="http:/www.blabla.com?a=1&b=2" method ="POST">
<input type="hidden" name="c" value="3" />
</form>

将请求方法改为' POST'而不是'GET'。

我通常是这样写的:

foreach($_GET as $key=>$content){
echo "<input type='hidden' name='$key' value='$content'/>";
}

这是有效的,但是不要忘记清除您的输入以防止XSS攻击!

这是对Efx上述帖子的回应:

如果URL已经包含了您想要更改的变量,那么它将再次作为隐藏字段添加。

下面是对该代码的修改,以防止重复URL中的变量:

foreach ($_GET as $key => $value) {
if ($key != "my_key") {
echo("<input type='hidden' name='$key' value='$value'/>");
}
}

当原始查询有数组时,对于php:

foreach (explode("\n", http_build_query($query, '', "\n")) as $keyValue) {
[$key, $value] = explode('=', $keyValue, 2);
$key = htmlspecialchars(urldecode($key), ENT_COMPAT | ENT_HTML5);
$value = htmlspecialchars(urldecode($value), ENT_COMPAT | ENT_HTML5);
echo '<input type="hidden" name="' . $key . '" value="' . $value . '"' . "/>\n";
}

来回答你的第一个问题是的,浏览器可以,原因是 , 浏览器并不关心action URL中的现有参数 所以它完全删除它们

为了防止这种情况发生使用我写的JavaScript函数 使用jQuery在

function addQueryStringAsHidden(form){
if (form.attr("action") === undefined){
throw "form does not have action attribute"
}


let url = form.attr("action");
if (url.includes("?") === false) return false;
    

let index = url.indexOf("?");
let action = url.slice(0, index)
let params = url.slice(index);
url = new URLSearchParams(params);
for (param of url.keys()){
let paramValue = url.get(param);
let attrObject = {"type":"hidden", "name":param, "value":paramValue};
let hidden = $("<input>").attr(attrObject);
form.append(hidden);
}
form.attr("action", action)
}

我的观察

  • 当方法是GET并且提交表单时,隐藏的输入元素被作为查询参数发送。旧参数在行动url被清除。基本上在这个例子中,表单数据取代了action url中的查询字符串

  • 当方法是POST,并且提交表单时,action url中的查询参数是完整的(req.query)并且输入元素数据作为表单数据发送(req.body)

长话短说,如果你想传递查询参数和表单数据,使用方法属性作为"POST"