IIS 404 dynamic redirect - iis

Question for you guys.
If I am capturing a 404 error through an isapi filter in IIS and calling a handler with code to redirect the user by taking in their url request as a parameter and running a query on the database. Can I run into issues making that dynamic server side redirect if multiple users are being caught by the error handler simultaneously. I believe the first execution is being terminated, the second one completes, and both users are redirected to the same url.
Any thoughts?
Thanks

I am capturing a 404 error through an isapi filter in IIS...
I am not clear if you are writing the filter, or if the filter already exists. I'll assume you are writing it yourself since this is stackoverflow, and I'll assume C or C++ since you said ISAPI.
In that case....An ISAPI filter will get an HTTP_FILTER_CONTEXT for each request incoming request. You need to structure your code so as to keep those things separate; pass the pointer to that structure around to each function in your code, if using C, or store it in object state if using C++. Also your code needs to be thread-safe.
Can I run into issues making that dynamic server side redirect if multiple users are being caught by the error handler simultaneously.
Yes, if you don't follow the requirements for writing a multi-threaded filter.
There are simpler ways to accomplish what you want, I think. IIS allows administrators to specify URLs to deliver a "custom HTTP Error Response". The URL can be anything on the webserver, including a dynamic web script, like a page written in ASPNET or PHP or whatever. You may want to use a 302 redirect to your dynamic page; that's a common pattern. There's no need to resort to writing an ISAPI filter.

Related

JSF - How to migrate URLs by intercepting and redirecting potential 404 errors?

