获取RestSetResponse的输出而不发出HTTP请求

MT0*_*MT0 10 rest coldfusion

我有一个最小的(示例)REST端点test/people.cfc:

component
  restpath = "test/people/"
  rest     = true
{
  remote void function create(
    required  string   first_name restargsource = "Form",
    required  string   last_name  restargsource = "Form"
  )
    httpmethod  = "POST"
    restpath    = ""
    produces    = "application/json"
  {
    // Simulate adding person to database.
    ArrayAppend(
      Application.people,
      { "first_name" = first_name, "last_name" = last_name }
    );

    // Simulate getting people from database.
    var people = Application.people;

    restSetResponse( {
      "status"  = 201,
      "content" = SerializeJSON( people )
    } );
  }
}
Run Code Online (Sandbox Code Playgroud)

如此ColdFusion文档中所述:

注意:ColdFusion忽略函数的返回值,并使用函数使用响应集RestSetResponse().

因此,void函数的返回类型似乎对REST函数是正确的.

现在,我知道我可以使用以下命令从CFM页面调用它:

httpService = new http(method = "POST", url = "https://localhost/rest/test/people"); 
httpService.addParam( name = "first_name", type = "formfield", value = "Alice" ); 
httpService.addParam( name = "last_name",  type = "formfield", value = "Adams" ); 
result = httpService.send().getPrefix();
Run Code Online (Sandbox Code Playgroud)

但是,我想在不发出HTTP请求的情况下调用该函数.

首先,REST CFC似乎无法从REST目录中访问.这可以通过在ColdFusion管理面板中创建到REST服务的根路径的映射来简单地解决.

然后我可以这样做:

<cfscript>
Application.people = [];

people = new restmapping.test.People();

people.create( "Alice", "Adams" );

WriteDump( application.people );
</cfscript>
Run Code Online (Sandbox Code Playgroud)

这直接调用函数,输出显示它已添加了该函数.但是,REST功能的响应已经消失在以太网中.有谁知道是否有可能检索响应的HTTP状态代码和内容(至少是 - 最好是所有HTTP头)?

更新 - 集成测试场景:

这是一个用例(多个),其中通过HTTP请求调用REST端点具有连锁效应,可以通过直接调用端点作为组件的方法来缓解这种效应.

<cfscript>
// Create an instance of the REST end-point component without
// calling it via HTTP request.
endPoint = new restfiles.test.TestRESTEndPoint();

transaction {
  try {
    // Call a method on the end-point without making a HTTP request.
    endPoint.addValueToDatabase( 1, 'abcd' );
    assert( getRESTStatusCode(), 201 );
    assert( getRESTResponseText(), '{"id":1,"value":"abcd"}' );
    // Call another method on the end-point without making a HTTP request.
    endPoint.updateValueInDatabase( 1, 'dcba' );
    assert( getRESTStatusCode(), 200 );
    assert( getRESTResponseText(), '{"id":1,"value":"dcba"}' );
    // Call a third method on the end-point without making a HTTP request.
    endPoint.deleteValueInDatabase( 1 );
    assert( getRESTStatusCode(), 204 );
    assert( getRESTResponseText(), '' );
  }
  catch ( any e )
  {
    WriteDump( e );
  }
  finally
  {
    transaction action="rollback";
  }
}
</cfscript>
Run Code Online (Sandbox Code Playgroud)

通过HTTP请求调用每个REST函数将在每次请求之后将数据提交到数据库 - 在提交数据的测试之间进行清理会变得非常复杂并且经常导致需要将数据库闪回到先前的状态(导致集成)测试无法与闪回期间的任何其他测试和不可用时段并行运行.能够在不进行大量原子HTTP请求的情况下调用REST端点,而是将它们捆绑到可以回滚的单个事务中,这意味着可以在单个用户的会话中执行测试.

那么,如何获取在RestSetResponse()创建REST组件实例时直接调用表示REST路径的函数(不使用HTTP请求)时设置的HTTP状态代码和响应文本?

小智 1

@MT0,

该解决方案将*涉及几个步骤:

  1. 改成remote void function createremote struct function create
  2. 添加var result = {"status" = 201, "content" = SerializeJSON( people )}
  3. 将您的restSetResponse(..)通话更改为restSetResponse(result)
  4. 添加return result;

* 该解决方案当前不起作用,b/c ColdFusion 票证CF-3546046尚未完全修复。我已要求 Adob​​e 重新打开它,并提交了CF-4198298来修复此问题,以防 CF-3546046 未重新打开。请参阅我对 CF-3546046 的最新评论,并随时为任一票投票。一旦完全修复了其中一个问题,那么上面列出的对代码的更改将允许它在通过 REST 调用时设置正确的 HTTP 响应,并在直接调用时返回函数的返回变量。注意:如果您还想在直接调用函数时返回标头,则还可以在步骤 2 中的结构headers中指定一个结构。result

谢谢!-亚伦·内夫