node.js 与 express 如何从 url 中删除查询字符串
Posted
技术标签:
【中文标题】node.js 与 express 如何从 url 中删除查询字符串【英文标题】:node.js with express how to remove the query string from the url 【发布时间】:2012-12-19 11:13:08 【问题描述】:我有一个按钮,它正在执行获取我的页面并向查询字符串添加过滤器。我的代码将该过滤器应用于网格,但用户可以删除/编辑该过滤器。由于他们可以看到网格中应用了哪些过滤器,因此我想在显示页面时从查询字符串中删除 ?filter=blah
。
如果页面上的 URL 显示 ?filter=columnA
最初是正确的,这可能会令人困惑,但用户删除了该过滤器并在 columnB
上应用了一个新过滤器,但查询字符串仍然显示 ?filter-columnA
。网格可以处理更改过滤器而无需回发。
我该怎么做?如果您无法删除/更新查询字符串,是否可以解析它,然后在没有查询字符串的情况下重定向到主页?将过滤器保存到 var 过滤器后,查询字符串中将不再需要它。
这是显示页面的代码:
exports.show = function(req, res)
var filter = req.query.filter;
if (filter === null || filter === "")
filter = "n/a";
res.render("somepage.jade",
locals:
title: "somepage",
filter: filter
);
;
【问题讨论】:
【参考方案1】:使用url.parse()
获取地址的组成部分,即req.url
。没有查询字符串的 url 存储在 pathname
属性中。
使用express'redirect
发送新的页面地址。
const url = require('url'); // built-in utility
res.redirect(url.parse(req.url).pathname);
Node 文档url
。
【讨论】:
使用 req.originalUrl 而不是 req.url 在嵌套路由器内部工作 更现代的方法是使用new URL(req.originalUrl).pathname
而不是url.parse(req.url).pathname
。这样可以避免加载 url 模块(const url = require('url');
行)。
@JakubKukul 这对于 Node 来说是不正确的:你仍然应该在 Node 中需要 url
模块。【参考方案2】:
不要使用模块来做类似的事情:
res.redirect( req.originalUrl.split("?").shift() );
【讨论】:
“不要使用模块来做类似的事情。”为什么?url.parse
是自 0.1.25
以来的核心模块,非常适合这个任务。
@MarttiLaine 导致原生 javascript 可以在最终给定字符后删除字符串。 (认为它可能对复杂的 url 或 hashHistory 有一些警告)【参考方案3】:
Express 4.x+ 答案:res.redirect(req.path)
【讨论】:
res.redirect(req.baseUrl)
req.baseUrl 未定义,req.path 按预期工作。
在某些情况下(例如在中间件中),您实际上可能需要组合 req.baseUrl
和 req.path
。有关详细信息,请参阅我的答案。【参考方案4】:
// load built-in utilities for URL resolution and parsing
var url = require('url');
function removeQueryString(url)
// split url into distinct parts
// (full list: https://nodejs.org/api/url.html#url_url_parse_urlstr_parsequerystring_slashesdenotehost)
var obj = url.parse(url);
// remove the querystring
obj.search = obj.query = "";
// reassemble the url
return url.format(obj);
【讨论】:
【参考方案5】:使用req.path
如果您的端点是http://<your-domain>.com/hello/there?name=john
...
然后req.path
= /hello/there
文档:https://expressjs.com/en/api.html#req.path
【讨论】:
【参考方案6】:在您的情况下,完整的 url 存储在 req.url
中,使用 node.js 的 url.parse() 提取部分。获取路径并使用 res.set()
发送 Location 标头以重定向到没有查询字符串的 URL。
var url = require('url');
res.set('Location', url.parse(req.url).pathname);
【讨论】:
我试过了......它仍然有查询字符串......也许我没有调用正确的方法来“重定向”它。我的代码如下:exports.show = function(req, res) var filter = req.query.filter; if (filter === null || filter === "") filter = "n/a"; res.set('位置',url.parse(req.url).pathname); res.render('somepage.jade', locals: title: 'somepage', filter: filter ); ;【参考方案7】:为了避免通过强制重定向重新加载页面,我将以下内容添加到我的 .ejs 文件的 <head>
部分:
<script type="text/javascript">
var uri = window.location.toString();
if (uri.indexOf("?") > 0)
var clean_uri = uri.substring(0, uri.indexOf("?"));
window.history.replaceState(, document.title, clean_uri);
</script>
来源:http://atodorov.org/blog/2013/01/28/remove-query-string-with-javascript-and-html5/
【讨论】:
您是否尝试重新加载?如果没有,则重新加载不起作用,因为现在没有查询参数来获取数据。【参考方案8】:通用 Node.js 解决方案
> new URL('https://example.com/admin/new?foo=bar').pathname;
'/admin/new'
如果你还想包含原点:
> const url = require('url');
> url.format(new URL('https://example.com/admin/new?foo=bar'), search: false);
'https://example.com/admin/new'
Express.js 解决方案
其他答案包括使用req.url
/req.originalUrl
/req.path
/req.baseUrl
的各种组合。使用哪一个取决于上下文。如果您在 app.METHOD
函数中或者从中间件或嵌套路由器内部访问它们,这些属性的行为会有所不同。
总结:
使用req.originalUrl
应该是最通用的,但您需要自己解析路径名(见上文)。
使用req.path
是最直接的,但您必须确保您不在中间件/嵌套路由器中。
当您在 app.METHOD
函数中时:
// GET 'http://example.com/admin/new?foo=bar'
app.get('/admin/new', (req, res) =>
console.dir(req.originalUrl); // '/admin/new?foo=bar'
console.dir(req.url); // '/admin/new?foo=bar
console.dir(req.baseUrl); // ''
console.dir(req.path); // '/admin/new'
return res.status(200).send('All engines running!');
);
当您在中间件(或嵌套路由器)中时:
// GET 'http://example.com/admin/new?foo=bar'
app.use('/admin', (req, res, next) =>
console.dir(req.originalUrl); // '/admin/new?foo=bar'
console.dir(req.url); // '/new?foo=bar'
console.dir(req.baseUrl); // '/admin'
console.dir(req.path); // '/new'
next();
);
【讨论】:
【参考方案9】:使用此方法从 URL 中删除特定的查询参数。
/**
* remove query parameters from actual url
* @param * params paramerters to be remove, e.g ['foo', 'bar']
* @param * url actual url
*/
function removeQueryParam(parameters = [], url)
try
var urlParts = url.split('?');
var params = new URLSearchParams(urlParts[1]);
parameters.forEach(param =>
params.delete(param);
)
return urlParts[0] + '?' + params.toString();
catch (err)
console.log(err);
return url;
console.log(removeQueryParam(["foo"], "/foo?foo=foo&bar=bar"));
以上示例将返回 /foo?bar=bar
【讨论】:
【参考方案10】:我遇到了类似的问题,我的解决方法是在 部分添加一个脚本。但是,为了避免在我向后或向前移动时出现不一致,我需要添加一个 onbeforeunload 事件监听器。这种方法的好处是它避免了重定向。
// 将原始 url 存储在本地存储中 window.localStorage.setItem('specifiedKey', window.location.href); // 清除字符串的查询参数并在历史 API 中替换它 const cleanUrl = location.href.match(/^.+(?=\?)/g); window.history.replaceState(null, null, (cleanUrl ? cleanUrl[0] : location.href)); // 在窗口重新加载之前更新历史记录 window.onbeforeunload = () => window.history.replaceState(null, null, window.localStorage.getItem('specifiedKey'));我认为唯一的问题是浏览器不兼容,JavaScript 引擎无法支持正则表达式后视运算符。使用 .split('?')[0]
可以轻松解决此问题【讨论】:
以上是关于node.js 与 express 如何从 url 中删除查询字符串的主要内容,如果未能解决你的问题,请参考以下文章
如何在Node.js / Express中进行重定向(301)?
请求新页面时如何将 AngularJS 路由与 Express (Node.js) 一起使用?
如何使用 mongodb、node.js、express 和 EJS 创建动态站点地图?