Non-escaped query parameters for URL - go

I want to create a query parameter without escaping the query string.
For example, I need to create a query parameter q with the content
"before:{2019-12-24 19:57:34}"
so that the URL is
https://android-review.googlesource.com/changes/?q=before:{2019-12-24 19:57:34}
If I use this code (Golang Playground)
url, _ := url.Parse("https://android-review.googlesource.com/changes/")
q := url.Query()
q.Set("q", "before:{2019-12-24 19:57:34}")
url.RawQuery = q.Encode()
fmt.Println(url)
url is escaping the special characters, spaces, and brackets:
https://android-review.googlesource.com/changes/?q=before%3A%7B2019-12-24+19%3A57%3A34%7D
How can I solve this issue except manually creating the URL (without query parameters then)?

If you don't want your URL query to be encoded, then don't use the Encode() method. Instead, set the RawQuery value directly, yourself:
url, _ := url.Parse("https://android-review.googlesource.com/changes/")
url.RawQuery = "q=before:{2019-12-24 19:57:34}"
fmt.Println(url)
Output:
https://android-review.googlesource.com/changes/?q=before:{2019-12-24 19:57:34}
playground
Keep in mind, however, that this is a recipe for potential disaster, depending on how that url is eventually used. In particular, the space in that URL should be escaped, according to RFC. See more here.
Perhaps you'll want to implement your own minimal escaping, if that's compatible with your use-case.

Related

Substitute a variable in regexp.MatchString method

