Logo Search packages:      
Sourcecode: parser version File versions  Download package

void Request::core ( const char *  config_filespec,
bool  config_fail_on_read_problem,
bool  header_only 
)

core request processing

BEWARE: may throw exception to you: catch it!

load MAIN class, execute . MAIN class consists of all the auto.p files we'd manage to find plus the file user requested us to process all located classes become children of one another, composing class we name 'MAIN'

Test:
log stack trace
Parameters:
config_filespec  system config filespec
config_fail_on_read_problem  fail if system config file not found

Definition at line 301 of file pa_request.C.

References String::append(), String::append_help_length(), String::append_strdup(), Value::as_bool(), VString::as_vfile(), Value::as_vfile(), Hash< K, V >::clear(), Request_info::document_root, exception_trace, execute_method(), execute_virtual_method(), VResponse::fields(), file_list, VMail::fill_received(), flang, Hash< K, V >::get(), VStateless_class::get_element(), Value::get_string(), Value::is_string(), String::L_CLEAN, String::L_TAINTED, String::L_UNSPECIFIED, SAPI::log(), mail, main_class, Request_info::path_translated, Hash< K, V >::put(), request_info, response, sapi_info, VMethodFrame::set_self(), VMethodFrame::store_param(), UNHANDLED_EXCEPTION_CONTENT_TYPE, Request_info::uri, and use_file().

