REST service example

In this example, the REST service returns an HTTP error code 404 to the browser until the query string contains the string ByPass.

When the GWC application is started, the parameter ACCESS is also set and can be retrieved in the Genero program with fgl_getenv("ACCESS").

IMPORT COM
IMPORT XML

PRIVATE CONSTANT C_BASEURL = "/ws/r/qa-test/delegateService/"
PRIVATE CONSTANT C_X_FOURJS_ENVIRONEMENT_ = "X-FourJs-Environment-"
PRIVATE CONSTANT C_X_FOURJS_ENVIRONEMENT_PARAMETER_ =
  "X-FourJs-Environment-Parameter-"
PRIVATE CONSTANT C_GENERO_INTERNAL_DELEGATE = "_GENERO_INTERNAL_DELEGATE_"

MAIN
  DEFINE  req   com.HttpServiceRequest
  DEFINE  methd STRING
  DEFINE  url   STRING
  DEFINE  path  STRING
  DEFINE  query STRING 
  DEFINE  ind   INTEGER 
  DEFINE  tmp   STRING 
   
  CALL com.WebServiceEngine.Start()

  WHILE TRUE
    TRY
      LET req = com.WebServiceEngine.GetHttpServiceRequest(-1)
      IF req IS NULL THEN
        EXIT WHILE
      ELSE
        LET url = req.getUrl()
        DISPLAY "URL : ",url
        LET methd = req.getMethod()
        CALL SplitUrl(url) RETURNING path, query 
        DISPLAY "Incoming request: ",methd," path=",path," query=",query
        LET ind = path.getIndexOf(C_BASEURL,1)
        IF ind<1 THEN
          CALL req.sendResponse(400,"Invalid request")
        ELSE
          CALL DispatchService(req,path.subString(ind+C_BASEURL.getLength(),
            path.getLength()),query)
        END IF 
        DISPLAY "Sent response: ",methd," path=",path," query=",query
      END IF
    CATCH
      EXIT WHILE 
    END TRY
  END WHILE 
  
END MAIN

FUNCTION DispatchService(req,path,query)
  DEFINE  req   com.HttpServiceRequest
  DEFINE  path  STRING
  DEFINE  query STRING 
  DEFINE  ind   INTEGER
  LET ind = path.getIndexOf("/",1)
  IF ind>0 THEN
    CALL req.sendResponse(400,"invalid path")
  ELSE
    CASE path
      WHEN "Delegate" # Handle a dispatcher delegate service
        CALL DelegateWA(req,query)
      OTHERWISE
        CALL req.sendResponse(400,"unknown service '"||path||"'.");
    END CASE 
  END IF
END FUNCTION
        
#
# Delegate WA service
#  If browser URL doesn't contain 'ByPass' in query string then return a 404 error,
#  otherwise start GWC application
#        
FUNCTION DelegateWA(req,query)
  DEFINE  req               com.HttpServiceRequest
  DEFINE  query             STRING
  DEFINE  url               STRING
  DEFINE  queryString       STRING
  DEFINE  parameter         STRING
  DEFINE  ind               INTEGER
  DEFINE  ByPass            BOOLEAN
  DEFINE  q                 DYNAMIC ARRAY OF RECORD
                              qname   STRING,
                              qvalue  STRING
                            END RECORD
  # Read requests
  LET query = req.readFormEncodedRequest(false)  
  IF query IS NULL THEN
    CALL req.sendResponse(400,"no query string")
  ELSE 
    LET ByPass = FALSE
    CALL SplitUrl(query) RETURNING url,queryString
    CALL ParseQueryString(queryString) RETURNING q
    # Check if user-agent query string has a ByPass string ?
    FOR ind=1 TO q.getLength()
      IF q[ind].qname="ByPass" THEN
        LET ByPass = TRUE
      END IF
    END FOR
    IF NOT ByPass THEN
      # return error
      CALL req.sendResponse(404,"ByPass is missing")
    ELSE
      # Set parameter for GWC application via environment variable: ACCESS=OK
      CALL req.setResponseHeader(C_X_FOURJS_ENVIRONEMENT_||"ACCESS","OK")
      # Start application with HTTP code 307
      CALL req.sendResponse(307,C_GENERO_INTERNAL_DELEGATE)
    END IF
  END IF
  
END FUNCTION

#
# Parse given string and returns a dynamic array of the element inside the
#   query string 
#
FUNCTION ParseQueryString(str)
  DEFINE  str   STRING
  DEFINE  tkz   base.StringTokenizer
  DEFINE  token STRING
  DEFINE  ind   INTEGER  
  DEFINE  ret   DYNAMIC ARRAY OF RECORD 
                  qname   STRING,
                  qvalue  STRING
                END RECORD 
  INITIALIZE ret TO NULL
  LET tkz = base.StringTokenizer.create(str,"&")
  WHILE (tkz.hasMoreTokens())
    LET token = tkz.nextToken()
    CALL ret.appendElement()
    LET ind = ind + 1
    CALL ExtractKeyValueFromQuery(token) RETURNING ret[ind].qname,ret[ind].qvalue
  END WHILE 
  RETURN ret                    
END FUNCTION

#
# Extract Key and Value from query string
#
FUNCTION ExtractKeyValueFromQuery(str)
  DEFINE str  STRING
  DEFINE ind  INTEGER
  LET ind = str.getIndexOf("=",1)
  IF ind>1 THEN
    RETURN str.subString(1,ind-1),str.subString(ind+1,str.getLength())
  ELSE
    RETURN str,NULL
  END IF
END FUNCTION

#
# Splits an URL into path and query string parts
#    
FUNCTION SplitUrl(url)
  DEFINE  url   STRING
  DEFINE  ind   INTEGER
  DEFINE  query STRING
  DEFINE  path  STRING  
  LET ind = url.getIndexOf("?",1)
  IF ind>1 THEN
    LET query = url.subString(ind+1,url.getLength())
    LET path = url.subString(1,ind-1)
  ELSE
    LET query = NULL
    LET path = url.subString(1,url.getLength())
  END IF
  RETURN path, query
END FUNCTION