3

I have been tasked with creating an API for our ColdFusion 8 based CMS system. After doing some research I decided that a RESTful API would be the best bet for three reasons:

  1. Its down right simple to use
  2. Fairly easy to implement
  3. Excellent long term solution

Seeing as I am first an foremost an application/systems programmer, high level web development is not my forte, so rather than reinventing the wheel I started looking at some frameworks for our API.

I settled on Taffy mainly because I found its design more elegant than PowerNap and FW/1, however I am having some trouble implementing it.

As per the documentation I have placed the unzipped "taffy" folder in our web root as well as created an api directory inside of our development site -

xxx.xxx.xxx.xxx/dev.cms/api_mk3

Inside are directories:

/resources/studentCollection.cfc
/resources/studentMember.cfc
/Application.cfc
/index.cfm

The contents of all four files are as follows:

studentCollection.cfc

<cfscript>
component extends="taffy.core.resource" taffy:uri="/students" {
    public function get() {
        //query the database for matches, making use of optional parameter "eyeColor" if provided
        //then...
        var someCollectionObject = ArrayNew(1);
        someCollectionObject[1] = "Jason Bristol";
        return representationOf(someCollectionObject).withStatus(200); //collection might be query, array, etc
    }
}
</cfscript>

studentMember.cfc

<cfscript>
component extends="taffy.core.resource" taffy:uri="/students/{personName}" {
    public function get(string personName) {
        //find the requested person, by name
        //then...
        return noData().withStatus(404);//representationOf(personName).withStatus(200); //member might be a structure, ORM entity, etc
    }
}
</cfscript>

Application.cfc

<cfcomponent extends="taffy.core.api">
<cfscript>

    this.name = 'CMS-API';

    variables.framework = {};
    variables.framework.debugKey = "debug";
    variables.framework.reloadKey = "reload";
    variables.framework.reloadPassword = "true";
    variables.framework.representationClass = "taffy.core.genericRepresentation";
    variables.framework.returnExceptionsAsJson = true;

    // do your onApplicationStart stuff here
    function applicationStartEvent() {
    }

    // do your onRequestStart stuff here
    function requestStartEvent() {
    }

    // this function is called after the request has been parsed and all request details are known
    function onTaffyRequest(verb, cfc, requestArguments, mimeExt) {
        // this would be a good place for you to check API key validity and other non-resource-specific validation
        return true;
    }

</cfscript>

index.cfm

Blank, as per the documentation.

The issue I am having is if I were to navigate to

xxx.xxx.xxx.xxx/dev.cms/api_mk3/index.cfm/students

I will get a 404

[14:57:02.963] GET http://xxx.xxx.xxx.xxx/dev.cms/api_mk3/index.cfm/students [HTTP/1.1 404 Not Found 56ms]

Request URL:
http://xxx.xxx.xxx.xxx/dev.cms/api_mk3/index.cfm/students


Request Method:
GET


Status Code:
HTTP/1.1 404 Not Found



Request Headers
14:57:02.000

User-Agent:Mozilla/5.0 (Windows NT 6.1; WOW64; rv:20.0) Gecko/20100101 Firefox/20.0
Host:xxx.xxx.xxx.xxx
Connection:keep-alive
Accept-Language:en-US,en;q=0.5
Accept-Encoding:gzip, deflate
Accept:text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8


Sent Cookie
CFTOKEN:85979056CFID:1194857



Response Headers
Δ56ms

X-Powered-By:ASP.NETServer:Microsoft-IIS/6.0
Date:Fri, 17 May 2013 18:57:37 GMT
Content-Type:text/html; charset=UTF-8
Connection:close

Now assuming I am understanding everything correctly, I should have a .json formatted response of "Jason Bristol" or something along those lines.

I suspect that there is an issue with MIME types or URL rewriting in IIS6, but I don't know the specifics on how to correct this. I have been pushing for an upgrade to Windows Server 2008 RC2 for quite some time now, but with no luck.

Is this operator error or is this fixable?

EDIT: I am getting nothing in the CF logs from what I can see. Below is the entry from the IIS Log:

2013-05-20 13:56:20 W3SVC4 10.40.204.236 GET /dev.cms/api_mk3/index.cfm/students - 80 - 70.88.47.65 Mozilla/5.0+(Windows+NT+6.1;+WOW64)+AppleWebKit/537.31+(KHTML,+like+Gecko)+Chrome/26.0.1410.64+Safari/537.31 404 0 0
Jason Bristol
  • 401
  • 1
  • 5
  • 19
  • Do you know if ColdFusion itself is working before trying to implement the framework? Can you surf to a CFM page in the root `xxx.xxx.xxx.xxx/index.cfm`? – Miguel-F May 17 '13 at 19:58
  • I can indeed, our CMS system is currently running without a hiccup on our ColdFusion 8 installation – Jason Bristol May 17 '13 at 20:06
  • Have you tried reinitializing Taffy by hitting the url `xxx.xxx.xxx.xxx/dev.cms/api_mk3/index.cfm?reload=true`? – Miguel-F May 17 '13 at 20:12
  • Just tried, still getting a 404 – Jason Bristol May 17 '13 at 20:30
  • Interestingly enough I also am finding that hitting xxx.xxx.xxx.xxx/dev.cms/api_mk3/index.cfm itself is giving a 404, however that file does in fact exist – Jason Bristol May 17 '13 at 20:46
  • I assume that you are getting the 404 from IIS. Can you check the ColdFusion logs to verify if the request is making it through or not? When you attempted the `?reload=true` did you get a 404 as well? – Miguel-F May 17 '13 at 20:48
  • Edit: I am not seeing anything in the CF logs, looks like it is stopping at ISS – Jason Bristol May 20 '13 at 13:51
  • I assume you meant IIS (not ISS). In IIS under the folder that you created (api_mk3) do you see the Handler Mappings for ColdFusion? Is the `.cfm` extension allowed? Is `index.cfm` the default document? – Miguel-F May 20 '13 at 14:33
  • .cfm is an allowed extension and index.cfm is in the default document list – Jason Bristol May 20 '13 at 14:58
  • What about the Handler Mappings? Do you see entries for `*.cfm`, `*.cfml`, and `*.cfc`? I would try a test by taking Taffy out of the equation. Rename the `Application.cfc` file under your "/dev.cms/api_mk3" folder and modify the `index.cfm` file to a "Hello World" ColdFusion template. Can you surf to `xxx.xxx.xxx.xxx/dev.cms/api_mk3/index.cfm` now? – Miguel-F May 20 '13 at 15:06
  • I have *.cfm, *.cfc, and *.cfml mapped, I renamed Application.cfc and modified index.cfm to print "Hello World" upon navigating to xxx.xxx.xxx.xxx/dev.cms/api_mk3/index.cfm I see "Hello World" printed to the screen with no errors. – Jason Bristol May 20 '13 at 15:14
  • Okay, well that tells us that ColdFusion is working down to that sub-folder. (I actually was not expecting that to work.) So it must be something in the Taffy setup (which I don't really know anything about). Since the `index.cfm` file is blank, it must be something in the `Application.cfc` file which extends the Taffy one. So I would start looking there. I did notice that your `studentMember.cfc` seems to be returning a 404 but you are not calling that one, right? This line: `return noData().withStatus(404);` – Miguel-F May 20 '13 at 15:22
  • Correct, studentMember.cfc is not being used right now. I did a little digging into taffy myself. /dev.cms/taffy/core/dashboard.cfm should bring me to a taffy dashboard where I can configure settings however when I navigate to this page I receive an error "Element _TAFFY.ENDPOINTS is undefined in APPLICATION." Starting to think there are some issues inside the taffy directory. Will continue to test and see what I come up with – Jason Bristol May 20 '13 at 15:28

2 Answers2

1

This is a known issue on plain vanilla installations on tomcat. (If you use tomcat?)

You could add an additional servlet mapping in your web.xml file.

<servlet-mapping>
    <servlet-name>CFMLServlet</servlet-name>
    <url-pattern>/api/index.cfm/*</url-pattern>
</servlet-mapping>

https://github.com/atuttle/Taffy/wiki/404-issue-with-Railo-or-Tomcat-and-API-in-a-sub-folder

Thorsten
  • 223
  • 3
  • 13
-1

This:

xxx.xxx.xxx.xxx/dev.cms/api_mk3/index.cfm/students

does not look like a valid url. index.cfm is a web page so adding directories after it does not make sense. If students is a subfolder, you want something like this:

xxx.xxx.xxx.xxx/dev.cms/api_mk3/students

If there is an index or default file in that folder, it should come up. Otherwise you have to specify a file in that folder.

Dan Bracuk
  • 20,699
  • 4
  • 26
  • 43
  • As per https://github.com/atuttle/Taffy/wiki/Getting-Started "Assuming your API is located at http://example.com/api/index.cfm, and you've implemented the resource with URI /products and the GET method, then you could open up the URL: http://example.com/api/index.cfm/products in your browser and the data would be returned, serialized using the default mime type (JSON unless otherwise defined)" From what I understand this URL format is how to access the API – Jason Bristol May 17 '13 at 19:29