Skip to main content
I.am.Sceiffer
Participating Frequently
September 12, 2020
Question

REST API not working in ColdFusion 2018 running on IIS 10.0

  • September 12, 2020
  • 1 reply
  • 574 views

1) I installed IIS with ALL features and subfeatures;

 

2) I created the hosts generic.lab and api.generic.lab in hosts file then I created the sites (one for host) in IIS using defaultAppPool:

  1. a) the generic.lab was located in D:\websites\generic.lab\wwwroot
  2. b) the api.generic.lab was located in D:\websites\generic.lab\SubDomains\api

 

3) I installed ColdFusion 2018 developer mode in C:\ColdFusion at port 8594 with ALL features and ALL updates (from 1 through 10), then I ran the IIS_connector.bat in C:\ColdFusion\cfusion\bin\connectors;

 

4) I enabled the “Allow REST Discovery” in ColdFusion Administrator > Server Settings > Settings > API Manager Section;

 

5) In api.generic.lab site, I wrote the web.config:

<?xml version="1.0" encoding="UTF-8"?>

<configuration>

    <system.webServer>

        <httpProtocol>

            <customHeaders>

                <remove name="X-Powered-By" />

                <add name="Access-Control-Allow-Credentials" value="true" />

                <add name="Access-Control-Allow-Methods" value="GET, POST, PUT, HEAD, OPTIONS, DELETE" />

                <add name="Access-Control-Max-Age" value="600" />

                <add name="Access-Control-Allow-Origin" value="*" />

                <add name="Access-Control-Allow-Headers" value="x-requested-with, Content-Type, origin, authorization, accept, client-security-token" />

                <add name="Api-Version" value="2" />

            </customHeaders>

        </httpProtocol>

        <security>

            <requestFiltering>

                <verbs>

                    <add verb="PUT" allowed="true" />

                    <add verb="DELETE" allowed="true" />

                    <add verb="PATCH" allowed="true" />

                </verbs>

                <fileExtensions>

                    <add fileExtension=".cfm" allowed="true" />

                    <remove fileExtension=".cfm" />

                    <add fileExtension=".cfc" allowed="true" />

                    <remove fileExtension=".cfc" />

                </fileExtensions>

            </requestFiltering>

        </security>

        <defaultDocument>

            <files>

                <clear />

                <add value="index.cfm" />

            </files>

        </defaultDocument>

        <directoryBrowse enabled="true" />

        <urlCompression doStaticCompression="true" doDynamicCompression="true" />

        <handlers>

            <add name="asp_as_html" path="*.html" verb="*" modules="IsapiModule" scriptProcessor="%windir%\system32\inetsrv\asp.dll" />

            <add name="asp_as_htm" path="*.htm" verb="*" modules="IsapiModule" scriptProcessor="%windir%\system32\inetsrv\asp.dll" />

        </handlers>

        <httpErrors existingResponse="PassThrough" errorMode="Custom" />

    </system.webServer>

</configuration>

 

6) Then I wrote the application.cfc:

component output=true displayName='Application' hint='Application that uses global variables and manages accesses.'{

    this['name']='generic_api';

    this['applicationTimeout']=createTimeSpan(0,0,2,30);

    this['appBasePath']=expandPath('/');

    this['timeout']=900;

    this['enableRobustException']=true;

 

    this['sessionManagement']=false;

 

    this['passArrayByReference']=true;

    this['searchImplicitScopes']=false;

    this['enableNULLSupport']=true;

    this['sameFormFieldsAsArray']=true;

 

    this['scriptProtect']='all';

 

    this['secureJSON']=false;

    this['wsChannels']=[{'name'='w_generic'}];

 

    this['serialization']={

        'preserveCaseForStructKey'=true

    ,   'serializeQueryAs'='struct'

    ,   'preserveCaseForQueryColumn'=true

    };

 

    this['SMTPserverSettings']={

        'server'='smtp.sceiffer.com'

    ,   'username'='sceiffer@sceiffer.com'

    ,   'password'='Ah-Ah-Ah-you-didnt-say-the-magic-word'

    ,   'port'=465

    };

 

    setting enableCFoutputOnly=false showDebugOutput=false;

 

    public boolean function onApplicationStart(){

        application['s_dataSources']={

            's_dsn'={

                's_mssql'={

                    'dataSource'='generic_mssql'

                }

            ,   's_mysql'={

                    'dataSource'='generic_mysql'

                }

            }

        ,   's_qoq'={

                'DBType'='query'

            }

        };

        application['s_timeZone']={

            'v_UTC'=duplicate(getTimeZoneInfo()['utcTotalOffset'])

        ,   'v_local'=duplicate(getTimeZoneInfo()['utcTotalOffset'])*(-1)

        };

        application['s_smtp']=duplicate(this['SMTPserverSettings']);

        application['s_block']={

            'v_authentication'=3

        };

        local['a_restDirectories']=directoryList(path=expandPath('/rest/'),recurse=false,listInfo='path');

        if(yesNoFormat(arrayLen(local['a_restDirectories']))){

            local['i_directory']=0;

            for(local.i_directory in local.a_restDirectories){

                restInitApplication(local['i_directory'],listLast(local['i_directory'],'\'));

            }

        }

        return true;

    }

 

    public boolean function onMissingTemplate(required string targetPage){

        return true;

    }

 

    public boolean function onRequestStart(required string targetPage){

        return true;

    }

 

    public void function onRequest(required string targetPage){

        setLocale('Portuguese (Brazilian)');

        include arguments['targetPage'];

        return;

    }

 

    public void function onCFCRequest(string cfcname,string method,struct args){

        return;

    }

 

    public void function onAbort(required string targetPage){

        return;

    }

 

    public void function onRequestEnd(){

        return;

    }

 

    public void function onApplicationEnd(struct applicationScope={}){

        local['a_restDirectories']=directoryList(path=expandPath('/rest/'),recurse=false,listInfo='path');

        if(yesNoFormat(arrayLen(local['a_restDirectories']))){

            local['i_directory']=0;

            for(local.i_directory in local.a_restDirectories){

                restDeleteApplication(local['i_directory']);

            }

        }

        return;

    }

 

    public void function onError(required any exception,required string eventName){

        local['v_newFolder']=expandPath('/_src/_dbg/')&'_'&dateFormat(dateAdd('s',application['s_timeZone']['v_UTC'],now()),'yyyy-mm-dd');

        if(not(directoryExists(local['v_newFolder']))){

            directoryCreate(local['v_newFolder']);

        }

        local['q_listErrorFiles']=directoryList(path=local['v_newFolder'],listInfo='query');

        local['v_newFile']=timeFormat(dateAdd('s',application['s_timeZone']['v_UTC'],now()),'HH-mm-ss-lll');

        local['v_simultaneous']=0;

        local['s_query']={

            'v_sql'="

                select

                    1

                from [local].[q_listErrorFiles]

                where name=:v_errorFileName

                ;"

        ,   's_params'={

                'v_errorFileName'={

                    'cfsqltype'='cf_sql_varchar'

                ,   'value'='_'&local['v_newFile']&'_'&toString(numberFormat(local['v_simultaneous'],'000'))&'.html'

                }

            }

        };

        local['q_getErrorFile']=queryExecute(sql=local['s_query']['v_sql'],params=local['s_query']['s_params'],options=application['s_dataSources']['s_qoq']);

        while(local['q_getErrorFile'].recordCount>0){

            local['v_simultaneous']=local['v_simultaneous']+1;

            local['s_query']={

                'v_sql'="

                    select

                        1

                    from [local].[q_listErrorFiles]

                    where name=:v_errorFileName

                    ;"

            ,   's_params'={

                    'v_errorFileName'={

                        'cfsqltype'='cf_sql_varchar'

                    ,   'value'='_'&local['v_newFile']&'_'&toString(numberFormat(local['v_simultaneous'],'000'))&'.html'

                    }

                }

            };

            local['q_getErrorFile']=queryExecute(sql=local['s_query']['v_sql'],params=local['s_query']['s_params'],options=application['s_dataSources']['s_qoq']);

        }

        local['v_newFile']=local['v_newFolder']&'\'&'_'&local['v_newFile']&'_'&toString(numberFormat(local['v_simultaneous'],'000'))&'.html';

        fileWrite(local['v_newFile'],'','utf-8');

        writeDump(var=arguments,label='arguments',format='html',output=local['v_newFile']);

        if(isDefined('variables')){

            writeDump(var=variables,label='variables',format='html',output=local['v_newFile']);

        }

        writeDump(var=cgi,label='cgi',format='html',output=local['v_newFile']);

        writeDump(var=server,label='server',format='html',output=local['v_newFile']);

        if(isDefined('application')){

            writeDump(var=application,label='application',format='html',output=local['v_newFile']);

        }

        writeDump(var=cookie,label='cookie',format='html',output=local['v_newFile']);

        writeDump(var=url,label='url',format='html',output=local['v_newFile']);

        if(isDefined('form')){

            writeDump(var=form,label='form',format='html',output=local['v_newFile']);

        }

        return;

    }

}

 

7) At last, I wrote the firstObj.cfc in D:\websites\generic.lab\SubDomains\api\rest\firstAPI

component output=true rest=true restPath='firstObj'{

    remote any function firstGET() httpMethod='GET' restPath='firstGET' produces='application/json'{

        local['s_return']={

            'status'=200

        ,   'content'=serializeJSON(data={'response'='Oi!'},useSecureJSONPrefix=false,useCustomSerializer=false)

        };

        restSetResponse(local['s_return']);

    }

}

 

😎 To register the CFC as a REST Service, I created an index.cfm and ran it, then I visited the REST Services in ColdFusion Administrator > Data & Services to verify whether it appears and VOILA;

 

9) To run the firstGET function as REST, I put the cfhttp tag at index.cfm:

    cfhttp(method='GET',url='http://api.generic.lab/rest/firstAPI/firstObj/firstGET',port=80,charset='utf-8',result='variables.s_result');

    writeDump(var=variables.s_result);

 

