By default the Xbase++ WebHandler does negotiate the content type encoding automatically. The following simple AddressService returns a Object and leaves the content negotiation up to the WebHandler and the request sending party. The great benefit of that approach is that your service interfaces can be used within your application by calling the method directly (in-process) business-logic as well as remote (out-of-process) web or mobile client application.
To send requests use CURL . If you do not use it already we recommend it as an great tool for WebHandler request/response analysis. You can get it from here https://curl.haxx.se/windows/
*) The content-type is also text/plain in case of a request with Accept-Type: */*
Xbase++:
CLASS AddressService FROM WebHandler
EXPORTED:
METHOD getAddress()
METHOD getGreeting()
ENDCLASS
METHOD AddressService:getAddress()
LOCAL oAddress
// just create a dataobject with some members
oAddress := DataObject():new()
oAddress:ID := "NU01"
oAddress:Company := "NCC1701"
oAddress:Contact := "Nyota Uhura"
RETURN oAddress
METHOD AddressService:getGreeting()
RETURN "Hello from europe: öäü é è!"
Pre-Requsite for the following experiment
Run the WebHandler, use your own code or the simplified console service shown below.To send requests use CURL . If you do not use it already we recommend it as an great tool for WebHandler request/response analysis. You can get it from here https://curl.haxx.se/windows/
Xbase++:
#include "inkey.ch"
#include "web.ch"
PROCEDURE Main
LOCAL oEndpoint
SET CHARSET TO ANSI
// Starts http endpoint at port 8023 and binds all classes dervied from WebHandler to
// that endpoint via the classnames as the servicename and the exported methodname
// as the interface.
oEndpoint := HttpEndpoint():new(8023, "*")
IF( !oEndpoint:start() )
ErrorLevel(-1)
RETURN
ENDIF
WAIT
oEndpoint:stop()
RETURN
Content negotiation experiment
In the following table we are using CURL to send requests to our webhandler. As shown, depending on the Accept-Type of the request the Xbase++ Webhandler does automatically negotiate the content type, serializes objects or arrays into the proper data stream and send it back to the client. Of course, in case of text/html only texts data can be returned since there is no representation of an Object in HTML. However if character data is returned by the method of an webhandler and content type is text/html then HTML encoding is applied automatically as outlined with the :getGreeting() interface.Request | Response (italic implies header information) |
---|---|
curl -H "Accept: text/html" http://localhost:8023/AddressService/getAddress | Content-type: text/html DataObject |
curl -H "Accept: application/json" http://localhost:8023/AddressService/getAddress | Content-Type: application/json {"ID" :"NU1", "Company" :"NCC1701", "Contact" :"Nyota Uhura"} |
curl -H "Accept: application/xml" http://localhost:8023/AddressService/getAddress | Content-Type: application/xml <object classname="DataObject"> <character name="ID">NU1</character> <character name="Company">NCC1701</character> <character name="Contact">Nyota Uhura</character> </object> |
curl -H "Accept: text/plain" http://localhost:8023/AddressService/getGreeting | Content-type: text/plain *) Hello from europe: öäü é è! |
curl -H "Accept: text/html" http://localhost:8023/AddressService/getGreeting | Content-type: text/html Hello from europe: öäü é è! |
Enforcing a content-type
To enforce a specific content-type irrespective which accept-type the request was, simple set the accept-type in your WebHandler using the HttpResponse which is a member of your WebHandler instance. Simple add the following code to your :getAddress() method. If you want to change the behavior for all of your interfaces simple overload :execute() and add the folllowing code before you call SUPER.
Xbase++:
// response of this interface is always in json
::HttpRequest:AcceptTypes[1] := "application/json"