2121#include < booster/log.h>
2222#include < booster/backtrace.h>
2323#include < booster/aio/io_service.h>
24+ #include < cppcms/http_content_filter.h>
2425
2526#include " cached_settings.h"
2627
@@ -38,6 +39,9 @@ namespace http {
3839 std::auto_ptr<http::response> response;
3940 std::auto_ptr<cache_interface> cache;
4041 std::auto_ptr<session_interface> session;
42+ booster::shared_ptr<application_specific_pool> pool;
43+ booster::intrusive_ptr<application> app;
44+ std::string matched;
4145 _data (context &cntx) :
4246 locale (cntx.connection().service().locale()),
4347 request (cntx.connection())
@@ -120,6 +124,20 @@ namespace {
120124 }
121125
122126 };
127+
128+ class context_guard {
129+ public:
130+ context_guard (cppcms::application &app,cppcms::http::context &ctx) : app_(&app)
131+ {
132+ app_->add_context (ctx);
133+ }
134+ ~context_guard ()
135+ {
136+ app_->remove_context ();
137+ }
138+ private:
139+ cppcms::application *app_;
140+ };
123141}
124142
125143
@@ -167,10 +185,27 @@ void context::submit_to_pool_internal(booster::shared_ptr<application_specific_p
167185 }
168186}
169187
170- void context::on_request_ready ( bool error )
188+ int context::translate_exception ( )
171189{
172- if (error) return ;
190+ try {
191+ throw ;
192+ }
193+ catch (abort_upload const &e) {
194+ return e.code ();
195+ }
196+ catch (std::exception const &e) {
197+ make_error_message (e);
198+ return 500 ;
199+ }
200+ catch (...) {
201+ BOOSTER_ERROR (" cppcms" ) << " Unknown exception" ;
202+ return 500 ;
203+ }
204+ return 0 ;
205+ }
173206
207+ int context::on_headers_ready (bool has_content)
208+ {
174209 char const *host = conn_->cgetenv (" HTTP_HOST" );
175210 char const *path_info = conn_->cgetenv (" PATH_INFO" );
176211 char const *script_name = conn_->cgetenv (" SCRIPT_NAME" );
@@ -183,15 +218,94 @@ void context::on_request_ready(bool error)
183218 path_info,
184219 matched
185220 );
221+ if (!pool)
222+ return 404 ;
223+
224+ int flags;
225+ if (!has_content || ((flags=pool->flags ()) & app::op_mode_mask) == app::synchronous || (flags & app::content_filter)==0 ) {
226+ d->pool .swap (pool);
227+ d->matched .swap (matched);
228+ return 0 ;
229+ }
230+
231+ booster::intrusive_ptr<application> app = d->pool ->get (service ());
232+ if (!app)
233+ return 500 ;
234+
235+ try {
236+ context_guard g (*app,*this );
237+ app->main (matched);
238+ }
239+ catch (...) {
240+ return translate_exception ();
241+ }
242+ d->pool .swap (pool);
243+ d->app .swap (app);
244+ d->matched .swap (matched);
245+ return 0 ;
246+ }
247+
248+ bool context::has_file_filter ()
249+ {
250+ return dynamic_cast <multipart_filter *>(request ().content_filter ())!=0 ;
251+ }
252+ int context::send_to_file_filter (file &f,int stage)
253+ {
254+ try {
255+ context_guard g (*d->app ,*this );
256+ multipart_filter *filter=static_cast <multipart_filter *>(request ().content_filter ());
257+ switch (stage) {
258+ case 0 : filter->on_new_file (f); break ;
259+ case 1 : filter->on_upload_progress (f); break ;
260+ case 2 : filter->on_data_ready (f); break ;
261+ }
262+ }
263+ catch (...) {
264+ return translate_exception ();
265+ }
266+ return 0 ;
267+ }
186268
187- if (!pool) {
188- response ().io_mode (http::response::asynchronous);
189- response ().make_error_response (http::response::not_found);
190- async_complete_response ();
269+ void context::on_request_ready (bool error)
270+ {
271+ booster::shared_ptr<application_specific_pool> pool;
272+ booster::intrusive_ptr<application> app;
273+ pool.swap (d->pool );
274+ app.swap (d->app );
275+ basic_content_filter *filter = 0 ;
276+
277+ if (error && app && (filter=request ().content_filter ())!=0 ) {
278+ context_guard g (*app,*this );
279+ try {
280+ filter->on_error ();
281+ }
282+ catch (...) {}
191283 return ;
192284 }
193285
194- submit_to_pool_internal (pool,matched,true );
286+ if (error)
287+ return ;
288+
289+ request ().set_ready ();
290+
291+ if (app && filter) {
292+ context_guard g (*app,*this );
293+ try {
294+ filter->on_end_of_content ();
295+ }
296+ catch (...) {
297+ translate_exception ();
298+ return ;
299+ }
300+ }
301+
302+ if (app) {
303+ app->assign_context (self ());
304+ dispatch (app,d->matched ,false );
305+ return ;
306+ }
307+
308+ submit_to_pool_internal (pool,d->matched ,true );
195309}
196310
197311namespace {
@@ -226,6 +340,21 @@ void context::dispatch(booster::shared_ptr<application_specific_pool> const &poo
226340 app->assign_context (self);
227341 dispatch (app,url,true );
228342}
343+
344+ void context::make_error_message (std::exception const &e)
345+ {
346+ BOOSTER_ERROR (" cppcms" ) << " Caught exception [" <<e.what ()<<" ]\n " << booster::trace (e) ;
347+ if (!response ().some_output_was_written ()) {
348+ if (service ().cached_settings ().security .display_error_message ) {
349+ std::ostringstream ss;
350+ ss << e.what () << ' \n ' ;
351+ ss << booster::trace (e);
352+ response ().make_error_response (http::response::internal_server_error,ss.str ());
353+ }
354+ else
355+ response ().make_error_response (http::response::internal_server_error);
356+ }
357+ }
229358// static
230359void context::dispatch (booster::intrusive_ptr<application> const &app,std::string const &url,bool syncronous)
231360{
@@ -248,20 +377,9 @@ void context::dispatch(booster::intrusive_ptr<application> const &app,std::strin
248377 app->response ().make_error_response (http::response::forbidden);
249378 }
250379 }
251- catch (std::exception const &e){
252- BOOSTER_ERROR (" cppcms" ) << " Caught exception [" <<e.what ()<<" ]\n " << booster::trace (e) ;
253- if (app->get_context ()) {
254- if (!app->response ().some_output_was_written ()) {
255- if (app->service ().cached_settings ().security .display_error_message ) {
256- std::ostringstream ss;
257- ss << e.what () << ' \n ' ;
258- ss << booster::trace (e);
259- app->response ().make_error_response (http::response::internal_server_error,ss.str ());
260- }
261- else
262- app->response ().make_error_response (http::response::internal_server_error);
263- }
264- }
380+ catch (...){
381+ if (app->get_context ())
382+ app->context ().translate_exception ();
265383 }
266384
267385 if (app->get_context ()) {
0 commit comments