Can't find CFSCRIPT routine - coldfusion

I've written a brief CFscript to encode/decode links:
function link_encode(str) {
x = Replace(str, "&", "and", "ALL");
y = Replace(x, " ", "_", "ALL");
z = Replace(y, "/", "|", "ALL");
return z;
}
function link_decode(str) {
x = Replace(str, "and", "&", "ALL");
y = Replace(x, "_", " ", "ALL");
z = Replace(y, "|", "/", "ALL");
return z;
}
This is in a file which is include in the site header (included on every page)
<cfinclude template="/includes/cfScriptFunctions.cfm">
This works fine in a 'normal' page:
<cfset link = link_encode(sub_menu.name)>
But, for SEO purposes I rewrite URLs via web.config:
<rule name="categories_1" stopProcessing="true">
<match url="category1/(.*)" />
<conditions logicalGrouping="MatchAll">
<add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
<add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true" />
</conditions>
<action type="Rewrite" url="/category1.cfm?id={R:1}" />
</rule>
When I land on this page, Coldfusion returns the error : "Variable LINK_DECODE is undefined". But, if I try to include the cfscript file in the page Coldfusion returns the error: "Routines cannot be declared more than once. The routine link_decode has been declared twice in different templates.". This tells me that the routine is available so why isn't it being found ?
update
Ooops... My Fault ... I was calling the function before it had been included in the page ... Duh.

Question... on your cfml page... when are you calling the link_decode? When are you including the header file? I've seen people call the link decode above their headers, to get queries built etc, to put data into the header, but the header has the cfscript. Check your flow, incase you're calling it before the include.

Related

How to make a rewrite rule in IIS when a querystring parameter is missing?

I want to redirect when a Url is missing a part of the querystring. So, for example
https://www.example.com?foo=1&bar=2
is a valid url, don't do anything. But, when the url looks like this:
https://www.example.com?foo=1 I want to redirect to https://www.example.com. 'bar' is missing here, but 'bar' can be any name.
For this I want to use IIS redirects using regex. I've found this question: IIS URL Rewrite - if query parameter(s) is missing but I can't get it this to work in my scenario. This is because every other querystring parameter after the ? can have any name. The first parameter is always foo, but the rest of the parameters can have any name.
Can someone help me with the correct regex for this?
Edit:
Real examples of querystrings that must be redirected:
?crop=0,0,0,0 or
?crop=2.6111111111111112,0.22222222222222221,0,0
Both lacks the & so they must be redirected.
You could try below url rewrite rule:
<rule name="query string rule" stopProcessing="true">
<match url="(.*)" negate="false" />
<conditions logicalGrouping="MatchAll">
<add input="{QUERY_STRING}" pattern="^foo=(\d{0,5})$" />
</conditions>
<action type="Redirect" url="http://www.sample1.com/" appendQueryString="false" />
</rule>

Proper way to fix this rewrite rule?

We have an application that is run in a virtual folder in IIS. We don't want the virtual folder name to be part our links though (primarily to preserve original link names for SEO reasons).
So here is one example of a rewrite rule we're using:
<rule name="Rewrite Account controller to UI">
<match url="/Account(.*)"/>
<action type="Rewrite" url="ui/Account{R:1}"/>
<conditions>
<add input="{URL}" pattern="\.axd$" negate="true" ignoreCase="true"/>
</conditions>
</rule>
The problem with this rule is that it would also match "~/someothercontroller/258642/Accounting-Essentials" and turn it into "/ui/Accounting-Essentials". And I don't want to include the host because the host is different in each environment.
What would this need to look like to match only if the expression is the first thing after the host?
Edit:
Sorry, I guess my post wasn't as clear as I thought it was. An example would be http://x/Account. This should rewrite to http://x/ui/Account. The x could be any host name with any number of periods but it's only the host name so it wouldn't contain any slashes.
You can see in the rule I have above that I want it to include anything that comes after Account however I realize that's not quite right either because it shouldn't match "http://x/Accounting", but it should match "http://x/Account/whatever".
So essentially, you want to make sure that Account comes right after the host, and also that Account is the full name of the directory. You can achieve this like so:
<rule name="Rewrite Account controller to UI">
<match url="^Account(/.*)?"/>
<action type="Rewrite" url="ui/Account{R:1}"/>
<conditions>
<add input="{URL}" pattern="\.axd$" negate="true" ignoreCase="true"/>
</conditions>
</rule>
The ^ ensures that this is the beginning of the string that you are evaluating.
The / after Account ensures that you only rewrite the url if "Account" is the full name of the directory.
It appears from the documentation that the inital / will not be included in the string you're evaluating (which is why I removed it), but you can test it both ways to be sure.
Also note that I added a / before {R:1}.
Edit: Another way
You could also add a rule that verifies that the whole URL matches a certain pattern. This might actually be an easier way:
<rule name="Rewrite Account controller to UI">
<match url="/Account(.*)"/>
<action type="Rewrite" url="ui/Account{R:1}"/>
<conditions>
<add input="{URL}" pattern="\.axd$" negate="true" ignoreCase="true"/>
<add input="{REQUEST_URI}" pattern="^/Account(/.*)?" ignoreCase="true"/>
</conditions>
</rule>
The Microsoft docs give this example of the server variable values:
For example, if a request was made for this URL:
http://www.example.com/content/default.aspx?tabid=2&subtabid=3, and a rewrite rule was defined on the site level then:
The rule pattern gets the URL string content/default.aspx as an input.
The QUERY_STRING server variable contains tabid=2&subtabid=3.
The HTTP_HOST server variable contains www.example.com.
The SERVER_PORT server variable contains 80.
The SERVER_PORT_SECURE server variable contains 0 and HTTPS contains OFF.
The REQUEST_URI server variable contains /content/default.aspx?tabid=2&subtabid=3.
The PATH_INFO server variable contains /content/default.aspx.