When migrating websites often dead URLs happen since old website used different URL structure or technology. Correct 301 "permanent" redirect is important for SEO friendly migrations.
Example:
Old page https://example.com/product/coca-cola-bottle.html moved in our JSF project to https://example.com/p/coca-cola-1-l/1000
Concept
We will save those mappings in our database and add them to our JSF application.
If an URL is requested that is not valid or rewritten we want to check the current requested URL if it exists in our database and redirect to the new target.
Some Ideas?
Create a custom exception handler and redirect if resource was not found
Override navigation handler to handle it before exception handler
Use #WebFilter with DispatcherType.ERROR and 404 error code check
Use OCPSoft rewrite solution. Not sure how to do this without loading all mappings into configuration. I prefer dynamic (lazy) approach.
Right now i implemented #WebFilter version using an injected bean to lookup the mapping.
I would start by including the rewrite-integration-cdi module:
https://github.com/ocpsoft/rewrite/blob/master/documentation/src/main/asciidoc/integration/cdi.asciidoc
Then create a CDI bean/Java class that can access your database.
Inject an instance of that class into your Rewrite ConfigurationProvider, then use it to build / create your Rewrite rules.
Here is an example of both #Injecting beans into your ConfigurationProvider, and also defining custom HTTP operations:
https://github.com/ocpsoft/rewrite/blob/master/showcase/rest-ws/src/main/java/org/ocpsoft/rewrite/showcase/rest/RestRewriteConfiguration.java
Depending on how dynamic you want your database lookups to be, you could either preload them at startup time (when the Config is built), or load & cache them inside the Request/Response lifecycle itself using a custom HttpCondition and `HttpOperation:
https://github.com/ocpsoft/rewrite/blob/master/api-servlet/src/main/java/org/ocpsoft/rewrite/servlet/config/HttpCondition.java
https://github.com/ocpsoft/rewrite/blob/master/api-servlet/src/main/java/org/ocpsoft/rewrite/servlet/config/HttpOperation.java
Then use those operations in your ConfigurationProvider to perform the database operations. Essentially you will do something like this, but check the database to see if the requested URL is a ‘known/stored’ redirect:
https://github.com/ocpsoft/rewrite/blob/851ccbabb8b6248c66589076fa67cb0ec07b3132/impl-servlet-tests/src/test/java/org/ocpsoft/rewrite/servlet/config/HttpRequestParameterTestProvider.java#L45
And then use an custom HttpOperation to perform the actions you want to take.
https://github.com/ocpsoft/rewrite/blob/851ccbabb8b6248c66589076fa67cb0ec07b3132/config-servlet/src/test/java/org/ocpsoft/rewrite/servlet/config/JoinBindingConfigurationProvider.java#L48
You could also technically just use a Condition that matches all requests, and an HttpOperation That only takes action if there is a database entry.
All that said, this sounds more complicated than it is, but there’s no good example I can find to link to that does exactly what you want, so I’m trying to piece it together.

Can a hard-set a status code in the web.config?

I would like to return a 404 status code for every single request to a website. I still want to deliver a page of content, but I want the status code on every single request to be 404. (It's weird, I know, but there's a specific reason...)
I know I could do with this an HTTP Module or an OWIN pipeline, but I'd like to do it without writing or deploying code, if possible. However, this is a very weird situation, so I'm not sure if this is possible.
Can I set this from the web.config?
As lex says, we couldn't return the right content page with 404 error status.
Here is a workaround, we could try to use custom error page to achieve your requirement. If it should return 404 error, you could redirect the page to custom error page. But you should use the url rewrite to redirect all the pages to a not existed page.
Details about how to use custom error page in IIS, you could refer to this article.
Details about how to use url rewrite, you could refer to this article.

What does ColdFusion's JWildCardHandler do in IIS?

I tried to disable Script permission on a folder for uploads and realized if I don't remove the JWildCardHandler, I would get,
HTTP Error 403.1 - Forbidden
You have attempted to run a CGI, ISAPI, or other executable program
from a directory that does not allow executables to run.
Would someone please explain what does JWildCardHandler do? Was it meant for handling some SEO-friendly URL? Why is it enabled by default? Wouldn't that mean requesting static files would also invoke this unnecessary handler?
The only plausible use-case I can think of is something like:
http://mydomain.com/index.cfm/something
Is this what something JWildCardHandler would handle?
Thanks
Would someone please explain what does JWildCardHandler do?
This is ColdFusion's catch-all handler for interpreting requests for ColdFusion pages.
Was it meant for handling some SEO-friendly URL? Why is it enabled by default?
If you have ColdFusion installed and have your site configured to use ColdFusion, this handler will be installed to catch those requests. It's not related to SEO.
Wouldn't that mean requesting static files would also invoke this unnecessary handler?
Considering that it's a catch-all and defined as an ISAPI filter, all requests will go through it.

How to move pages around and rename them while not breaking incoming links from external sites that still use the poorly formed URLs

update
Here is the situation:
I'm working on a website that has no physical folder structure. Nothing had been planned or controlled and there were about 4 consecutive webmasters.
Here is an example of an especially ugly directory
\new\new\pasite-new.asp
most pages are stored in a folder with the same name as the file, for maximum redundancy.
\New\10cap\pasite-10cap.asp
\QL\Address\PAsite-Address.asp
each of these [page directories]? (I don't know what else to call them) has an include folder, the include folder contains the same *.inc files in every case, just copied about 162 times for each page directory. The include folder was duplicated so that the
<!--#include file="urlstring"--> would work correctly due to lack of understanding of relative paths, and the #inclue virtual directive or using server.execute()
Here is a picture if my explanation was lacking.
Here are some of my limitations:
The site is written in ASP classic
Server is Windows Server 2003 R2 SP2 , IIS 6 (According to my resource)
I have no access to the IIS server
I would have to go through a process to add any modules or features to iis
What changes can I make that would allow me to move pages around and rename them while not breaking incoming links from external sites that still use the poorly formed URLs?
To make my question more specific.
How can I move the file 10cap.asp from \new\10cap\ to a better location like \ and rename the file to someting like saveourhomescap.asp and not break any incoming links and finally, not have to leave a dummy 10cap.asp page in the original location with a redirect to the new page.
Wow, that's a lot of limitations to deal with.
Can you setup a custom error page? If so you can add some code into a custom error page that would redirect users to the new page. So maybe you create a custom 404 page, and in that page you grab the query string variable and based on that send the user to the correct "new" page. That would allow you to delete all of the old pages.
Here is a pretty good article on this method: URL Rewriting for Classic ASP
Well, you have a lot of limitations and especially no access to the IIS server hurts. An ISAPI module for URL rewriting is not an option here (IIS) and equally a custom 404 page where you could read the referer and forward with a HTTP 301 won't work (IIS).
I would actually recommend you to go through the process and let them install:
An ISAPI URL rewriting module
or if that doesn't work (for any reason):
Let them point the HTTP 404 of your web to a custom 404.asp, read the referer and redirect with a HTTP 301 (Moved Permanently) to your new location.
If none of this is an option for you, I can think about another possibility. I haven't actually tried that so I'm not 100% sure if it will work, but in theory it sounds good ;)
You could make in your global.asa in the Session_OnStart event a Response.Redirect or change the header of your response to a HTTP 301. This will actually only work for new users and not fix real 404 errors. Sorry, for the pseudo code, but it's a while ago that I had anything to do with classic ASP and I think you'll get what I mean ;)
sub Session_OnStart
' here should be a Select Case switch or something like that
Response.Redirect("newlocation.asp")
' or if that will work, this would be better (again with switch)
Response.Status = "301 Moved Permanently"
Response.AddHeader "Location", "http://company.com/newlocation.asp"
end sub
Hope that helps.
I recommend using URL Rewrite for that, see the following blog about it, in particular "Site Reorganization":
http://blogs.msdn.com/b/carlosag/archive/2008/09/02/iis7urlrewriteseo.aspx
For more info about URL Rewrite see: http://www.iis.net/download/URLRewrite
You can try ISAPIRewrite since it's classic ASP + IIS6
http://www.isapirewrite.com/
They have a lite version which is free, probably good enough for your use.
urlrewrite will only work if you can install a dll on the server
one of these articles will help
http://www.google.com/search?hl=en&client=firefox-a&rls=org.mozilla%3Aen-US%3Aofficial&hs=qRR&q=url+rewrite+classic+asp&btnG=Search&aq=f&oq=&aqi=g-m1
basically you have to point 404 errors to an error page which will parse the incoming querystring / post info and redirect user to correct location with incoming parameters added.
variations on that theme will be found in the examples fro google.

Can I have 'friendly' url's without a URL rewriter in IIS?

Without having a url rewriter such as ISAPI_Rewrite available, is it possible to achieve the following:
I would like a user to browse to http://www.jjj.com/directory where /directory does not actually exist. IIS transfers the user to not-found.cfm.
At this point I can serve index.cfm i.e. http://www.jjj.com/directory/index.cfm.
The url will display just fine and the page loads even though the directory or index.cfm doesn't exist. However I'd like to be able to not have index.cfm in the url.
Ideal:
Page Request to http://www.jjj.com/directory
IIS loads not-found.cfm as the default 404 errorhandler.
Not found strips the CGI.query_string and uses cfswitches to funnel the user to the appropriate controller function. May use onMissingTemplate?
The page request never changes in the URL and the page loads transparently the user with 200 OK status
If a user requests http://www.jjj.com/directory/index.cfm I would 301 redirect to http://www.jjj.com/directory
Current:
Page Request to http://www.jjj.com/directory
IIS loads not-found.cfm as default 404 error handler.
Not found strips the CGI.query_string and uses cfswitches to funnel the user to the appropriate controller function.
The page request changes to http://www.jjj.com/directory/index.cfm with a 200 OK status
You're asking how to cut something but telling us you're not allowed to use a knife or anything resembling one.
Here's my only clever idea using onMissingTemplate().
GET /directory/
-> 404.cfm
-> <cfinclude template="#cgi.script_name#/special.cfm" />
-> fires onMissingTemplate() where you ignore the "special.cfm" bit and just use the rest of the requested path to figure out what controller to wire up to.
This is a kludgy hack, though, so I would try to avoid it myself. Maybe if you explain why ISAPI Rewriting isn't an option, then we might be able to help further.
You can tell IIS to have 404 and 403 errors execute a custom URL on your site (such as /urlhandler.cfm).
Then, you can parse the 'cgi.query_string' and route the application anyway you desire using cfinclude to simply include the correct 'template.cfm', or, you can reformat the input your framework is expecting, or, use a project like http://coldcourse.riaforge.org/.
Just one note, IIS will give you a URL that looks like this: '404;http://yoursite.com/the/url/you/wanted/to/route'.
Is IIS7 on the approved list of software? That can get you native url rewriting and side-step the whole issue.
Second option -- my CFM voodoo is rusty, but I think you can setup IIS6 to look for a CFM page (like you are doing) but then step in at the application level and do the url rewriting/repointing before it actually hits the 404 page.
Another way around it -- find an ISAPI url rewriter that is, say, under the MIT license. Build your own copy. Then have them install that as part of your software package.

Resources