rest api with lucee and wrong errorcode from throw

281 views
Skip to first unread message

Stéphane MERLE

unread,
Oct 27, 2015, 11:35:33 AM10/27/15
to Lucee
Hi,

in my rest app, when I throw a custom error like this :


throw(errorCode="400", message="#erreurmsg#", detail="ERREUR 400 #erreurmsg# #serialize(ARGUMENTS)#");

I get a 500 error

500 Internal Server Error
with the correct message....

(so I don't think that the error is super catch and even so, the onerror function just log and do a rethrow())

anything I miss here ?

Stéphane

AJ Mercer

unread,
Oct 27, 2015, 6:53:26 PM10/27/15
to lu...@googlegroups.com
Not too sure what you are trying to do here,
but if you are using onerror in application.cfc - it does not work

Search this forum for previous discussions.
--
See Lucee at CFCamp Oct 22 & 23 2015 @ Munich Airport, Germany - Get your ticket NOW - http://www.cfcamp.org/
---
You received this message because you are subscribed to the Google Groups "Lucee" group.
To unsubscribe from this group and stop receiving emails from it, send an email to lucee+un...@googlegroups.com.
To post to this group, send email to lu...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/lucee/6798e78d-1c46-4f41-b657-16d13a7bc791%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


--

Stéphane MERLE

unread,
Oct 28, 2015, 3:54:54 AM10/28/15
to lu...@googlegroups.com


Le 27 oct. 2015 23:53, "AJ Mercer" <ajme...@gmail.com> a écrit :
>
> Not too sure what you are trying to do here,
> but if you are using onerror in application.cfc - it does not work

?
seems to work for me except that i cannot throw custom code ...
my instalation is on Ubuntu.  a nginx proxy send request to the lucee vm.

default install i think

throw function and 500 even with errorcode 400

i though that some catalina parameters where to blame.

Thanks for your help

Stéphane

> You received this message because you are subscribed to a topic in the Google Groups "Lucee" group.
> To unsubscribe from this topic, visit https://groups.google.com/d/topic/lucee/0v-pmUk8ipU/unsubscribe.
> To unsubscribe from this group and all its topics, send an email to lucee+un...@googlegroups.com.


> To post to this group, send email to lu...@googlegroups.com.

> To view this discussion on the web visit https://groups.google.com/d/msgid/lucee/CAPURtC34W-ZrCpFktJcO17u8BYCmm7inAoAyRt8VLyy9x2Gp4Q%40mail.gmail.com.

Jeroen Knoef

unread,
Oct 28, 2015, 5:59:26 AM10/28/15
to Lucee
If you throw an exception and don't catch it, that's an internal server error, so a 500 status is correct.
If you want a different status code, use: header statuscode="400" statustext="bad request";
You can do this inside onerror, just don't rethrow the exception.

Stéphane MERLE

unread,
Nov 3, 2015, 9:32:34 AM11/3/15
to Lucee
I did my own mythrow function and added it to the application scope :


public function mythrow(errorCode, detail) {
        writeLog(file="apidg_custom_error", text="ERREUR GENEREE #errorCode# : #detail#");
        header statusCode=errorCode statusText=detail;
        //pc = getpagecontext().getresponse();
        //pc.getresponse().setstatus(errorCode, detail);

        //getPageContext().getResponse().setstatus(errorCode, detail);

        exit method='exittag';

    }

so I call it like this : application.mythrow(errorCode='400', detail=erreurmsg);

my problem is with the exit ....
I have to exit from the request as an error occured but if I used exit or abort, I get a "Page request is aborted"
and if I use a return ... of course the script goes on but it's bad ..

How can I stop the process ?

I still need the header to be set with either solutions :
        header statusCode=errorCode statusText=detail;
        //pc = getpagecontext().getresponse();
        //pc.getresponse().setstatus(errorCode, detail);

        //getPageContext().getResponse().setstatus(errorCode, detail);


Thanks for your help !

Stéphane

Stéphane MERLE

unread,
Nov 3, 2015, 11:41:00 AM11/3/15
to Lucee
I did convert the whole application.cfc from cfscript to tag version, so my function looks now like this :

<cffunction name="mythrow" access="private" output="false" returntype="void">
       
<cfargument name="errorCode" type="numeric" default="500" />
       
<cfargument name="detail" type="string" required="true" hint="message to return to api consumer" />
       
<cfargument name="message" type="string" default="" />
       
<cfcontent reset="true" />
       
<cfif isdefined("arguments.message") and arguments.message neq "">
           
<cfset arguments.detail=arguments.detail & arguments.message>
       
</cfif>
       
<cfheader statuscode="#arguments.errorCode#" statustext="#arguments.detail#" />
       
<cfabort />
   
</cffunction>

but still I get a
Page request is aborted


help needed here ...

Stéphane

Jordan Michaels

unread,
Nov 3, 2015, 2:34:44 PM11/3/15
to lu...@googlegroups.com
Stéphane,

Maybe this is an issue with how the request is handled on it's way back from Lucee? IE: a reverse proxy issue?

So, if Lucee is throwing a 400 error and the request then goes through tomcat's web server to IIS or Apache, maybe IIS or Apache is interpreting the 400 error from Lucee and returning a 500 to the end user?

What happens if you remove the web server from your stack? Just hit the tomcat web server directly - usually on port 8888. Do you get a 400 error then?

Hope this helps.

-Jordan



----- Original Message -----
From: "Stéphane MERLE" <stephan...@gmail.com>
To: "Lucee" <lu...@googlegroups.com>
Sent: Tuesday, October 27, 2015 8:35:33 AM
Subject: [Lucee] rest api with lucee and wrong errorcode from throw

Hi,

in my rest app, when I throw a custom error like this :


throw(errorCode="400", message="#erreurmsg#", detail="ERREUR 400
#erreurmsg# #serialize(ARGUMENTS)#");

I get a 500 error

*500* Internal Server Error
with the correct message....

(so I don't think that the error is super catch and even so, the onerror
function just log and do a rethrow())

anything I miss here ?

Stéphane

AJ Mercer

unread,
Nov 3, 2015, 8:23:33 PM11/3/15
to lu...@googlegroups.com
have you seen this function?

    does not explain keys for the struct :-/

RestSetResponse(
    {
        "status":"#status#",
        "content":"#URL['callback']#(#serializeJSON(results)#)",
        "headers":{"Content-Type": "application/javascript"}}
);

pretty sure all keys are optional
    RestSetResponse({"status":"#status#"});

--
You received this message because you are subscribed to the Google Groups "Lucee" group.
To unsubscribe from this group and stop receiving emails from it, send an email to lucee+un...@googlegroups.com.
To post to this group, send email to lu...@googlegroups.com.

For more options, visit https://groups.google.com/d/optout.

Jon Clausen

unread,
Nov 3, 2015, 8:39:09 PM11/3/15
to Lucee
If you want to write the headers to the browser <cfflush> (or flush; in script) will force the currently defined headers to write.  Once you call abort; after that, your headers are already sent and may not be changed.

Frankly, though, you're better off implementing better error handling upstream and letting 500 errors be what they are: server errors.  If you want to deliver a 400 or 404, that should be determined before there is ever a chance to throw an exception.

Stéphane MERLE

unread,
Nov 4, 2015, 4:07:28 AM11/4/15
to Lucee


Le mardi 3 novembre 2015 20:34:44 UTC+1, Jordan Michaels a écrit :
Stéphane,

Maybe this is an issue with how the request is handled on it's way back from Lucee? IE: a reverse proxy issue?

So, if Lucee is throwing a 400 error and the request then goes through tomcat's web server to IIS or Apache, maybe IIS or Apache is interpreting the 400 error from Lucee and returning a 500 to the end user?

What happens if you remove the web server from your stack? Just hit the tomcat web server directly - usually on port 8888. Do you get a 400 error then?


I did try this but no ... still a 500 errorcode even for a 401 ... I was thinking that I've missed something in the tomcat catalina setup but I did remember adding a customerror param somewhere ...
 
this was a great idea thow ...

Stéphane

Stéphane MERLE

unread,
Nov 4, 2015, 4:16:16 AM11/4/15
to Lucee
Nice one !

I did try like this :

<cffunction name="mythrow" access="private" output="false" returntype="void">
       
<cfargument name="errorCode" type="numeric" default="500" />
       
<cfargument name="detail" type="string" required="true" hint="message to return to api consumer" />
       
<cfargument name="message" type="string" default="" />
       
<cfcontent reset="true" />
       
<cfif isdefined("arguments.message") and arguments.message neq "">
           
<cfset arguments.detail=arguments.detail & arguments.message>
       
</cfif>
       
<cfheader statuscode="#arguments.errorCode#" statustext="#arguments.detail#" />

       
<!--- <cfabort showerror="#arguments.errorCode# #arguments.detail#" /> --->
       
<cfscript>
            RestSetResponse({"status":"#arguments.errorCode# #arguments.detail#"});
       
</cfscript>
   
</cffunction>


but I think that the code is going thrue and then hit a real 500 error ....
if I add a cfabort after the </cfscript> I get :
Page request is aborted

Stéphane

Stéphane MERLE

unread,
Nov 4, 2015, 4:26:37 AM11/4/15
to Lucee


Le mercredi 4 novembre 2015 02:39:09 UTC+1, Jon Clausen a écrit :
If you want to write the headers to the browser <cfflush> (or flush; in script) will force the currently defined headers to write.  Once you call abort; after that, your headers are already sent and may not be changed.

you are right !! this did the trick :

    <cffunction name="mythrow" access="private" output="false" returntype="void">
       
<cfargument name="errorCode" type="numeric" default="500" />
       
<cfargument name="detail" type="string" required="true" hint="message to return to api consumer" />
       
<cfargument name="message" type="string" default="" />
       
<cfcontent reset="true" />
       
<cfif isdefined("arguments.message") and arguments.message neq "">
           
<cfset arguments.detail=arguments.detail & arguments.message>
       
</cfif>

       
<cfcontent reset="yes"><cfheader statuscode="#arguments.errorCode#" statustext="#arguments.detail#" /><cfflush /><cfabort showerror="#arguments.errorCode# #arguments.detail#" />
   
</cffunction>


 

Frankly, though, you're better off implementing better error handling upstream and letting 500 errors be what they are: server errors.  If you want to deliver a 400 or 404, that should be determined before there is ever a chance to throw an exception.


this is exactly what I try to do ...
when I do check the params I send back a 400 error with the message ... but I leave 500 catched error when there is a bug in my code ...

for example a part of my checks :

if (structkeyexists(application.bddinfos, ARGUMENTS.id_base) eq 0) {
   erreurmsg
="wrong id_base";
   writeLog
(file=application.logname_error, text="#GetFunctionCalledName()# #erreurmsg# #serialize(ARGUMENTS)#");
   application
.mythrow(errorCode="400", detail="ERREUR #erreurmsg# #serialize(ARGUMENTS)#");
}

And now, thanks to you, it's working ... I spent almost 3 days on that ...

THANKS !



 

Stéphane MERLE

unread,
Nov 4, 2015, 8:15:11 AM11/4/15
to Lucee
I try to build the API with those recommendations :

http://blog.octo.com/designer-une-api-rest/

and I see that I should send a 201 for a new POST ... so in fact I shouldn't send any RETURN to my functions ?
or should I catch the onRequestEnd to do like mythrow ?

it seem incredible that no one get stopped by those personnalisation statuscode ...

Stéphane

AJ Mercer

unread,
Nov 4, 2015, 9:12:30 AM11/4/15
to lu...@googlegroups.com
Status is just the code, Luce puts in the description for that code
--
Love Lucee? Become a supporter and be part of the Lucee project today! - http://lucee.org/supporters/become-a-supporter.html
---
You received this message because you are subscribed to the Google Groups "Lucee" group.
To unsubscribe from this group and stop receiving emails from it, send an email to lucee+un...@googlegroups.com.
To post to this group, send email to lu...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/lucee/ae314d35-ddd9-4e81-aedd-e6be6c3c9d46%40googlegroups.com.

For more options, visit https://groups.google.com/d/optout.

Stéphane MERLE

unread,
Nov 4, 2015, 9:26:39 AM11/4/15
to Lucee
I just added

header statuscode="201" statustext="Created";

before the return and it works great ...

the only concern I have now is with the "required" parameters ... if I miss one, the error code is throwned by lucee with errorcode 200 ....

I know  I can do it myself in the function and remove the required but still ... it's not using lucee the way it should ...

Thanks for your input !

Stéphane

Jon Clausen

unread,
Nov 4, 2015, 9:53:00 AM11/4/15
to lu...@googlegroups.com

Stéphane,

The main idea behind the REST spec for creation is that the response provides the URL of the new resource in the Location header. You may respond with an empty structure or provide a data response.

If you want the location header to be exposed to javascript for a cross-domain request, you will also need to add the following header

Access-Control-Expose-Headers: Location

A typical jQuery handling of that header would be:

      $.ajax({
   type: 'POST',
   url:'/api/v1/myhandler',
   data: formData,
   success: function(data, textStatus, request){
        var resource = request.getResponseHeader('location');
        $.get(resource).success(
                function(data){
                    return data;
                    }
            );
   }}
  });

This methodology requires two HTTP requests, which I dislike personally. There’s nothing in the spec that says you can’t respond with data and my personal preference is to respond with the data of the resource created, unless there is a specific reason not to do so (e.g. - the data marshalling for that resource response is done by a separate controller or other resource).

Here’s a good rundown on various thoughts to your question.

http://stackoverflow.com/questions/1829875/is-it-ok-by-rest-to-return-content-after-post

--

Love Lucee? Become a supporter and be part of the Lucee project today! - http://lucee.org/supporters/become-a-supporter.html
---
You received this message because you are subscribed to the Google Groups "Lucee" group.
To unsubscribe from this group and stop receiving emails from it, send an email to lucee+un...@googlegroups.com.
To post to this group, send email to lu...@googlegroups.com.

AJ Mercer

unread,
Nov 5, 2015, 4:03:17 AM11/5/15
to lu...@googlegroups.com

Stéphane MERLE

unread,
Nov 9, 2015, 3:17:05 AM11/9/15
to Lucee
Nice !
Reply all
Reply to author
Forward
0 new messages