understanding IIS Proxy response header rewrite Rule

we have a IIS reverse proxy response rule, which modifies Location HTTP header.. I am trying to decode the logic and planning to write same logic in xslt, can someone explain below logic. how match pattern works and action rewrite and value works and what is R:1, R:2 , R:3 here ?
<rule name="Change Location Header" enabled="true">
<match serverVariable="RESPONSE_LOCATION" pattern="^http(s)?://([^/]+)/(.*)" />
<conditions logicalGrouping="MatchAny" trackAllCaptures="true">
<add input="{RESPONSE_STATUS}" pattern="^301" />
<add input="{RESPONSE_STATUS}" pattern="^302" />
</conditions>
<action type="Rewrite" value="http{R:1}://{R:2}/{R:3}" />
</rule>
Your rule is changing the domain in the HTTP location header for redirect responses
How is working match condition and what is R:1,R:2,R:3
RESPONSE_LOCATION variable has full lik url. For example:
https://demo.cloudimg.io/s/width/300/sample.li/boat.jpg
In this case, after match operation with regexp: ^http(s)?://([^/]+)/(.*)
Mathces will be like that:
{R:0} https://demo.cloudimg.io/s/width/300/sample.li/boat.jpg
{R:1} s
{R:2} demo.cloudimg.io
{R:3} s/width/300/sample.li/boat.jpg

IIS rewrite rule to check for querystring and add it if its not there

I'm trying to make a IIS URL rewrite rule that appends an URL parameter to the URL. The url parameter is hssc. So, any url that is processed through the server, needs that parameter. Keeping in mind that some urls will have their own params already, and other urls won't, and root urls, etc, sometimes it will need to add ?hssc=1 or &hssc= - so, if I have a URL that is as such:
http://www.blah.com should become http://www.blah.com/?hssc=1
http://www.blah.com/index.html should become http://www.blah.com/index.html?hssc=1
http://www.blah.com/?q=5 should become http://www.blah.com/q=5&hssc=1
http://www.blah.com/index.html?q=5 should become http://www.blah.com/index.html?q=5&hssc=1
http://www.blah.com/index.html?q=5&hssc=1 should be left alone
I also want it that the URL should not be hidden (as in a backend rewrite behind the scenes). I need the URL to appear in the URL, so when users copy the URL, or bookmark it, the parameter is there.
I've set the condition to match it \&hssc|\?hssc - now I just need a way to write the URL, so it appears and keeps the part of the original URL that is already there.
Figured this out - the rule will be set up as such:
<rewrite>
<rules>
<rule name="sigh" patternSyntax="ECMAScript" stopProcessing="true">
<match url="(.*)" negate="false" />
<action type="Redirect" url="{PATH_INFO}?hssc=1" />
<conditions>
<add input="{QUERY_STRING}" pattern="^hssc=|\?hssc=|\&hssc=" negate="true" />
</conditions>
</rule>
</rules>
</rewrite>
just as a hint to maintain QS through the code:
public static string GetQS()
{
var sb = new System.Text.StringBuilder();
System.Collections.Specialized.NameValueCollection Qs = HttpContext.Current.Request.QueryString;
var lst = new List<string>(Qs.AllKeys);
foreach (string s in lst)
{
if (s == "MyOwnQSKey")
sb.Append(s + "=" + "MyValue" + "&");
else
sb.Append(s + "=" + Qs[s] + "&");
}
if (!lst.Contains("MyOwnQSKey"))
sb.Append("MyOwnQSKey=MyValue&");
if (sb.ToString().EndsWith("&"))
sb.Remove(sb.Length - 1, 1);
return "?" + sb;
}
i just copied this from one of my projects similar to yours in Url-Rewrite and QS
hope this help

