Fan

 

abstract const class

web::WebService

sys::Obj
  web::WebService : sys::Service
//
// Copyright (c) 2007, Brian Frank and Andy Frank
// Licensed under the Academic Free License version 3.0
//
// History:
//   21 Dec 07  Brian Frank  Creation
//

**
** WebService defines the standard service interface
** for all Fan based web servers.
**
** See [docLib::Web]`docLib::Web#webServices`
**
abstract const class WebService : Service
{

//////////////////////////////////////////////////////////////////////////
// Pipeline
//////////////////////////////////////////////////////////////////////////

  **
  ** The pipeline field stores a series of WebSteps which
  ** are processed in sequence to service a web request.
  **
  ** See [docLib::Web]`docLib::Web#pipeline`
  **
  const WebStep[] pipeline

  **
  ** Service the specified web request with the configured
  ** pipeline.  Any exceptions raised by a step, are propagated
  ** to the caller - internal errors should be handled by
  ** subclasses.  If `WebRes.done` is called, then the pipeline
  ** is terminated.
  **
  virtual Void service(WebReq req, WebRes res)
  {
    // init thread locals
    Actor.locals["web.req"] = req
    Actor.locals["web.res"] = res
    try
    {
      // if pipeline is empty
      if ((Obj?)pipeline == null || pipeline.isEmpty)
        throw Err("Must set WebService.pipeline")

      // onBeforeService
      pipeline.each |WebStep step|
      {
        try { step.onBeforeService(req, res) } catch (Err e) { log.error("BeforeService $step.type", e) }
      }

      // process each step unless done
      pipeline.each |WebStep step|
      {
        if (!res.isDone) step.service(req, res)
      }

      // onAfterService
      pipeline.each |WebStep step|
      {
        try { step.onAfterService(req, res) } catch (Err e) { log.error("AfterService $step.type", e) }
      }
    }
    finally
    {
      // save session if accessed
      sessionMgr.save

      // cleanup thread locals
      Actor.locals.remove("web.req")
      Actor.locals.remove("web.res")
    }
  }

//////////////////////////////////////////////////////////////////////////
// Threading
//////////////////////////////////////////////////////////////////////////

  **
  ** Subclasses must call super if overridden.
  **
  protected override Void onStart()
  {
    pipeline.each |WebStep step|
    {
      try { step.onStart(this) } catch (Err e) { log.error("Starting $step.type", e) }
    }
  }

  **
  ** Subclasses must call super if overridden.
  **
  protected override Void onStop()
  {
    pipeline.each |WebStep step|
    {
      try { step.onStop(this) } catch (Err e) { log.error("Stopping $step.type", e) }
    }
    sessionMgr.stop
  }

//////////////////////////////////////////////////////////////////////////
// Fields
//////////////////////////////////////////////////////////////////////////

  ** Standard log for web service
  static const Log log := Log.get("web")

  ** Session management thread
  internal const WebSessionMgr sessionMgr := WebSessionMgr()


}