I have a golang script that needs to create and look for a particular regex. The string to look for id defined as a constant.
const nameRegex = "service-route"
I can use this variable in some places.
rb := &compute.Route{
Name: fmt.Sprintf("%s-%s", nameRegex, generateCode(host))
I would like to use the same string to find aswell.
Basically I have something like
matched, _ := regexp.MatchString("^service-route-.*", route.Name)
if matched {
Doing something like
matched, _ := regexp.MatchString("^%s-.*" , nameRegex, route.Name)
does not work as the function MatchString requires only 1 argument.
I tried something like
myRegex , err := regexp.Compile("%s", nameRegex)
myRegex.MatchString(route.Name)
that too does not work.
Is it even possible to use a variable to match a regex ?
The 1st parameter to MatchString is a string. So use Sprintf (as you did earlier) to generate the pattern string, something like this:
regexp.MatchString(fmt.Sprintf("^%s-.*", nameRegex), route.Name)
or construct the string using concatentation:
regexp.MatchString("^" + nameRegex + "-.*", route.Name)
This seems to be a one-off check, so there is not need to pre-compile the regex.
It is possible. Here is go playground : https://play.golang.org/p/hc9eMcSzGQC

Search Query Parameter

I want to search email which contains '+' in it. for example
something like this myemail.subdomain+1#domain.com.
URL - https://example.com?searchKey=myemail.subdomain+1#
I am using Laravel, this parameter is fetched from route using
$request->get('searchKey');
but it's converting '+' to ' ' ,
as a result i am getting
searchKey as myemail.subdomain 1#
which leads to improper result.
Any help?
PHP assumes that + from GET request is a space. Right encoded plus symbol is %2B.
You have to just prepare string from request to save plus symbol:
$searchKey= urlencode(request()->get('searchKey'));
In your case you'll get # as %40. Then you can replace plus with correct code and decode it. But then be careful with usual spaces!
$searchKey = urlencode(request()->get('searchKey'));
$searchKey = urldecode(str_replace('+', '%2B', $searchKey));
https://www.php.net/manual/en/function.urlencode.php
https://www.php.net/manual/en/function.urldecode.php
P.S. I suppose it is not the best soulution, but it should work.
P.P.S. Or, if you can prepare plus as a %2B before it will be at search parameter, do it

http.NewRequest() decoding my URL input

When using http.NewRequest("GET", url , nil) for URLs that contain a % followed by some number, *example: https://api.deutschebahn.com/freeplan/v1/journeyDetails/356418%252F128592%252F57070%252F90271%252F80%253fstation_evaId%253D8000261) Go will encode the string to a "/" in the url. How can I avoid that?
Explicitly set the RawPath field of the URL struct:
req := http.NewRequest("GET", "https://api.deutschebahn.com/freeplan/v1/journeyDetails/356418%252F128592%252F57070%252F90271%252F80%253fstation_evaId%253D8000261", nil)
req.URL.RawPath = "/freeplan/v1/journeyDetails/356418%252F128592%252F57070%252F90271%252F80%253fstation_evaId%253D8000261"
This functionality is documented for this use case:
Note that the Path field is stored in decoded form: /%47%6f%2f becomes /Go/. A consequence is that it is impossible to tell which slashes in the Path were slashes in the raw URL and which were %2f. This distinction is rarely important, but when it is, code must not use Path directly.
Go 1.5 introduced the RawPath field to hold the encoded form of Path. The Parse function sets both Path and RawPath in the URL it returns, and URL's String method uses RawPath if it is a valid encoding of Path, by calling the EscapedPath method.

Passing a filepath over url

I need to pass this filepath over via route to my actionmethod:
<p>#car.Name</p>
so for example #car.ContainerPath is a string of "34_Creating%20Cars%20Forms/Exercise%20Cars/Audi%202010%20Parts%20Reference.pdf"
I need to escape this somehow I think? I would prefer not to send this over url but with a hyperlink I don't see a way not to.
UPDATE:
For additional info, here's the actionmethod it's going to:
public string GetFileZipDownloadUrl(CarViewModel model, string fileContainerPath)
{
string downloadUrl = string.Empty;
downloadUrl = GetFileZipDownloadUrl(model.CarId,fileContainerPath, model.UserId);
return downloadUrl;
}
so I'm sending over for that fileContainerPath paths like this in the url for that #car.ContainerPath param:
"55_Creating Cars Forms/Exercise Cars/Audi Parts Reference.pdf"
so the route url before it's requested looks like this when formed in that hyperlink:
http://Cars/55/55_Creating Cars Forms/Exercise Cars/Audi Parts Reference.pdf/20/Url
My action method just needs to use that path to go get a reference to a file under the hood.
If you want to just get rid of %20 in the url use encoding/decoding like in #Xander's answer. However if any of your data is very dynamic and can have weird characters you should consider adding a Safe() and Unsafe() methods that will strip out all the "Dangerous" characters for url, and then turn it back to original value.
Raw Url:
HttpUtility.UrlEncode(rawurl);
Decode encoded url:
HttpUtility.UrlDecode(encodedurl);
http://msdn.microsoft.com/en-us/library/system.web.httputility.urlencode.aspx
http://msdn.microsoft.com/en-us/library/system.web.httputility.urldecode.aspx

What is Ruby doing with gsub here?

I'm working on converting code from Ruby to Node.js. I came across these lines at the end of a function and I'm curious what the original developers were trying to accomplish:
url = url.gsub "member_id", "member_id__hashed"
url = url.gsub member_id, member_id_hashed
url
I'm assuming that url at the end is Ruby's equivalent to return url;
as for the lines with gsub, from what I've found online that's the wrong syntax, right? Shouldn't it be:
url = url.gsub(var1, var2)?
If it is correct, why are they calling it twice, once with quotes and once without?
gsub does a global substitute on a string. If I had to guess, the URL might be in the form of
http://somewebsite.com?member_id=123
If so, the code has the following effect:
url.gsub "member_id", "member_id__hashed"
# => "http://somewebsite.com?member_id__hashed=123"
Assuming member_id = "123", and member_id_hashed is some hashed version of the id, then the second line would replace "123" with the hashed version.
url.gsub member_id, member_id_hashed
# => "http://somewebsite.com?member_id__hashed=abc"
So you're going from http://somewebsite.com?member_id=123 to http://somewebsite.com?member_id__hashed=abc
Documentation: https://ruby-doc.org/core-2.6/String.html#method-i-gsub
I'm assuming that the url at the end is Ruby's equivalent to return url;
If that code is part of a method or block, indeed, the line url is the value returned by the method. This is because by default a method in Ruby returns the value of the last expression that was evaluated in the method. The keyword return can be used (as in many other languages) to produce an early return of a method, with or without a return value.
that's the wrong syntax, right? shouldn't it be
url = url.gsub(var1, var2)?
The arguments used to invoke a method in Ruby may stay in parentheses but they may, as well, be listed after the method name, without parentheses.
Both:
url = url.gsub var1, var2
and
url = url.gsub(var1, var2)
are correct and they produce the same result.
The convention in Ruby is to not put parentheses around method arguments but this is not always possible. One such case is when one of the arguments is a call of another method with arguments.
The parentheses are then used to make everything clear both for the interpreter and the readers of the code.
If it is correct, why are they calling it twice, once with quotes and once without?
There are two calls of the same method, with different arguments:
url = url.gsub "member_id", "member_id__hashed"
The arguments of url.gsub are the literal strings "member_id" and "member_id__hashed".
url = url.gsub member_id, member_id_hashed
This time the arguments are the variables member_id and member_id_hashed.
This works the same in JavaScript and many other languages that use double quotes to enclose the string literals.
String#gsub is a method of class String that does search & replace in a string and returns a new string. It's name is short of "global substitute" (it replaces all occurrences). To replace only the first occurrence use String#sub.

Resources