Is this the best place to use a 301 redirect to control which domain name is used?

I am using ColdFusion 9.0.1
I have a new site that is accessible through a few domains such as:
mydomain.com
www.mydomain.com
foo.mydomain.com
For SEO and tracking purposes, I want to make sure that only "mydomain.com" is indexed and accessed. So, every request that tries to access my site through other domains will be 301 directed to "mydomain.com".
I want to make sure that I capture and preserve the query string so that I don't just send people to the home page.
I will also make sure that I can access the site locally at 127.0.0.1
I wondering where in the code is the best place to do this SPECIFIC type of redirect. My guess it's in application.cfc near the top, in the onRequestStart() method.
Is this best place to put the code and does is this code complete? Is there a better way to code this?
<cfscript>
ThisHost = CGI.HTTP_HOST;
QString = CGI.QUERY_STRING;
GoToURL = "http://mydomain.com?" & QString;
if (ThisHost != "mydomain.com" && ThisHost != "127.0.0.1") {
writeOutput("<cfheader statuscode='301' statustext='Moved permanently'>");
writeOutput("<cfheader name='location' value='#GoToURL#'>");
abort;
}
</cfscript>
UPDATE
I know this isn't the best way to accomplish what I need, because this task is much better suited to the web server's skill set. Here's my code till I can implement this on the web server:
<cfscript
ThisHost = CGI.HTTP_HOST;
QString = CGI.QUERY_STRING;
GoToURL = "http://flyingpiston.com/?" & QString;
if (ThisHost != "flyingpiston.com" && ThisHost != "127.0.0.1:8500") {
location(GoToURL, false, 301);
}
<cfscript
I agree with other comments and answers that doing this at the web server is a better solution. I would also point out that if you want to use the script syntax, this is entirely wrong and will simply return a string to the browser:
writeOutput("<cfheader name='location' value='#GoToURL#'>");
In ColdFusion 9, you would instead use the location() function:
location("url", addtoken, statusCode);
In your case:
location(GoToURL, false, 301);
Your GoToURL variable is also missing the page name, so you'd need to add CGI.SCRIPT_NAME into the mix just before the ? to get the full URL being called.
With the tag syntax (as of ColdFusion 8 I believe), there is no need to use the CFHEADER tag for a 301 redirect. The CFLOCATION tag now supports a statuscode attribute which can be set to 301 as needed.
If you are on IIS 7.0 the you may be able configure your web.config file for a canonical redirect like so:
<configuration>
<system.webServer>
<rewrite>
<rules>
<rule name="Redirect to WWW" stopProcessing="true">
<match url=".*" />
<conditions>
<add input="{HTTP_HOST}" pattern="^domain.com$" />
</conditions>
<action type="Redirect" url="http://www.domain.com/{R:0}"
redirectType="Permanent" />
</rule>
</rules>
</rewrite>
</system.webServer>
</configuration>
Check out this link for additional options.
The previous answer shows how to redirect domain.com to www.domain.com. If you want to redirect www.domain.com to 'domain.com', you will need a web.config file that looks like this:
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<location path="" overrideMode="Inherit">
<system.webServer>
<rewrite>
<rules>
<rule name="remove www" patternSyntax="Wildcard" stopProcessing="true">
<match url="*" />
<conditions logicalGrouping="MatchAny">
<add input="{HTTP_HOST}" pattern="www.*" />
<add input="{HTTP_HOST}" pattern="foo.*" />
</conditions>
<serverVariables />
<action type="Redirect" url="http://{C:1}" />
</rule>
</rules>
</rewrite>
</system.webServer>
</location>
</configuration>
The above web.config file was created on IIS 7.5 (Windows Server 2008 R2).
Your host will need to install the URL Rewrite Module as mentioned above in order for this to work.
The web.config file is stored in the root folder of your site.
The above example will redirect 'www' and 'foo' sub-domains to the domain.
This 10 URL Rewriting Tips and Tricks article has been a good reference for me.