Referenced by real_parser_handler().

                                                                                                  {
#ifdef RESOURCES_DEBUG
//measures
struct timeval mt[10];
//measure:before all
gettimeofday(&mt[0],NULL);
#endif
      try {
            // filling mail received
            mail.fill_received(*this);

            // loading config
            if(config_filespec) {
                  const String& filespec=*new String(config_filespec);
                  use_file(main_class,
                        filespec, 0 /*main_alias*/, 
                        true /*ignore class_path*/, 
                        config_fail_on_read_problem, 
                        true /*file must exist if 'fail on read problem' not set*/);
            }

            // loading auto.p files from document_root/.. 
            // to the one beside requested file.
            // all assigned bases from upper dir
            {
                  const char* after=request_info.path_translated;
                  size_t drlen=strlen(request_info.document_root);
                  if(memcmp(after, request_info.document_root, drlen)==0) {
                        after+=drlen;
                        if(after[-1]=='/') 
                              --after;
                  }
                  
                  while(const char* before=strchr(after, '/')) {
                        String& sfile_spec=*new String;
                        if(after!=request_info.path_translated) {
                              sfile_spec.append_strdup(
                                    request_info.path_translated, before-request_info.path_translated,
                                    String::L_CLEAN);
                              sfile_spec << "/" AUTO_FILE_NAME;

                              use_file(main_class,
                                    sfile_spec, 
                                    0 /*main_alias*/,
                                    true /*ignore class_path*/, 
                                    true /*fail on read problem*/, 
                                    false /*but ignore absence, sole user*/);
                        }
                        after=before+1;
                  }
            }

            try {
                  // compile requested file
                  String& spath_translated=*new String;
                  spath_translated.append_help_length(request_info.path_translated, 0, String::L_TAINTED);
                  use_file(main_class,
                        spath_translated, 
                        0 /*main_alias*/,
                        true /*ignore class_path*/);

                  configure();
            } catch(...) {
                  configure(); // configure anyway, useful in @unhandled_exception [say, if they would want to mail by SMTP something]
                  rethrow;
            }

#ifdef RESOURCES_DEBUG
//measure:after compile
gettimeofday(&mt[1],NULL);
#endif
            // execute @main[]
            const String* body_string=execute_virtual_method(main_class, main_method_name);
            if(!body_string)
                  throw Exception(PARSER_RUNTIME,
                        0,
                        "'"MAIN_METHOD_NAME"' method not found");

#ifdef RESOURCES_DEBUG
            //measure:after main
gettimeofday(&mt[2],NULL);
#endif

            // extract response body
            Value* body_value=response.fields().get(download_name); // $response:download?
            bool as_attachment=body_value!=0;
            if(!body_value)
                  body_value=response.fields().get(body_name); // $response:body
            if(!body_value)
                  body_value=new VString(*body_string); // just result of ^main[]
            // ensure that body_value has no just L_TAINTED parts left
            if(body_value->is_string())
            {
                  String& untainted=*new String();
                  untainted.append(*body_value->get_string(), flang);
                  body_value=new VString(untainted);
            }

            // @postprocess
            if(Value* value=main_class.get_element(post_process_method_name, main_class, false))
                  if(Junction* junction=value->get_junction())
                        if(const Method *method=junction->method) {
                              // preparing to pass parameters to 
                              //    @postprocess[data]
                              VMethodFrame frame(/*method->name, */ *junction, 0/*no parent*/);
                              frame.set_self(main_class);

                              frame.store_param(*body_value);
                              body_value=&execute_method(frame, *method).as_value();
                        }

            VFile* body_file=body_value->as_vfile(
                  String::L_UNSPECIFIED, &charsets);

#ifdef RESOURCES_DEBUG
//measure:after postprocess
gettimeofday(&mt[3],NULL);          
#endif

            // OK. write out the result
            output_result(body_file, header_only, as_attachment);

#ifdef RESOURCES_DEBUG
            //measure:after output_result
gettimeofday(&mt[9],NULL);          
t[9]=mt[9].tv_sec+mt[9].tv_usec/1000000.0;

double t[10];
for(int i=0;i<10;i++)
    t[i]=mt[i].tv_sec+mt[i].tv_usec/1000000.0;
//measure:log2 compile,main,postprocess,output
SAPI::log("rmeasure: %s,%.2f,%.2f,%.2f %.2f,%.2f %.2f", 
request_info.uri,
t[1]-t[0],
t[2]-t[1],
t[3]-t[2],
sql_connect_time,sql_request_time,
t[9]-t[3]
);
#endif
      } catch(const Exception& e) { // request handling problem
            try {
            // we're returning not result, but error explanation

            Request::Exception_details details=get_details(e);
            const char* exception_cstr=get_exception_cstr(e, details);

            // reset language to default
            flang=fdefault_lang;
            
            // reset response
            response.fields().clear();

            // this is what we'd return in $response:body
            const String* body_string=0;

            // maybe we'd be lucky enough as to report an error
            // in a gracefull way...
            if(Value* value=main_class.get_element(
                        *new String(UNHANDLED_EXCEPTION_METHOD_NAME), 
                        main_class,
                        false)) {
                  if(Junction* junction=value->get_junction()) {
                        if(const Method *method=junction->method) {
                              // preparing to pass parameters to 
                              //    @unhandled_exception[exception;stack]
                              VMethodFrame frame(/*method->name, */ *junction, 0/*no caller*/);
                              frame.set_self(main_class);

                              // $exception
                              frame.store_param(details.vhash);
                              // $stack[^table::create{name file  lineno      colno}]
                              Table::columns_type stack_trace_columns(new ArrayString);
                              *stack_trace_columns+=new String("name");
                              *stack_trace_columns+=new String("file");
                              *stack_trace_columns+=new String("lineno");
                              *stack_trace_columns+=new String("colno");
                              Table& stack_trace=*new Table(stack_trace_columns);
                              if(!exception_trace.is_empty()/*signed!*/) 
                                    for(size_t i=exception_trace.bottom_index(); i<exception_trace.top_index(); i++) {
                                          Trace trace=exception_trace.get(i);
                                          Table::element_type row(new ArrayString);

                                          *row+=trace.name(); // name column
                                          Operation::Origin origin=trace.origin();
                                          if(origin.file_no) {
                                                *row+=new String(file_list[origin.file_no], String::L_TAINTED); // 'file' column
                                                *row+=new String(String::Body::Format(1+origin.line), String::L_CLEAN); // 'lineno' column
                                                *row+=new String(String::Body::Format(1+origin.col), String::L_CLEAN); // 'colno' column
                                          }
                                          stack_trace+=row;
                                    }

                              frame.store_param(*new VTable(&stack_trace));

                              // future $response:body=
                              //   execute ^unhandled_exception[exception;stack]
                              exception_trace.clear(); // forget all about previous life, in case there would be error inside of this method, error handled  would not be mislead by old stack contents (see extract_origin)
                              body_string=&execute_method(frame, *method).as_string();
                        }
                  }
            }
            
            if(!body_string) {  // couldn't report an error beautifully?
                  // doing that ugly

                  // future $response:content-type
                  response.fields().put(content_type_name, 
                        new VString(*new String(UNHANDLED_EXCEPTION_CONTENT_TYPE)));
                  // future $response:body
                  body_string=new String(exception_cstr);
            }

            VString body_vstring(*body_string);
            VFile* body_file=body_vstring.as_vfile(String::L_UNSPECIFIED, &charsets);

            // conditionally log it
            Value* vhandled=details.vhash.hash().get(exception_handled_part_name);
            if(!vhandled || !vhandled->as_bool()) {
                  SAPI::log(sapi_info, "%s", exception_cstr);
            }

            // ERROR. write it out
            output_result(body_file, header_only, false);

            } catch(const Exception& e) { // exception in unhandled exception
                  Request::Exception_details details=get_details(e);
                  const char* exception_cstr=get_exception_cstr(e, details);
                  // unconditionally log the beast
                  SAPI::log(sapi_info, "%s", exception_cstr);

                  throw Exception(0,
                        0,
                        "in %s", 
                              exception_cstr);
            }
      }
}


Generated by  Doxygen 1.6.0   Back to index