Add a prefix to generated links, but not to incoming routes - ruby

Our Rails 4 application needs to be accessible over an archaic portal. This portal works by adding (from the perspective of the browser) a prefix to each URL; this prefix is removed by the portal before forwarding the request to my application.
So the browser calls https://portal.company.com/portal/prefix/xyzzy/myapp/mymodel/new; the portal does its thing and requests https://myserver.company.com/myapp/mymodel/new (passing along the stripped prefix in some irrelevant way). The prefix is dynamic and can change between requests.
The problem is that the portal is not able to rewrite the HTML pages served by my application. That is, it does not put in the prefix. It expects applications to either only emit relative URLs, or to add the portal prefix themselves.
So:
A regular URL /myapp/mymodel/new, for example, must stay as is for when the application is accessed directly (for certain users which do not use the portal).
When accessed over the portal, our application must still understand /myapp/mymodel/new as usual, but when using mymodel_new_path or link_to #mymodel or form_for #my_model or whatever other magic URL generators there are, it has to add the portal prefix. So, any URL emitted by the application must look like /portal/prefix/xyzzy/myapp/mymodel/new where the per-request string /portal/prefix/xyzzy is given by some method defined by us (and the part xyzzy can change between requests).
How can I achieve that? My routes.rb looks like this today:
MyApp::application.routes.draw do
scope ' /myapp' do
get ...
This probably has to stay as is, because URLs in incoming requests do not change when coming from the portal. But how do I influence the outgoing URLs?

