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

时间:2017-01-24 13:05:22

标签: 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 )
    } );
  }
}

如上所述hereColdFusion documentation

  

注意: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();

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

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

我可以这样做:

<cfscript>
Application.people = [];

people = new restmapping.test.People();

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

WriteDump( application.people );
</cfscript>

直接调用该函数,输出显示已添加该函数。但是,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>

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

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

1 个答案:

答案 0 :(得分:0)

@ MT0,

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

  1. remote void function create更改为remote struct function create
  2. 添加var result = {"status" = 201, "content" = SerializeJSON( people )}
  3. restSetResponse(..)来电更改为restSetResponse(result)
  4. 添加return result;
  5. *解决方案目前无效,b / c ColdFusion票证CF-3546046未完全修复。我已经要求Adobe重新打开它并提交CF-4198298以解决此问题,以防万一CF-3546046没有重新打开。请参阅我最近对CF-3546046的评论,并随时为这两张票投票。一旦完全修复,那么上面列出的代码更改将允许它在通过REST调用时设置正确的HTTP响应,并在直接调用时返回函数的返回变量。注意:如果您还想在直接调用函数时返回标题,还可以在步骤2中的headers结构中指定result结构。

    谢谢! -Aaron Neff