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.baseUrlreq.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)?

Node.js / REST:如何从 url 获取 _id

请求新页面时如何将 AngularJS 路由与 Express (Node.js) 一起使用?

如何使用 mongodb、node.js、express 和 EJS 创建动态站点地图?

如何使用 Express 和 Node.js 从表单发送参数

如何从 Node.js/Express 服务器调用 GraphQL API?