I'm trying to use Siesta for sending POST request with multiple url parameters.
The problem is even though the solution is presented here, it only shows example for a single parameter. So my question is, is there any other ways to add multiple parameters or should I just use the withParam() multiple times?
E.g. .withParam("myparam", "1").withParam("myparam2", "1").withParam("myparam3", "1")...
I'm asking because using withParam() multiple times kinda look messy although it works =)
You’ve answered your own question: withParam is chainable, and that is the correct way to add multiple params.
It’s quite possible to format it in a tidy way, as in this snippet from the example project:
var activeRepositories: Resource {
return service
.resource("/search/repositories")
.withParam("q", "stars:>0")
.withParam("sort", "updated")
.withParam("order", "desc")
}
I would welcome a feature request for a flavor that takes a dictionary if you or others think that would be useful.
Related
Simple question, in terms of best practice is it better to format my URL like this:
http://www.example.com/search?query=hello&page=1
or like this:
http://www.example.com/search/hello/page/1
Can you provide a valid reason for your choice please.
First one fits the situation where you want to "filter" your result if it gets a little too complicated, like this example:
cars.com/audi/sedan/a/4/black/manual.....
this is gonna take so long and complicated and result will be nightmare, but this would work better:
cars.com/mercedes/amg?color=white&transmission=manual
2nd way is just like thinking it of a 'folder'ed structure:
socialmedia.com/shares/1/comments/1/page/2
I am pretty sure you get the idea.
p.s. if you will provide your API to a brand new clients, who don't know anything about it, then first one is also more understandable but, i suggest you also have a API documentation which describes the parameters and the relevant poasible other calls as well. in this way your url formatting will be clearer and clients will not struggle to solve parameters in the url.
The first way is not only functional, but lets a human understand what the name/value pairs are. Sure you could go into configuration and string manipulation and make your URL look like the second example and still function, but from a readability pov and ease of function, the first one is best.
When I allow a user to enter text using s:textfield, he can enter something like <b>Name</b> or something like \Me/. I want that these should be escaped before I am saving them to the database. When we retrieve them, the escaping is done automatically, but I want it to happen also when we are saving it.
I was trying to return a json output from my action class, but due to a name \a/ stored in my database, wrong json was being formed. This would have been avoided if the name had been escaped before being saved into the database.
You can use StringEscapeUtils. You can call escapeJavascript(textfield) in your action and then store it into the database.
#Daud, The problem you explained is called Cross site scripting or XSS.
And I think you should use Filters to clean the request parameters. This is the most sophisticated way. You can call these filters for the actions which are posting some parameters via request.
Visit my blog to see how to avoid XSS threat using Filter approach.
I also faced this issue when our project was tested by well known firm specializing in security testing and they suggested this filter approach.
You can give it a try.
I have a rails 3 app and now i implementing filter for my catalog. Filters form pass data to controller through GET request. As a result i have link like this in my browser after i submit
my form (apply search):
http://localhost:3001/shoes?filter%5BShoeBottomType%5D%5B%5D=2&filter%5BShoeClassification%5D%5B%5D=1&filter%5BShoeClassification%5D%5B%5D=2&filter%5BShoeElation%5D%5B%5D=3&filter%5BShoeElation%5D%5B%5D=4&filter%5BShoeElation%5D%5B%5D=5&filter%5BShoeLiningColor%5D%5B%5D=2&filter%5BShoeLiningColor%5D%5B%5D=3&filter%5BShoeLiningColor%5D%5B%5D=4&filter%5BShoeTopColor%5D%5B%5D=1&filter%5BShoeTopColor%5D%5B%5D=2&filter%5Bonly_action%5D%5B%5D=1&page=2
Is there a way to do URL more beautiful?
PS i dont want use POST request, because I read that it is bad for SEO
TLDR: just leave it.
HTML forms serialize in a straightforward manner; the parameters are named after the HTML elements. The actual issue here is how the form elements are named. It looks like they have names like filter[ShoeBottomType][]; look into your HTML to see the name attributes. Since you're in Rails, I'm guessing you having a filter hash passed to your Rails controller method as a single argument, and since Rails expects hashes to use a certain URL format for hashes and arrays (it has to know how to deserialize it from the request), the form helper writes the form that way. And yours is especially complicated because the hash values are arrays, hence the extra set of brackets. Then it's URL encoded and you end up with an ugly mess.
You could avoid some of this problem by passing the inputs individually back to the controller instead of as a big hash. Something like:
def index
shoe_bottom_types = params[:bottom_types]
shoe_classifications = params[:classifications]
shoe_elations = params[:elations]
...
which will get you to: /shoes?bottomTypes[]=1&bottomTypes[]=2.... That doesn't seem much better, and now your controller is all gross. And I don't see how you're going to get rid of the brackets entirely if you want to have more than one of the same filter. I guess you could get crazy and do your own parsing in your controller, like breaking apart shoeBottomTypes=1|2, but then you'll have to do your own form serialization too. Again, just not worth it.
Backing up for a sec, the SEO stuff doesn't make much sense. Search engines won't fill out your form; they just follow links. The real reason you should use GET is that (presumably), submitting your form doesn't have side effects, since it's just a search. See here; it's important to use the right HTTP methods. If you use POST, you'll get weird warnings on reloads and you won't be able to bookmark the search.
Backing up even further, why do you care, especially now that SEO is out of the picture? Just as a quick demo, I did a google search for the word "thing" and this was the URL:
https://www.google.com/#hl=en&output=search&sclient=psy-ab&q=thing&pbx=1&oq=thing&aq=f&aqi=g2g-s1g1&aql=1&gs_sm=3&gs_upl=764l1877l0l1980l6l6l0l0l0l0l89l432l5l5l0&bav=on.2,or.r_gc.r_pw.r_cp.r_qf.,cf.osb&fp=220ef4545fdef788&biw=1920&bih=1086
So URLs for form submissions can be long. The user won't even look at it.
The only possibility I can think of for why you'd care about the length/ugliness of your URL here is that you want, separately from the form, to create links to certain searches. There are several ways to handle that, but since I don't know whether that's relevant to you, I'll let that be a follow-up.
So bottom line, it looks like I'd expect, and trying to fix it sounds ugly and pointless.
If you do not want to use a POST request, then there is no other way then to put the form values in the URL -- they have to get to the server one way or another.
On the other hand however, I do not see why doing a POST would be bad for SEO and I would love to see the article that stated so.
My suggestion is that you could add some custom routes to beautify your urls.
For example :
http://localhost:3001/shoes/Type/2/Classification/1,2/Elation/3,4,5/LiningColor/2,3,4/TopColor/1,2/only_action/1/page/2
This is far much shorter than your initial URL ;)
The counterpart is that, as far as I know, you have to use always the same order for params in your url.
The routing rule is the following :
match "shoes/Type/:type/Classification/:classification/Elation/:elation/LiningColor/:liningcolor/TopColor/:topcolor/only_action/:only_action/page/:page" => "shoes#show"
You can retrieve the passed values in params array. You have to split the string containing , in order to retrieve the multiple values.
I have a relatively simple (I think) use-case but I can't find any examples where someone has done this. We are using Varnish as a cache and reverse proxy in front of two different applications and would like to make things a bit more unified across both as they both do similar things. I was hoping Varnish could help rewrite the URLs as shown below.
Original application URL for pagination (get first 10 items):
http://myapplication.com/products/?startindex=1&endindex=10
Desired URL:
http://myapplication.com/products/?paginate=1:10
This is just one example (the most complex because it combines two parameters), but in all cases the input values for the parameters stay the same, it is just that the parameter names will change.
Another example would be:
http://myapplication.com/search/?query=something
to:
http://myapplication.com/search/?q=something
Does anyone have any experience with varnish and how this could be done?
Thanks
Apparently you can. The answer is that regsub is your friend.
For example:
if (req.url ~ "(.*)(id=)") {
set req.url = regsub(req.url, "(feeds/[a-zA-Z]*/)(.*)([\?|&])(id=)([a-zA-Z0-9]*)(.*)", "\1\2\3byGuid=\5\6");
}
This will convert and incoming "id" parameter into a "byGuid" parameter on the backend. t also does a bunch of stuff with the rest of the URL string but the basics are there. SO if anyone wants to do something similar this is a good starting point.
I'm unsure what the proper way is to access parts of the requested URL.
In this case, I want to get the requested path without the query variables. This is the only way I found to do it:
String path = getRequest().getResourceRef().getHostIdentifier() +
getRequest().getResourceRef().getPath();
The result would be the bold part of this url: https://stackoverflow.com/questions/ask?query=value
I also found about 6 different ways to get the server name (http://stackoverflow.com) but I'm worried that some of them would fail in certain cases that I am unaware of (why would there be 6 different ways to do one thing):
getRequest().getHostRef().getHostIdentifier();
getRequest().getHostRef().getIdentifier();
getRequest().getRootRef().getHostIdentifier();
getRequest().getRootRef().getIdentifier();
getRequest().getResourceRef().getHostIdentifier();
And this seems to get the complete URL with query parameters:
getRequest().getResourceRef().getIdentifier();
Any further explanation would be much appreciated.
If you're in a UniformResource (or subclass) I think you might be looking for the method getReference(), which returns the URI reference. There are a number of other convenience methods in that class you might be interested in so you don't have to go through the request. See UniformResource (Restlet 2.0).