Application logic

Reference | Web Services


A ‘logic’ component represents the interface between the Granitic framework and your application logic. Granitic passes your code a populated and validated ws.Request as well as an empty ws.Response into which you can record any errors your code encounters as well the ‘result’ data to be encoded in the eventual HTTP response.

Linking a handler to logic

Every instance of handler.WsHandler requires that you set the Logic field to a reference to a component that either:

Which of those you use depends on the use cases (listed below) that most closely matches your requirement

Capture data into an empty struct

The most common use case for web services is that a request will have some information that needs to be captured. Generally that information can be parsed into a target struct that does not require any complex initialisation.

In this case, your logic component should implement a method of the form:

  ProcessPayload(context.Context, *ws.Request, *ws.Response, *YourStruct)

Where YourStruct is the type that you want Granitic to instantiate, populate with data from the request and pass into your logic component.

No data to capture

Some web service requests do not require or allow information to be supplied in the HTTP request body, path or query parameters. ‘Health check’ or service status endpoints, for example. For these requests your logic component should implement the handler.WsRequestProcessor interface, e.g. have a method with the signature:

  Process(ctx context.Context, request *ws.Request, response *ws.Response)

Capture data into a complex struct

There are some circumstances under which the target struct into which Granitic should parse web service data needs initialisation before it can receive data.

If this is the case for your web service, your logic component must implement handler.WsRequestProcessor and handler.WsUnmarshallTarget.

Before parsing, Granitic will call your logic component’s

  UnmarshallTarget() interface{}

method. This method should create a struct, perform whatever initialisation is needed and return a pointer to that struct. For example:

func UnmarshallTarget() interface{} {
	
 s:= new(MyStruct)

 //Perform intialisation
 
 return s
	
}

Your logic component can then recover this later, e.g:

func Process(ctx context.Context, request *ws.Request, response *ws.Response) {
	
  s := request.RequestBody.(*MyStruct)
	
}

Building a response

Granitic will construct a response based on the state of the ws.Response object when your logic component’s Process... method returns.

Body

The contents of the Response.Body field will be serialised into the HTTP response body by the ws.ResponseWriter that is set on the ResponseWriter field of your handler. If you are using the JSONWs or XMLWs facility this will happen automatically.

You can set this field to any Go value that can be serialised by the ws.ResponseWriter.

HTTP status code

The HTTP status code (200, 404 etc) that is set on the eventual HTTP response returned to your web service client is calculated in one of two ways.

  1. Granitic examines the types of errors present in the Errors field of the ws.Response according to the rules defined here
  2. You can explicitly set the desired response code by setting the HTTPStatus on the ws.Response.

Next: Error handling

Prev: Validation