【问题标题】:How do I return a status code error from a REST Service while using an OnError handler?如何在使用 OnError 处理程序时从 REST 服务返回状态代码错误?
【发布时间】:2021-05-17 18:26:19
【问题描述】:

我正在尝试使用 ColdFusion 10 设置一些 REST Web 服务,如果我在 Application.cfc 中有一个 onError 处理程序,则错误状态代码不会返回给消费者。

让我们考虑一下这个 Application.cfc

<cfcomponent displayname="ApplicationCFC" output="true" >
    <cfscript>
        this.name = "learnWith";
        this.applicationTimeout = createTimeSpan(1,1,0,0);
        this.sessionManagement = "false";
        this.restsettings.autoregister = true;
        this.restsettings.skipCFCWithError = true;
    </cfscript>

    <cffunction name="onApplicationStart" returntype="boolean" output="true">
        <cfset RestInitApplication(expandPath('/myDir'),"lw")>
        <cfreturn true>
    </cffunction>
</cfcomponent>

现在考虑服务,如下所示:

<cfcomponent rest="true" restpath="/user">
    <cffunction name="authenticate" access="remote" restpath="/login" returntype="String" httpmethod="POST"
            consumes="application/json" produces="application/json">
        <cfset requestData = getHTTPRequestData()>
        <cfset userInfo = deserializeJSON(ToString(requestData.content)) />

        <!--- cfquery to load user data ---->

        <cfif local.dataQuery.recordcount EQ 1>
            <cfset local.userVO = createObject()> <!--- create and populate userVo here --->
            <cfreturn SerializeJSON(local.userVO)>
        <cfelse>
            <!--- user not found, throw 401 error --->
            <cfthrow type="RestError" errorcode="401"  />
        </cfif>
    </cffunction>
</cfcomponent>

此代码在 Postman 中完美运行。如果我传入正确的凭据

{
    "userName": "user",
    "password": "hashedPassword
}

我按预期返回了一个用户对象,响应为 200。

如果我传递了虚假或无效的凭据:

{
    "userName": "fakeuser",
    "password": "fakePassword
}

我收到 401 错误:

太完美了。但是,我想为 CFC 使用全局错误处理程序,既用于基于非 REST 服务的代码,也用于记录可能的 REST 服务错误。如果我将其添加到 Application.cfc

    <cffunction name="onError" returnType="void" output="true">
        <cfargument name="exception" required="true">
        <cfargument name="eventname" type="string" required="true">
        <!--- error logging here --->
        <cfthrow type="RestError" errorcode="401" />
        <!--- or 
            <cfthrow type="#arguments.exception.Cause.Cause.type#" 
                     errorcode="#arguments.exception.Cause.Cause.code#">--->

    </cffunction>

ColdFusion 返回 500 内部服务器错误消息。

我在 CFC 方法和 onError 处理程序中都尝试了 cfheader:

<cfheader statusCode = "401" statusText = "RestError">

它将返回没有正文的 200 而不是 401 状态:

我已经尝试了各种迭代,但不知所措。我可以使用来自 ColdFusion 休息服务的状态代码,同时还有一个 onError 处理程序吗?如果有,怎么做?

【问题讨论】:

  • 我认为问题可能在于您的onError 方法&lt;cfthrow type="RestError" errorcode="401" /&gt; 中有此代码。要调用的 onError 方法已经发生错误,并且您正在从错误处理程序中抛出另一个错误。我认为您应该能够在 onError 方法中使用 &lt;cfheader statuscode="401" statustext="Unauthorized" /&gt; 来返回特定的 HTTP 状态代码。但不要使用cfthrow。至少不在onError 方法本身内。
  • @Miguel-F 如果我删除 cfthrow 并且有一个没有代码的 onError 方法,我仍然没有在服务器上返回 401。该解决方案似乎是使用restSetResponse() 发回响应而不使用 cfthrow 或返回项目。我会发布更深入的内容。
  • 您发布的答案是比引发错误更好的解决方案,但要明确的是,我并不是要您尝试没有代码的 onError 方法。你仍然需要我提到的&lt;cfheader ...&gt; 代码。无论如何,很高兴你能成功。
  • @Miguel-F cfheader 在使用 CF 的 REST API 时无论是在 onError 方法还是 CFC 方法中都没有影响。我在最初的问题中指出了这一点。

标签: rest coldfusion coldfusion-10 application.cfc


【解决方案1】:

我能够做我想做的事。我可以使用 restSetResponse 创建所需的响应,而不是使用 cfthrow 创建错误。

在 cffunction 内部,首先确保将返回类型设置为 void。

然后,您希望手动创建响应对象并使用restSetResponse 将其发回,而不是返回对象或使用 cfthrow。

这解决了我的问题:

<cfcomponent rest="true" restpath="/user">
    <cffunction name="authenticate" access="remote" restpath="/login" returntype="void" httpmethod="POST"
            consumes="application/json" produces="application/json">
        <cfset requestData = getHTTPRequestData()>
        <cfset userInfo = deserializeJSON(ToString(requestData.content)) />

        <!--- cfquery to load user data ---->

        <cfset local.result = structNew()/>

        <cfif local.dataQuery.recordcount EQ 1>
            <cfset local.userVO = createObject()> <!--- create and populate userVo here --->

            <cfset local.result.status = 200 />
            <cfset local.result.content = SerializeJSON(local.userVO) />
        <cfelse>
            <cfset local.result.status = 401 />
            <cfset local.result.content = SerializeJSON({message: 'User Not Authorized'}) />
        </cfif>

        <cfset restSetResponse(local.result) />
    </cffunction>
</cfcomponent>

一旦我这样做了,我就能够控制对消费者的响应,而无需触发Application.cfc 中的onError 方法。

【讨论】:

  • 谢谢,有帮助!
猜你喜欢
  • 2017-07-13
  • 2021-08-05
  • 1970-01-01
  • 2016-11-18
  • 2021-07-27
  • 1970-01-01
  • 2014-02-08
  • 1970-01-01
  • 2014-10-26
相关资源
最近更新 更多