Callables to throw(#ewgi_context{})

0 views
Skip to first unread message

Mikael Karlsson

unread,
Nov 3, 2008, 5:28:45 AM11/3/08
to ew...@googlegroups.com
Hi,
would like to propose that callables should be able to throw #ewgi_context{} as well as to return them in order to handle exceptions. I hope it is a good idea, but not sure.
Implementation-wise I think this will only need minor modifications, in the ewgi_server callbacks. In ewgi_mochiweb.erl a couple of new lines would need to be added for instance:

run(MochiReq) ->
    try parse_arg(MochiReq) of
        Req when is_record(Req, ewgi_request) ->
            try process_application(ewgi_api:context(Req, ewgi_api:empty_response())) of
                not_found ->
                    MochiReq:not_found();
                Ctx when is_record(Ctx, ewgi_context) ->
                    handle_result(Ctx, MochiReq)
            catch
++            Ctx when is_record(Ctx, ewgi_context)  ->
++                 handle_result(Ctx, MochiReq)
                Reason ->
                    error_logger:error_report(Reason),
                    MochiReq:respond(?EWGI2MOCHI(?INTERNAL_SERVER_ERROR, []))
            end

.
.
Any comments?
Best regards
Mikael

Filippo Pacini

unread,
Nov 3, 2008, 7:22:09 AM11/3/08
to ew...@googlegroups.com
Mikael Karlsson wrote:
> Hi,
> would like to propose that callables should be able to throw
> #ewgi_context{} as well as to return them in order to handle exceptions.
> I hope it is a good idea, but not sure.
This would be the easiest way to escape a chain of calls.
E.g. if you have:
Result = app3(app2(app1(Ctx)))

and app1 or app2 needs to answer with a 50x code this is the easiest way
to send immediately the response.

Did you have a different use in mind?
Or has someone a cleaner solution to handle cases like this?

cheers,
filippo

Mikael Karlsson

unread,
Nov 3, 2008, 7:43:35 AM11/3/08
to ew...@googlegroups.com


2008/11/3 Filippo Pacini <filippo...@gmail.com>


This is the use I had in mind.
Is the example the same as lists:foldl( fun(A, Acc) -> A(Acc) end, Ctx, [app1,app2,app3]) by the way?

Quote from another thread:
In this way any "component" could throw an error, or break out with any other response. For instance an authentication module may rewrite the request and fill in the auth_type and remote_user* fields in the return value if it succeeds but throw an {401,"Unauthorized"} response (with WWW-authenticate headers) if it needs an authorization or if it fails. The other option is not to throw but to put the response into the return value - but that means that any other component coming next needs to be aware of this condition, and not proceed with its own stuff in case status code differs from 200 for instance.

Best regards
Mikael


Hunter Morris

unread,
Nov 3, 2008, 8:18:54 AM11/3/08
to ew...@googlegroups.com

I agree that throwing a context tuple is probably a more elegant
solution than trying to deal with the 'err' element of the
ewgi_response tuple. This is another case where EWGI differs
significantly from WSGI. I believe that the Python WSGI spec included
the exc_info argument in the start_response callable because there was
a possibility that output had already been sent to the browser when
the failure happened. Because we have a more functional approach with
applications simply returning a ewgi_context tuple, that approach
doesn't make sense.

Shall we get rid of the 'err' element of the tuple and rely instead on
Mikael's suggestion for error handling?

While on the subject of error handling, the other case that we haven't
discussed is if a stream throws an error while being evaluated. Take
this trivial example:

Stream = fun() -> {<<"chunk">>, fun() -> throw({error, foo}) end} end.

Should we leave it up to the server implementation to handle this
correctly? I think that is probably the simplest solution.

Best,
Hunter

Filippo Pacini

unread,
Nov 3, 2008, 8:54:57 AM11/3/08
to ew...@googlegroups.com
Hunter Morris wrote:
>
> I agree that throwing a context tuple is probably a more elegant
> solution than trying to deal with the 'err' element of the
> ewgi_response tuple. This is another case where EWGI differs
> significantly from WSGI. I believe that the Python WSGI spec included
> the exc_info argument in the start_response callable because there was
> a possibility that output had already been sent to the browser when
> the failure happened. Because we have a more functional approach with
> applications simply returning a ewgi_context tuple, that approach
> doesn't make sense.
Python uses the exception so middleware modules and applications can
"change their mind" on headers unless they have already been sent.
So if you get an error you can change the Status response, but as you
say this doesn't make sense in our case.

>
> Shall we get rid of the 'err' element of the tuple and rely instead on
> Mikael's suggestion for error handling?

Yes I think removing the error element shouldn't cause any trouble.

>
> While on the subject of error handling, the other case that we haven't
> discussed is if a stream throws an error while being evaluated. Take
> this trivial example:
>
> Stream = fun() -> {<<"chunk">>, fun() -> throw({error, foo}) end} end.
>
> Should we leave it up to the server implementation to handle this
> correctly? I think that is probably the simplest solution.

What is the correct way to handle an error during a chunked response?
We log the error, and send the last empty chunk?

best regards,
filippo

Reply all
Reply to author
Forward
0 new messages