This suggestion will allow you to easily prefix the urls produced by the Rails path helpers as your require. Do note, however, it will also make these extended paths valid requests for your application - they shoud just route where expected but you'll get get some extra values in the params hash that you can ignore, so I suspect this is possibly acceptable.
First, add all the prefix bits as optional parameters to your routes' base scope:
scope '(:portal/)(:prefixA/)(:prefixB)/myapp' do
# routes
end
Note that the those optional params cannot include the / char without it being escaped by the path helpers, so if you have a few levels in the prefix (which it appears you do in the question) you'll need a few different params, all but the last followed by a slash, as above.
With that done, you should define default_url_options in your ApplicationController, it should return a hash of the values you need in your routes:
def default_url_options(_options={})
{
portal: 'portal',
prefixA: 'whatevertheprefixis',
prefixB: 'nextbitoftheprefix'
}
end
And that should do it, path helpers (along with link_to #object etc) should all now include those values every time you use them.
Note that since the portal bit at the start is also an optional parameter, you can simply add additional logic to default_url_options and have it return an empty hash whenever you do not want this prefixing behaviour.

Related

How to remove '/' from end of Sinatra routes

I'm using Sinatra and the shotgun server.
When I type in http://localhost:9393/tickets, my page loads as expected. But, with an extra "/" on the end, Sinatra suggests that I add
get '/tickets/' do
How do I get the server to accept the extra "/" without creating the extra route?
The information in Sinatra's "How do I make the trailing slash optional?" section looks useful, but this means I would need to add this code to every single route.
Is there an easier or more standard way to do that?
My route is set up as
get '/tickets' do
It looks like the FAQ doesn't mention an option that was added in 2017 (https://github.com/sinatra/sinatra/pull/1273/commits/2445a4994468aabe627f106341af79bfff24451e)
Put this in the same scope where you are defining your routes:
set :strict_paths, false
With this, Sinatra will treat /tickets/ as if it were /tickets so you don't need to add /? to all your paths
This question is actually bigger than it appears at first glance. Following the advice in "How do I make the trailing slash optional?" does solve the problem, but:
it requires you to modify all existing routes, and
it creates a "duplicate content" problem, where identical content is served from multiple URLs.
Both of these issues are solvable but I believe a cleaner solution is to create a redirect for all non-root URLs that end with a /. This can easily be done by adding Sinatra's before filter into the existing application controller:
before '/*/' do
redirect request.path_info.chomp('/')
end
get '/tickets' do
…
end
After that, your existing /tickets route will work as it did before, but now all requests to /tickets/ will be redirected to /tickets before being processed as normal.
Thus, the application will respond on both /ticket and /tickets/ endpoints without you having to change any of the existing routes.
PS: Redirecting the root URL (eg: http://localhost:9393/ → http://localhost:9393) will create an infinite loop, so you definitely don't want to do that.

Shorten URLs within CodeIgniter

This question has been asked a few times but I can't seem to find a solution that helps me which is why I am trying here.
I have my site setup with the following for URLs I am using CodeIgniter I have a controller called user which loads a user view.
So my URLs are structured as follows:
http://example.com/user/#/username
I want to try and strip out the user controller from the URL to tidy up my URL so they would just read:
http://example.com/#/username
Is this possible I have been looking at route and have tried lots of different options but none have worked?
$route['/'] = "user";
Could anyone offer any solution?
Assuming the '#' in your URLs is a valid function and 'username' is a parameter for that function, then this route should work:
$route['#/(:any)'] = "user/#/$1";
Depending on what usernames are to be routed you may want to change the wildcard. For example, if you only wanted to route numbers as the parameter, you could change (:any) to (:num).
(:num) will match a segment containing only numbers.
(:any) will match a segment containing any character.
You can also use regular expressions to define routing rules, allowing you to further restrict what is routed.

Ajax results filtering and URL parameters

I am building a results filtering page using AJAX requests. I would like to reflect the filters in the URL. For example: for price_from I want to add ?price_from=VAL to the URL.
I have a backend that is capable of rendering the page with URL parameters.
After some googling I would a Backbone.router solution which has a hash fallback for the IE that does not support HTML5 history API.
I have a problem with setting a good philosophy of routes. I have a set of filtering parameters (price_from, price_to, color, ...) and I would like to attach each parameter to one route.
Is that possible to chain the routes to match for example: ?price_from=0&price_to=1&color=red? (the item order can change)
It means: call all the routes at the same time and keep the ie backwards compatibility?
Your best bet would be to have a query portion of the URL rather than using GET parameters to denote the search criteria. For example:
Push state: /search/query/price_from=0&price_to=1&color=red
Hash based: #search/query/price_from=0&price_to=1&color=red
Your backend would of course need to change a bit to be able to parse the new URL structure.

Asp.Net Web Api - Change parameter name

In my team we have coding rule that requires that every function's parameter starts with prefix, e.g. *p_someParam*.
With Web Api if we want to request a GET function that takes two parameters, we should add those parameters like "...?p_firstParam=value1&p_secondParam=value2".
Is there some way to use in requests more user-friendly names, like someParam without prefix, that will automatically map to parameters in controller's action? Maybe there is some attribute to rename action parameters? I couldn't find any similar example.
Every clue is appreciated.
I think you looking for URL rewriting, in that you need to map the urls to config or programmatic
http://www.codeproject.com/Articles/2538/URL-Rewriting-with-ASP-NET nice article to follow, its in ASP.Net,

What are the benefits of using MVC HTML helpers like ActionLink, BeginForm, TextBox, etc instead of the native HTML tags?

In a SO response to a different question, a user stated that it allowed you to avoid hard-coding route values into a html link tag, but that is not really valid since you have to put in the controller, action, area, etc as strings so you are still hard-coding the route values.
How is this:
#Html.ActionLink(linkText: "MyLink", actionName: "MyAction", controllerName: "MyController", new { id = #myId }, new { area = "SomeArea"})
better than this:
<a href='/SomeArea/MyController/MyAction/myId'>MyLink</a>
Your observation is only true if (a) you're using strictly the default routing format and (b) if your application will always be installed at the root of the site. If you don't do the former (say create a short cut route /help which goes to the Home controller and Help action, and subsequently change it by introducing a Help controller with more actions, then you'll need to update all of your hard-coded anchor tags. A better alternative is using the RouteLink helper with the route name and, optionally, other parameters.
With regard to the latter, I typically use a single server for most of my staging deployments and the application does NOT sit at the site root, but rather in a subdirectory. Production deployment is mixed, but many applications get installed at the site root. Using the helpers allows me to ignore the difference during development as the helper properly constructs the url relative to the current site in all cases. This is so helpful that I even use it for scripts, css files, images, etc. via the UrlHelper to make sure that any paths specified for those do not break between staging and production.
There seems to be little to benefit in using the helper, providing you make one change - add a tilda so that the router automatically resolves the address to the correct place.
<a href='~/SomeArea/MyController/MyAction/myId'>MyLink</a>

Resources