WSHeader

Defines custom headers in the request and response of Web service functions.

Syntax

WSHeader

Where:

WSHeader in an ATTRIBUTE() clause of an input parameter or return value of the function defines a HTTP header.

WSHeader is an optional attribute.

Usage

Use the WSHeader attribute to define a custom header in an input parameters or in a return value. Custom headers are commonly used to provide information; however, you can also use them to pass data that implements logic on the server or client side.

Typically, you use WSHeader to pass data related to the service in the form of an HTTP header. For example, an input parameter defined with ATTRIBUTE(WSHeader, WSName="Authorization") sets the standard HTTP authorization header.

The WSHeader attribute supports use of complex types, such as records and arrays.

The GWS supports serialization of complex types as a comma-separated list of values, according to the OpenAPI specification style: simple explode: false.

If a value contains a comma, the GWS engine serializes the comma with percent encoding as "%2C" in the parameter. For example:
DEFINE b DYNAMIC ARRAY OF STRING = ["O,ne", "Two", "Three", NULL, "Five"]
The parameter contains: O%2Cne,Two,Three,,Five. The server and the client must deserialize "O%2Cne" to "O,ne" for insertion in Genero BDL.

Use WSName with WSHeader to name headers; otherwise the GWS gives the headers default names ("rv0", "rv1", etc) at runtime.

Example: WSHeader in input parameter

In the sample function, a header named "X-FourJs-Environment-Variable-REMOTE_ADDR" passes the Genero Application Server environment variable for the IP address of the remote client. This variable has hyphens ("-"), which are not allowed in Genero BDL variables.

The example uses the WSName attribute to identify the variable "X-FourJs-Environment-Variable-REMOTE_ADDR" in the HTTP request. The ip_addr parameter is BDL friendly and this is used in the function. The parameter is optional as defined by the attribute WSOptional.
Tip: The WSContext attribute, if set, can provide your service with access to environment variables set by the GAS.
IMPORT com

PUBLIC DEFINE myerror RECORD ATTRIBUTE(WSError="My error")
  code INTEGER,
  reason STRING
END RECORD

PUBLIC FUNCTION getRemoteAddress (ip_addr STRING 
   ATTRIBUTE(WSHeader, WSOptional, WSName="X-FourJs-Environment-Variable-REMOTE_ADDR") )
   ATTRIBUTES (WSGet, 
              WSPath="/users/ip",
              WSDescription="Get remote address of the client",
              WSThrows="400:Invalid,404:NotAvailable" )
   RETURNS ( INTEGER ATTRIBUTE(WSHeader), STRING)
     DEFINE ip STRING
     TRY
       LET ip=ip_addr
       IF ip IS NULL THEN 
          LET ip="Got no remote address."
       ELSE
         LET ip = SFMT("Hello there, you're at %1",ip )
       END if
     CATCH
       LET ip="Error getting remote address."
       LET myerror.reason = SFMT("Error during execution: %1 [%2]", sqlca.sqlcode, SQLERRMESSAGE )
       CALL com.WebServiceEngine.SetRestError(400,myerror)
     END TRY
     RETURN 3, ip
END FUNCTION

Example: WSHeader in return value

This example sets a custom header in the RETURNS clause of the function. The integer ("3") is returned in the header and the string ("hello world" ) is returned in the response body.
Warning: Standard response headers

Setting a standard HTTP header on a response must be handled with care, especially for those that define the response body such as Content-Type, or Content-Encoding. Make sure what you define with WSName does not conflict with what is specified in the OpenAPI specification for the service.

PUBLIC FUNCTION help() 
  ATTRIBUTES (WSGet)
  RETURNS (INTEGER ATTRIBUTE(WSHeader), 
    STRING)
    # ... function code  ...
    RETURN 3, "hello world"
END FUNCTION

Example: WSHeader returns a record

This example sets a custom header in the RETURNS clause of the function on a user-defined record type ("T_RECORD"). The string ("Return record in header: ..." ) is returned in the response body.
TYPE T_RECORD RECORD #... END RECORD

PUBLIC FUNCTION headerRecord(
    a T_RECORD ATTRIBUTES(WSHeader, WSOptional))
    ATTRIBUTES(WSGet,
        WSPath = "/v1/ok",
        WSDescription = "Return record in header",
        WSRetCode = "202:Accepted",
        WSThrows = "400:Bad Request,401:Unauthorized,500:Internal Server Error")
    RETURNS(STRING ATTRIBUTES(WSMedia = "application/json"),
        T_RECORD ATTRIBUTES(WSHeader))

    DEFINE b T_RECORD

    # ... function code  ...

    RETURN "Return record in header: ...", b.*

END FUNCTION