0

I am facing a challenge with extracting the complete value out of the query param.

For instance, I have a localhost:8080/myAPI?name=Shop & stop #1234

I have the issue with & as well but atleast the content after & is getting populated as a separate param. I wrote some logic to manage it.

Coming to #, the content after # is not at all getting populated. I am using net/http library.

Did anyone face the similar issue?

Curious
  • 29
  • 2
  • 1
    The problem with your question is that you did not tell us what exactly you are _doing._ Is it about making an HTTP request to an HTTP server (listening on `localhost:8080`) or is it about your server which accepts requests from clients which perform HTTP requests to the `/myAPI` endpoint of your _server,_ and you're having troubles with the clients properly sending arbitrary strings as the value of the `name` URL query parameter? – kostix Mar 31 '21 at 17:44
  • 1
    One facet of the problem I've described is that your question contains no code at all, so it's very hard to see what exactly "extracting the complete value" even means, and it's not clear whether you're attempting to do that correctly or not. – kostix Mar 31 '21 at 17:45
  • Please read [this](https://stackoverflow.com/help/on-topic) and [this](https://stackoverflow.com/help/minimal-reproducible-example) to not repeat the indicated problem in your future questions. – kostix Mar 31 '21 at 17:46
  • 1
    Fragments (that is what you call "content after # " is not sent in a HTTP Request _at_ _all_. You simply cannot know the fragment on the server side as the URL of the request never contains a fragment. – Volker Mar 31 '21 at 18:20
  • see also https://stackoverflow.com/questions/1637211/get-anchor-from-uri –  Mar 31 '21 at 18:37
  • @Volker Yeah. I guess I have to find a way to update the way I am sending the name. Maybe add a new parameter to send the value after '#'. Looks like that is the only option I have. – Curious Apr 01 '21 at 13:45
  • @mh-cbon Thanks for the link. Looks like it is not possible to capture the content after '#' from the server side. – Curious Apr 01 '21 at 13:49
  • @ThinkGoodly Are you referring to the this code snippet you posted before? In your case you have hard coded the name value. In my case, I am not seeing content after # entering into my code at all. the server is stripping it. I maybe wrong. Please advise me if I am not understanding your comment correctly. Thanks. This is the code I got from your previous comment. v := url.Values{} v.Set("name", "Shop & Stop #23452") q := v.Encode() u := "http://localhost:8080/myAPI?" + q fmt.Println(u) // prints http://localhost:8080/myAPI?name=Shop+%26+stop+%2323452 – Curious Apr 02 '21 at 03:14
  • @ThinkGoodly Thank you very much. Now I got the complete Idea. The user have to construct the URL like you suggested in the previous comment so that I will be able to capture my expected value. I tested it in my local; I got the expected value. – Curious Apr 02 '21 at 13:48

2 Answers2

2

First, in URLs the & character has special meaning: it spearates query parameters. So if the data you encode in the URL contains & characters, it has to be escaped. url.QueryEscape() can show you how the escaped form looks like:

fmt.Println(url.QueryEscape("Shop & stop "))

It outputs:

Shop+%26+stop+

Note that & is escaped like %26, and also spaces are substituted with a + sign.

So your valid input URL should look like this:

rawURL := "http://localhost:8080/myAPI?name=Shop+%26+stop+#23452"

Use the net/url package to parse valid URLs, it also supports getting the parameter values and the fragment you're looking for (the fragment is the remaining part after the # character):

u, err := url.Parse(rawURL)
if err != nil {
    panic(err)
}

fmt.Println(u.Query().Get("name"))
fmt.Println(u.Fragment)

This outputs:

Shop & stop 
23452

Try the examples on the Go Playground.

icza
  • 389,944
  • 63
  • 907
  • 827
1

The bytes &, # and space have special meaning in a URL. These bytes must be escaped when included in a query value.

Use url.Values to create the escaped query:

v := url.Values{}
v.Set("name", "Shop & Stop #23452")
q := v.Encode()
u := "http://localhost:8080/myAPI?" + q
fmt.Println(u) // prints http://localhost:8080/myAPI?name=Shop+%26+stop+%2323452

You can also construct the URL using the url.URL type instead of string concatenation.

v := url.Values{}
v.Set("name", "Shop & Stop #23452")
u := url.URL{Scheme: "http", Host: "localhost:8080", Path: "/myapi", RawQuery: v.Encode()}
s := u.String()
fmt.Println(s) // prints http://localhost:8080/myAPI?name=Shop+%26+stop+%2323452

The url package encodes the # as %23. Most http server libraries will decode the %23 back to #. Here's an example using Go's net/http package:

name := req.FormValue("name") // name is "Shop & Stop #23452"

Run a complete client and server example on the Go Playground.

  • Thank you very much. – Curious Mar 31 '21 at 18:30
  • If this is indeed what the OP wanted (manipulating URLs to make client requests), I would recommend to extend your example and use the full power of `url.URL` to create a compete URLs containing the host, the path component and the query. – kostix Mar 31 '21 at 19:27
  • I have played around with the url.URL functionality but couldn't find a way to read the content after #. everything after # including it is not showing up in the url in my code. Below is how I am trying to capture the url in my code. u, _ := url.QueryUnescape(r.URL.string()). when I print 'u' I am getting. -> /myAPI?name=STOP & SHOP – Curious Mar 31 '21 at 21:34
  • I am trying to include the #23452 in the name parameter value – Curious Apr 01 '21 at 00:29
  • @SaiBagam, «but couldn't find a way to read the content after #.», OK this means you have fell victim of the so-called "XY Problem" as well. Please, _please,_ read [this](https://meta.stackexchange.com/questions/66377/what-is-the-xy-problem) carefully! – kostix Apr 01 '21 at 10:16