vibe-d / vibe.d

Official vibe.d development
MIT License
1.15k stars 284 forks source link

Throwing exceptions in diet templates #677

Open w0rp opened 10 years ago

w0rp commented 10 years ago

Suppose you have this code in a diet template.

p Some text.
|!= thisWillThrow();
p Some more text.

Currently, this will abort writing the document, but then proceed to display everything written up to that point in the browser, and I couldn't easily find a way to look at the exception.

I think there should be some kind of mechanism for catching exceptions thrown in this way and propagating them like exceptions in the router functions. Most importantly, you shouldn't be able to view the page if an exception is thrown in the middle of processing it.

s-ludwig commented 10 years ago

But at that point, half of the page is already written to the connection. The only way to continue would be to wrap every single D statement or expression in try/catch and then do something weird, like using default values and skipping statements when an exception is thrown. Among other things, that would be a performance disaster. AFAICS, logging the exception server side is the best option in this case (which is already done here). Or do you have a specific idea how to handle this?

etcimon commented 10 years ago

You could make the functions nothrow prior to using them in diet templates, and choose another way of reporting failures by wrapping it in a try / catch that writes an error report inside a div

w0rp commented 10 years ago

Is it completely impossible to make it so that exceptions which occur in the middle of templates abort writing the document and then don't return any HTML output from before?

s-ludwig commented 10 years ago

It would have to cache the page in memory for that to work. It's possible to do that by calling compileDietFile on a MemoryOutputStream and then writing the result at once, but it trades in higher memory use and performance for this.

etcimon commented 10 years ago

I have to say, always using a chunked stream isn't recommended because the content length should always be known for http good practice by defining the header, so it would eventually be necessary to have a contentLengthOutputStream which is built on top of an appender

s-ludwig commented 10 years ago

In that case: MemoryOutputStream - There is also a pending optimization to write a non-chunked response whenever the page is smaller than the chunked stream output buffer size. However, I see no reason why a chunked output stream shouldn't be used for a live generated HTML page. It surely isn't good for binary downloads and the like, but it's especially meant for occasions like here.

etcimon commented 10 years ago

Yes, in most cases chunked output is the ideal choice but a content-length capable http stream would also be more transactional which is useful in this case could allow to disable the TCP implementation of nagle's algorithm if used site-wide.

s-ludwig commented 10 years ago

The buffer size of the chunked stream could also be tuned (MTU - header_size) to make TCP-nodelay just as efficient.

gronka commented 9 years ago

I just knocked into this.

If a change would hurt performance or complexity much, I'd opt to leave it as is. However, perhaps a good option would be to have a simple wrapper for

- static if (is(typeof(variable)))
!= variable

Maybe something like #!{variable}. I'd like to write an associative array class that returns "" if the key is not located.

Regardless, I think it would be nice to add a list of "common gotchas" on http://vibed.org/templates/diet, or linking to an external list somewhere on that page.