10) The result was 404 NOT FOUND. I tested in REST Playground that comprehended the firstObj.cfc as located for 127.0.0.1:8594 host. The result was different: 204 NO RESPONSE; I changed the host to api.generic.lab in addres then the result came back to 404 NOT FOUND;

 

11) I modified the restInitApplication function, adding the options parameter after service mapping:

                restInitApplication(local['i_directory'],listLast(local['i_directory'],'\'),{

                    'skipCFCWithError'=false

                ,   'autoRegister'=true

                ,   'useHost'=true

                ,   'isDefault'=false

                });

 

12) I tried some options changing such as switching isDefault from FALSE to TRUE and adding host option, then I tried to run in REST Playground that removed firstAPI folder at REST Address. The result was the same 404 NOT FOUND for api.generic.lab;

 

13) I tried to modify the firstGET function switching from restSetResponse to return. The result was the same for 127.0.0.1:8594 (204 NO RESPONSE) and for api.generic.lab (404 NOT FOUND).

 

I really don’t know what to modify or start from the beginning. I just know I need a great support.

    This topic has been closed for replies.

    1 reply

    BKBK
    Community Expert
    Community Expert
    September 13, 2020

    Hi I_am_Sceiffer, please convert all your CFC code from cfscript format to tag format. I recently discovered a cfscript bug in ColdFusion. Occasionally, CFCs written in cfscript - particularly Application.cfc - do not behave as expected. See https://tracker.adobe.com/#/view/CF-4209174 

     

    This might or might not be the cause of your problem. But let's first get it out of the way.

     

    Sorry that my suggestion implies more work for you.