hideo67
September 5, 2023, 6:45am
1
Hi
I’m working on a legacy app running on ColdFusion, and testing on Lucee to see if I can add REST apis for some of the features of the app.
I got the api working, but noticed that some of the REST features described in the ColdFusion documents seem not to work on Lucee. I want to know if these were intentionally dropped, or just happened to be overlooked.
subresource locators ( RESTful Web Services in ColdFusion (adobe.com) )
This allows to organize your REST code into a tree structure, and I think it is valuable.
automatic mapping from RestError exceptions to http response codes. ( RESTful Web Services in ColdFusion (adobe.com) )
I think this kind of mapping is widely available in REST frameworks. I found a thread on this forum dating back in 2018( Rest api with lucee and wrong errorcode from throw - dev / google-group-archive - Lucee Dev ), but nobody seems to mention this feature.
OS : Ubuntu22.04
Java Version : TemurinJDK 11
Tomcat Version : 9
Lucee Version : 6
hideo67
September 8, 2023, 1:33pm
2
For the automatic mapping of RestError
s, I reached a solution.
There is a try-catch in lucee.runtime.ComponentPageImpl.callRest() that catches exceptions raised from the user defined function.
Adding a catch clause as follows seems to work:
catch (CustomTypeException ce) {
ThreadLocalPageContext.getLog(pc, "rest").error("REST", ce);
if (ce.getCustomTypeAsString() == "RestError") {
try {
status = Integer.parseInt(ce.getErrorCode());
}
catch (NumberFormatException ne) {
status = 500;
}
RestUtil.setStatus(pc, status, ce.getMessage());
}
else {
throw ce;
}
}
The other mapping feature is obviously more complicated.
1 Like
hideo67
September 9, 2023, 7:04am
3
After fiddling for a couple of hours I got the subresource locator thing working.
For readers unfamiliar with ACF’s REST spec, subresource locators work as follows:
In one component, you define a remote function that declares a restpath but does not specify an HTTP method, and returns an instance of another component. That other component will be given the rest, eh… remainder of the URL (recursively) and handle the request.
In the following v1.cfc, an input path “http://hostname/rest/v1/book/123 ” will reach the subresource locator.
v1.cfc:
component restpath="/v1" rest="true" {
remote string function hello() restpath="hello" httpmethod="GET" {
return "hello";
}
/* subresource locator */
remote Book function book(string isbn restargsource="path") restpath="book/{isbn}" {
return new Book(isbn);
}
}
The subresource locator object will define remote methods.
Book.cfc:
component rest="true" {
public void function init(string isbn) {
this.isbn = isbn;
}
public string function title(string chapter restargsource="Path") restpath="title/{chapter}" httpmethod="GET" {
return "Humpty Dumpty - Chap. #chapter#., ISBN[#this.isbn#]";
}
}
When you access http://hostname/book/123-4567/title/3 you will get the result:
"Humpty Dumpty - Chap. 3., ISBN[123-4567]"
Along with the RestError mapping to HTTP responses, the required change is local to lucee.runtime.ComponentPageImpl.
Would the dev team be interested in incorporating this?
2 Likes
Sure, we are always open for contributions like this!
hideo67
September 9, 2023, 12:05pm
5
OK, I will first file a ticket to JIRA.
1 Like
hideo67
September 9, 2023, 1:02pm
6
Filed to JIRA and submitted a PR.
To test the code, you have to deploy a test app on a running Lucee server and access it with http.
I tested it locally of course, but is there an established way to handle such tests?
1 Like
thanks for another nice clean targeted PR!
We are currently in a feature freeze for the 6.0 release, I have added both your PRs to the 6.1 sprint.
One little thing, please add the PR link as a comment on the issue once you have created it