Build HTTP Services in DataFlex
Lesson 4 - Handling POST requests
POST requests contain data, therefore, it is important to be familiar with the data in order to make the necessary requests.
API’s used to view the data…
- RequestDataString: reads the request body as a string, and performs character conversions that are controlled by peRequestCodePage
- RequestDataUChar: reads binary data from the request body. No conversions are done.
- Works with chunking to set the maximum amount of data that is to be sent at one time
- HttpRequestHeader: the name is passed and returned as a string
- UrlParameter: read query string parameters
- GetCookie
- ServerVariable: reads various server variables to get extra information from IIS about the request
Properties that are seeded while handling OnHttp events:
- piRequestSize
- psRequestAcceptType
- psRequestContentType
- psRequestPath
- psRequestQueryString
- psRequestVerb
Proper error handling is important when handling requests. By default, the HTTP Handler will not send errors to the client except for critical errors that occur outside of DataFlex code, but it will be logged in the event log. The errors need to be tracked and sent back to the client. This is done with APIs. The errors are queued using ErrorQueueStart and ErrorQueueEnd. ErrorCount and ErrorMessage provide details about the errors that can be sent to the client.
DEMONSTRATION
- The service currently returns a list of products. This demonstration will show how to add a way to add products to the list using a POST request on the same URL that also returns the products.
- On the oProducts object, the onHttpPost event is going to be implemented. It is assumed that the data coming is a JSON object in the same format as the JSON being sent back.
- The first step is to read the request body. ‘RequestDataUChar’ is used to read the entire request into a UChar array. Providing a limit on the maximum amount of data to be read, will make the service more secure. The limit in the example is set to one megabyte. The JSON request is usually less than that. Next the JSON is parsed by creating another JSON object inside a new handle called hoProduct. The ‘ParseUtf8’ function is used. It takes a UChar array as its parameter and returns a Boolean that indicates whether the parse was successful. An error is returned if the parse failed. ‘SetResponseStatus 400’ is used to do this, and the message is set to “Invalid JSON.” The creation of the new record can cause DataFlex errors, so the errors are going to be queued using sending “ErrorQueueStart” before the operation and “ErrorQueueEnd” after the operation.
- There is now a JSON object that has the same structure as JSON objects being returned. Next the member values are retrieved out of the JSON object and are put into the Data Dictionary buffer using “Set Field_Changed_Value” after the buffer is cleared to create a new record.
- Since the vendor is a parent table the vendor name is going to be treated differently. It is going to be put into the global buffer, and then a find operation is done to find the right vendor. Index 3 is used for this, which is vendor name and vendor ID. A check is then done to make sure the right vendor is found or if it jumps to the next one.
- Now that the buffers are seeded, the record needs to be saved. To start this, a request validate of the values in the buffer according to the business rules needs to happen. A Boolean will be returned indicating the success of the validation. If the request is ‘true’ there is an error. If it is anything else the record will be saved. The error count needs to be checked to see if there were previous errors because nothing should be saved if there have already been errors.
- If everything was successful, the newly saved product will be returned. The “JsonProduct” function that was created earlier is used to create JSON that represents the new product. It will be stringifyed and written out using “OutputUChar” after it is put into a UChar array. The content type HTTP header needs to be added, and its content-type needs to be set to “application/json.” Then the JSON object needs to be destroyed.
- Finally, code needs to be written that returns an error that has occurred. The code in this example is very simple, and just returns a string represents the error that has occurred in JSON. The first error is the only one that is returned. To do this the error message is retrieved using “Get ErrorMessage,” and “OutputString” is used to it is output the string that will generate in place.
- To test the POST method a program called Postman is used. This tool is for configuring HTTP requests, storing them, putting them in collections, etc. The first step for testing is creating a new request, which is added to a new collection, DFLCHttpHandler.
- It needs to be configured as a POST request, and the URL needs to be entered. Parameters do not need to be passed, but an HTTP header does need to be to confirm that the content types is JSON. Often code would be written in the HTTP handler to validate the content type that is being sent.
- A JSON object is needed for the request body. One is copied out of the generated response. The request needs to be set to ‘raw,’ and the JSON text is pasted in. Values can be changed to mimic a new product being added.
- The request is sent a 404, a not found error, is returned. The Debugger is opened, and a breakpoint is added. From the ‘Configure Studio’ options list, ‘Open WebApp URL in Browser when debugging?’ is disabled.
- The request is tested again, and the breakpoint is not hit. This is because psVerbs is set to “GET,” so only get requests are being handled. POST requests also need be handled. psVerbs is set to “GET,POST.”
- When the test is sent again the breakpoint is hit indicating the request is being handled. Next, an illegal datatype conversion is found. This is due to the parameter ‘ucRequest’ not being passed into UTF8.
- After that is corrected, and it is tested again, an error message is being generated inside the code that indicates that the vendor part ID could not be found. There is an issue with the casing in the JSON product function. JSON is case sensitive, so this is issue is corrected by changing “Id” to “ID.”
- Finally, the test returns as successful. Looking at the list, the new product has been added. Note, POST requests are not repeatable, so if the test is sent again a duplicate error results.