【问题标题】:node.js with express how to remove the query string from the urlnode.js 与 express 如何从 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
            }
    });

};

【问题讨论】:

    标签: node.js express query-string


    【解决方案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]

            可以轻松解决此问题

            【讨论】:

              猜你喜欢
              • 2018-12-08
              • 2019-01-14
              • 2011-02-02
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多