150

I am trying to pass parameters to a URL which looks like this:

http://www.foobar.com/foo?imageurl=

And I want to pass the parameters such as an image URL which is generated itself by another API, and the link for the image turns out as:

http://www.image.com/?username=unknown&password=unknown

However, when I try to use the URL:

http://www.foobar.com/foo?imageurl=http://www.image.com/?username=unknown&password=unknown

It doesn't work.

I have also tried using encodeURI() and encodeURIComponent() on the imageURL, and that too doesn't work.

HoldOffHunger
  • 15,349
  • 8
  • 79
  • 115
Apoorv Saxena
  • 3,846
  • 10
  • 28
  • 46
  • What language is generating the URL? JavaScript? – Phil Nov 15 '11 at 10:53
  • 5
    Note that you should not put passwords in urls, not even when using https, as every router between client and server will see the whole url. – fabb Aug 30 '18 at 05:54
  • Does this answer your question? [How to create query parameters in Javascript?](https://stackoverflow.com/questions/111529/how-to-create-query-parameters-in-javascript) – Nick Grealy Aug 25 '20 at 03:16
  • 1
    @fabb That doesn't seem to be true: https://stackoverflow.com/a/499594/513038 – Erhannis Dec 08 '20 at 17:01
  • @Erhannis GET path and params are encrypted for HTTPS, but not HTTP (which, ok, no-one should be using, but still...). However, much more seriously, server logs and any analytics tools will see the GET params, so you'll log plaintext passwords in your apache logs, and in your Google Analytics. They're also sent through the referrer header, if that's enabled. See https://security.stackexchange.com/questions/233795/are-url-parameters-of-get-and-post-requests-over-https-secure – Dan W Sep 03 '21 at 10:39

4 Answers4

202

With PHP

echo urlencode("http://www.image.com/?username=unknown&password=unknown");

Result

http%3A%2F%2Fwww.image.com%2F%3Fusername%3Dunknown%26password%3Dunknown

With Javascript:

var myUrl = "http://www.image.com/?username=unknown&password=unknown";
var encodedURL= "http://www.foobar.com/foo?imageurl=" + encodeURIComponent(myUrl);

DEMO: http://jsfiddle.net/Lpv53/

Niels
  • 46,575
  • 4
  • 58
  • 81
58

Using new ES6 Object.entries(), it makes for a fun little nested map/join:

const encodeGetParams = p => 
  Object.entries(p).map(kv => kv.map(encodeURIComponent).join("=")).join("&");

const params = {
  user: "María Rodríguez",
  awesome: true,
  awesomeness: 64,
  "ZOMG+&=*(": "*^%*GMOZ"
};

console.log("https://example.com/endpoint?" + encodeGetParams(params))
Eli Barzilay
  • 28,654
  • 3
  • 65
  • 108
Kyle VanderBeek
  • 987
  • 8
  • 7
  • This works very well in my case I added a call to decodeURIComponent inside the map function to make sure entries already encoded dont get messi – Herbert Pimentel Dec 23 '21 at 13:34
15

With URLSearchParams:

const params = new URLSearchParams()
params.append('imageurl', 'http://www.image.com/?username=unknown&password=unknown')
return `http://www.foobar.com/foo?${params.toString()}`
Flimm
  • 115,689
  • 38
  • 227
  • 240
serv-inc
  • 32,612
  • 9
  • 143
  • 165
5

Just try encodeURI() and encodeURIComponent() yourself...

console.log(encodeURIComponent('@#$%^&*'));

Input: @#$%^&*. Output: %40%23%24%25%5E%26*. So, wait, what happened to *? Why wasn't this converted? TLDR: You actually want fixedEncodeURIComponent() and fixedEncodeURI(). Long-story...

You should not be using encodeURIComponent() or encodeURI(). You should use fixedEncodeURIComponent() and fixedEncodeURI(), according to the MDN Documentation.

Regarding encodeURI()...

If one wishes to follow the more recent RFC3986 for URLs, which makes square brackets reserved (for IPv6) and thus not encoded when forming something which could be part of a URL (such as a host), the following code snippet may help:

function fixedEncodeURI(str) { return encodeURI(str).replace(/%5B/g, '[').replace(/%5D/g, ']'); }

Regarding encodeURIComponent()...

To be more stringent in adhering to RFC 3986 (which reserves !, ', (, ), and *), even though these characters have no formalized URI delimiting uses, the following can be safely used:

function fixedEncodeURIComponent(str) { return encodeURIComponent(str).replace(/[!'()*]/g, function(c) { return '%' + c.charCodeAt(0).toString(16); }); }

So, what is the difference? fixedEncodeURI() and fixedEncodeURIComponent() convert the same set of values, but fixedEncodeURIComponent() also converts this set: +@?=:*#;,$&. This set is used in GET parameters (&, +, etc.), anchor tags (#), wildcard tags (*), email/username parts (@), etc..

For example -- If you use encodeURI(), user@example.com/?email=me@home will not properly send the second @ to the server, except for your browser handling the compatibility (as Chrome naturally does often).

HoldOffHunger
  • 15,349
  • 8
  • 79
  • 115
  • What do you mean by `"except for your browser handling the compatibility"`? – Stephan Jul 31 '20 at 06:12
  • 1
    @Stephan: For example, if `site.com?formula=a+b=c` works in producing `formula=>a+b=c`, that violates the spec, but if it works, it's because Chrome/etc. can detect the spec failure of the URL, etc., and so on, w/ `user@site.com?email=user@site.com`. – HoldOffHunger Jul 31 '20 at 14:42