node.js with express how to remove the query string from the url
Asked Answered
B

10

48

I have a button that is performing a get to my page and adding a filter to the query string. My code applies that filter to the grid but the user can remove/edit that filter. Since they can see what filter was applied in the grid, I would like to remove the ?filter=blah from the query string when the page is displayed.

It might be confusing if on the page and the URL says ?filter=columnA which is correct initially, but the user removes that filter and applies a new one on columnB but the query string still says ?filter-columnA. The grid can handle changing filters without needing a post back.

How can I do that? And if you cannot remove/update a query string, is it possible to parse it and then just redirect to the main page without the query string? Once I have the filter saved to var filter, I no longer need it in the query string.

here is the code that displays the page:

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
            }
    });

};
Bratcher answered 4/1, 2013 at 23:49 Comment(0)
R
69

Use url.parse() to get the components of your address, which is req.url. The url without the query string is stored in the pathname property.

Use express' redirect to send the new page address.

const url = require('url'); // built-in utility
res.redirect(url.parse(req.url).pathname);

Node docs for url.

Raster answered 28/10, 2013 at 15:29 Comment(4)
Use req.originalUrl instead of req.url to work inside of nested routerJarmon
A more modern way would be to use new URL(req.originalUrl).pathname instead of url.parse(req.url).pathname. This lets you avoid loading the url module (const url = require('url'); line).Tannertannery
@JakubKukul this is not correct for Node: you are still supposed to require the url module in Node.Candlestand
For a bit more context: in Node.js "originalUrl" only has the path part of the URL and the URL constructor treates this as an invalid URL; so you can't use that simple construction in Node.js-land.Erythro
D
34

Don't use a module for doing something like that:

res.redirect( req.originalUrl.split("?").shift() );
Delusive answered 20/8, 2015 at 12:54 Comment(2)
"Don't use a module for doing something like that." Why? url.parse is a core module since 0.1.25 and very suitable for this task.Helix
@MarttiLaine cause native javascript can delete a string after a eventual given char. (Thought it may have some caveats for complex urls or with hashHistory)Blistery
B
23

Express 4.x+ answer:
res.redirect(req.path)

Battologize answered 9/8, 2016 at 22:36 Comment(3)
res.redirect(req.baseUrl)Elwina
req.baseUrl is undefined, req.path works as intended.Propertius
In some cases (e.g. when in middleware) you might actually need to combine req.baseUrl and req.path. See my answer for more details.Tannertannery
T
10

Generic Node.js solution

> new URL('https://example.com/admin/new?foo=bar').pathname;
'/admin/new'

If you also want to include the origin:

> const url = new URL('https://example.com/admin/new?foo=bar')
> url.search = '';
> url.toString() 
'https://example.com/admin/new'

Express.js solution

Other answers include various combinations of using req.url / req.originalUrl / req.path / req.baseUrl. Which one to use depends on the context. These properties behave differently if you're in the app.METHOD function or if you're accessing them from inside a middleware or a nested router.

Summary:

  • Using req.originalUrl should be the most versatile, but you need to parse the pathname yourself (see above).
  • Using req.path is the most straightforward, but you have to make sure you're not in a middleware/nested router.

When you're inside of the app.METHOD function:

// 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!');
});

When you're inside a middleware (or a nested router):

// 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();
});
Tannertannery answered 6/6, 2021 at 12:42 Comment(0)
R
8

Use req.path

If your endpoint is http://<your-domain>.com/hello/there?name=john...

then req.path = /hello/there


Documentation: https://expressjs.com/en/api.html#req.path

Redaredact answered 4/4, 2019 at 17:52 Comment(0)
I
6
// 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);

}
Interpretive answered 16/4, 2016 at 17:32 Comment(0)
S
4

The full url is stored in req.url in your case, use node.js's url.parse() to pull out the parts. Take the path and send a Location header using res.set() to redirect to URL without the query string.

var url = require('url');
res.set('Location', url.parse(req.url).pathname);
Stunning answered 5/1, 2013 at 0:19 Comment(1)
I tried that...it still has the query string in it...maybe I am not calling the right thing to "redirect" it. My code is as follows: exports.show = function(req, res) { var filter = req.query.filter; if (filter === null || filter === "") { filter = "n/a"; } res.set('Location',url.parse(req.url).pathname); res.render('somepage.jade', { locals: { title: 'somepage', filter: filter } }); };Bratcher
H
3

In order to avoid reload the page by forcing a redirect, I added the following to the <head> section of my .ejs file:

<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>

Source: http://atodorov.org/blog/2013/01/28/remove-query-string-with-javascript-and-html5/

Hhour answered 20/6, 2017 at 9:2 Comment(1)
Did you try reloading? If not, the reload doesn't work as there are no query parameters now to get the data about.Mum
U
1

use this method to remove specific query parameter from 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"));

Above example will return /foo?bar=bar

Undamped answered 11/12, 2020 at 8:7 Comment(0)
Y
0

I had a similar issue and the way that I approached it was by adding a script in the section. However, in order to avoid inconsistencies when I was moving either backward or forward I needed to add an onbeforeunload event listener. The benefit of that approach is that it avoids the redirection.


    // Stores the original url in the local storage
    window.localStorage.setItem('specifiedKey', window.location.href);

    // Cleans the query parameter of a string and replace it in the history API
    const cleanUrl = location.href.match(/^.+(?=\?)/g);
    window.history.replaceState(null, null, (cleanUrl ? cleanUrl[0] : location.href));

    // the history is updated before the window reloads
    window.onbeforeunload = () => {
    window.history.replaceState(null, null, window.localStorage.getItem('specifiedKey'));
        }

The only issue that I imagine is browser incompatibility, with the JavaScript engine not being able to support a regex look-behind operator. This can be easily fixed using .split('?')[0]

Yeh answered 25/12, 2018 at 14:39 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.