added LSL2 stored procedures
This commit is contained in:
476
LSL2/STPROC/HTTP_SCAN_SERVICES.txt
Normal file
476
LSL2/STPROC/HTTP_SCAN_SERVICES.txt
Normal file
@ -0,0 +1,476 @@
|
||||
Function HTTP_Scan_Services(RemainingURL)
|
||||
/***********************************************************************************************************************
|
||||
|
||||
This program is proprietary and is not to be used by or disclosed to others, nor is it to be copied without written
|
||||
permission from SRP Computer Solutions, Inc.
|
||||
|
||||
Name : HTTP_Scan_Services
|
||||
|
||||
Description : Handler program for the HTTP Scan service module.
|
||||
|
||||
Notes : All HTTP web services should include the HTTP_SERVICE_SETUP insert. This will provide several useful
|
||||
variables:
|
||||
|
||||
HTTPMethod - The HTTP Method (Verb) submitted by the client (e.g., GET, POST, etc.)
|
||||
APIURL - The URL for the API entry point (e.g., api.mysite.com/v1).
|
||||
SelfURL - The URL path representing the current service.
|
||||
FullEndPointURL - The URL submitted by the client. This can be the same or longer than
|
||||
the SelfURL.
|
||||
NextSegment - The URL segment immediately following the SelfURL (if any). This
|
||||
could contain the name of the next service or it could contain the
|
||||
Item ID for the current service (aka resource).
|
||||
CurrentServiceHandler - The name of this stored procedure.
|
||||
|
||||
Parameters :
|
||||
RemainingURL [in] -- The remaining portion of the URL that follows the URL that launched this current
|
||||
service. This information is used in the HTTP_SERVICE_SETUP insert to populate other
|
||||
useful variables (see Notes above).
|
||||
Response [out] -- Response to be sent back to the Controller (HTTP_MCP) or requesting procedure. Web API
|
||||
services do not rely upon anything being returned in the response. This is what the
|
||||
various services like SetResponseBody and SetResponseStatus services are for. A response
|
||||
value is only helpful if the developers want to use it for debug purposes.
|
||||
|
||||
History : (Date, Initials, Notes)
|
||||
07/31/18 dmb Original programmer.
|
||||
09/04/18 dmb Revamp so Scan is its own resource rather than a parent to a sub-resource. Migrate the Tools
|
||||
API logic into this routine as a starting point. Retrofit several SCANS column name equates
|
||||
to match the changes made to the dictionary.
|
||||
|
||||
***********************************************************************************************************************/
|
||||
|
||||
#pragma precomp SRP_PreCompiler
|
||||
|
||||
$insert APP_INSERTS
|
||||
$insert HTTP_SERVICE_SETUP
|
||||
$insert HTTP_INSERTS
|
||||
$insert SCANS_EQUATES
|
||||
|
||||
Declare function Scan_Services, Database_Services, RTI_CreateGUID
|
||||
Declare subroutine Scan_Services, Database_Services
|
||||
|
||||
// Assume the current HTTP method is valid until proven otherwise.
|
||||
ValidMethod = True$
|
||||
// Assume the current web service is valid until provent otherwise.
|
||||
ValidService = True$
|
||||
// Assume no HTTP methods are valid until proven otherwise.
|
||||
AllowedMethods = ''
|
||||
// A list of all services able to be called from this URL.
|
||||
AllowedServices = ''
|
||||
|
||||
// Handle the HTTP request as needed.
|
||||
Begin Case
|
||||
Case RemainingURL _EQC ''
|
||||
// This means the URL ends with /scan, which means this is the end point. The HTTP methods roughly function
|
||||
// as follows:
|
||||
//
|
||||
// POST - Creates a new resource. Assumes the server will generate the scan ID, which will be returned in
|
||||
// the HTTP response.
|
||||
AllowedMethods = 'POST,OPTIONS'
|
||||
Locate HTTPMethod in AllowedMethods using ',' setting MethodPos then
|
||||
On MethodPos GoSub Post, Options
|
||||
end else
|
||||
ValidMethod = False$
|
||||
end
|
||||
|
||||
Case Count(RemainingURL, '/') EQ 0
|
||||
// This means the URL ends with /scan/{scanID}. {scanID} is also known as the resource ID. When a resource is
|
||||
// closely mapped to a database row (as is the case with this Contacts API), this is where the basic CRUD
|
||||
// functionality will be added. The HTTP methods roughly function as follows:
|
||||
//
|
||||
// PUT - Creates* a resource using the Key ID contained in the URL. This is equivalent to the Write
|
||||
// statement in BASIC+.
|
||||
// GET - Reads the resource referenced by the Key ID contained in the URL. This is equivalent to the Read
|
||||
// statement in BASIC+.
|
||||
// PUT - Updates* the resource referenced by the Key ID contained in the URL. This is the exact same
|
||||
// feature defined above. This should make sense since the Write statement in BASIC+ is used to
|
||||
// create and update database rows. Note, the PUT method assumes the entire resource is within the
|
||||
// request body, not just the changes. See the PATCH method below.
|
||||
// DELETE - Deletes the source referenced by the Key ID contained in the URL. This is equivalent to the Delete
|
||||
// statement in BASIC+.
|
||||
//
|
||||
// * Many people use the POST method for creating (and updating) a resource. However, per the HTTP
|
||||
// specification, POST is to be used when creating a new resource that does not yet have a resource ID
|
||||
// (i.e., Key ID). The server determines the Key ID and this is returned to the client for future use.
|
||||
//
|
||||
// PATCH - Updates specific properties (e.g., data columns) of the resource referenced by the Key ID
|
||||
// contained in the URL. This is similar in concept to the WriteV statement in BASIC+, although
|
||||
// multiple changes in the resource can be updated with one PATCH method.
|
||||
AllowedMethods = 'POST,GET,PUT,PATCH,DELETE,OPTIONS'
|
||||
Locate HTTPMethod in AllowedMethods using ',' setting MethodPos then
|
||||
On MethodPos GoSub PostItem, GetItem, PutItem, PatchItem, DeleteItem, OptionsItem
|
||||
end else
|
||||
ValidMethod = False$
|
||||
end
|
||||
|
||||
Case Otherwise$
|
||||
ValidService = False$
|
||||
End Case
|
||||
|
||||
// Resolve any invalid conditions with the HTTP request.
|
||||
Begin Case
|
||||
Case Not(ValidService)
|
||||
HTTP_Services('SetResponseStatus', 404, NextSegment : ' is not a valid service request within the ' : CurrentServiceHandler : ' module.')
|
||||
|
||||
Case Not(ValidMethod)
|
||||
HTTP_Services('SetResponseStatus', 405, HTTPMethod : ' is not valid for this service.')
|
||||
|
||||
GoSub SetAllowedMethods
|
||||
End Case
|
||||
|
||||
Return Response OR ''
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Service Parameter Options
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
Options BOOLEAN = True$, False$
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Web Services
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//----------------------------------------------------------------------------------------------------------------------
|
||||
// Post
|
||||
//
|
||||
// Attempts to create a new scan. Creating a new scan follows these guidelines:
|
||||
//
|
||||
// - Any unexpected system errors will return a 500 status code (Internal Server Error).
|
||||
// - If no errors occur then a 201 (Created) status code is returned. The Content-Location response header will be
|
||||
// set to the value of the URL that will allow the client to GET the newly created resource.
|
||||
// - If there is an error locking the resource then a 423 status code (Locked) is returned.
|
||||
//----------------------------------------------------------------------------------------------------------------------
|
||||
Post:
|
||||
|
||||
ScanID = Scan_Services('CreateScansRow', 'Lot')
|
||||
If Error_Services('NoError') then
|
||||
ItemURL = SelfURL : '/' : ScanID
|
||||
StatusCode = 201
|
||||
GoSub CreateHALItem
|
||||
end else
|
||||
Message = Error_Services('GetMessage')
|
||||
HTTP_Services('SetResponseStatus', 500, Message)
|
||||
end
|
||||
|
||||
return
|
||||
|
||||
|
||||
//----------------------------------------------------------------------------------------------------------------------
|
||||
// Options
|
||||
//
|
||||
// Sets the appropriate response header fields for an OPTIONS request.
|
||||
//----------------------------------------------------------------------------------------------------------------------
|
||||
Options:
|
||||
|
||||
GoSub SetCommonOptionResponseHeaders
|
||||
|
||||
return
|
||||
|
||||
|
||||
//----------------------------------------------------------------------------------------------------------------------
|
||||
// PostItem
|
||||
//
|
||||
// Attempts to add new scan data to the scan resource.
|
||||
//----------------------------------------------------------------------------------------------------------------------
|
||||
PostItem:
|
||||
|
||||
ScanID = NextSegment
|
||||
|
||||
// The resource will have been put into the POST string.
|
||||
Body = HTTP_Services('GetHTTPPostString')
|
||||
If Body NE '' then
|
||||
// The POST string will have been encoded so use percent (URL) decoding.
|
||||
Body = HTTP_Services('DecodePercentString', Body)
|
||||
ParseResponse = SRP_JSON(hBody, 'PARSE', Body)
|
||||
If (ParseResponse EQ '') then
|
||||
ValidScan = False$ ; // Assume the scan is not valid for now.
|
||||
ScanData = SRP_JSON(hBody, 'GetValue', 'scanData')
|
||||
SRP_JSON(hBody, 'Release')
|
||||
Scan_Services('ProcessScanData', ScanID, ScanData)
|
||||
If Error_Services('NoError') then
|
||||
ItemURL = SelfURL : '/' : ScanID
|
||||
StatusCode = 200 ; // This service assumes the resource already exists.
|
||||
GoSub CreateHALItem
|
||||
end else
|
||||
Message = Error_Services('GetMessage')
|
||||
HTTP_Services('SetResponseStatus', 400, Message)
|
||||
end
|
||||
end else
|
||||
HTTP_Services('SetResponseStatus', 400, 'Unable to parse the scanData JSON.')
|
||||
end
|
||||
end else
|
||||
HTTP_Services('SetResponseStatus', 400, 'JSON object is missing from the request.')
|
||||
end
|
||||
|
||||
return
|
||||
|
||||
|
||||
//----------------------------------------------------------------------------------------------------------------------
|
||||
// GetItem
|
||||
//
|
||||
// Returns the specific resource.
|
||||
//
|
||||
// The easiest way to return a resource that is mapped to a database row is to use the GetDatabaseItem service. This
|
||||
// is being done in the code below. However, to demonstrate how then basic functionality can be extended, there is
|
||||
// additional code below that will show how to add the Contact resource's image URL to the JSON response.
|
||||
//----------------------------------------------------------------------------------------------------------------------
|
||||
GetItem:
|
||||
|
||||
ScanID = NextSegment
|
||||
ItemURL = SelfURL : '/' : ScanID
|
||||
ScanRow = Scan_Services('GetScansRow', ScanID)
|
||||
If Error_Services('NoError') then
|
||||
StatusCode = 200
|
||||
GoSub CreateHALItem
|
||||
end else
|
||||
Message = Error_Services('GetMessage')
|
||||
HTTP_Services('SetResponseStatus', 404, Message)
|
||||
end
|
||||
|
||||
return
|
||||
|
||||
|
||||
//----------------------------------------------------------------------------------------------------------------------
|
||||
// PutItem
|
||||
//
|
||||
// Attempts to replace the indicated scan resource with the incoming JSON object.
|
||||
//----------------------------------------------------------------------------------------------------------------------
|
||||
PutItem:
|
||||
|
||||
ScanID = NextSegment
|
||||
|
||||
// The resource will have been put into the POST string.
|
||||
Body = HTTP_Services('GetHTTPPostString')
|
||||
If Body NE '' then
|
||||
// The POST string will have been encoded so use percent (URL) decoding.
|
||||
Body = HTTP_Services('DecodePercentString', Body)
|
||||
ParseResponse = SRP_JSON(hBody, 'PARSE', Body)
|
||||
If (ParseResponse EQ '') then
|
||||
ScanRow = Database_Services('ReadDataRow', 'SCANS', ScanID)
|
||||
If Error_Services('NoError') then
|
||||
// Existing scan resource is being replaced.
|
||||
StatusCode = 200
|
||||
end else
|
||||
// Scan resource is being created for the first time.
|
||||
StatusCode = 201
|
||||
end
|
||||
If ScanRow<SCANS.CREATED_DATE$> EQ '' then ScanRow<SCANS.CREATED_DATE$> = Date()
|
||||
If ScanRow<SCANS.CREATED_TIME$> EQ '' then ScanRow<SCANS.CREATED_TIME$> = Time()
|
||||
ScanRow<SCANS.EMPLOYEE_ID$> = SRP_JSON(hBody, 'GetValue', 'employeeID', '')
|
||||
ScanRow<SCANS.TOOL_ID$> = SRP_JSON(hBody, 'GetValue', 'toolID', '')
|
||||
ScanRow<SCANS.CASSETTE_IDS$> = SRP_JSON(hBody, 'GetValue', 'cassetteID', '')
|
||||
Accept = SRP_JSON(hBody, 'GetValue', 'accept', False$)
|
||||
If Accept EQ True$ then
|
||||
// Before allowing the accept field to be set to True, verify that all required data has been populated.
|
||||
Begin Case
|
||||
Case ScanRow<SCANS.EMPLOYEE_ID$> EQ '' ; Accept = False$
|
||||
Case ScanRow<SCANS.TOOL_ID$> EQ '' ; Accept = False$
|
||||
Case ScanRow<SCANS.CASSETTE_IDS$> EQ '' ; Accept = False$
|
||||
End Case
|
||||
end
|
||||
ScanRow<SCANS.ACCEPTED$> = Accept
|
||||
If ScanRow<SCANS.ACCEPTED$> EQ True$ then
|
||||
ScanRow<SCANS.ACCEPTED_DATE$> = Date()
|
||||
ScanRow<SCANS.ACCEPTED_TIME$> = Time()
|
||||
end
|
||||
Database_Services('WriteDataRow', 'SCANS', ScanID, ScanRow, True$, False$, True$)
|
||||
If Error_Services('NoError') then
|
||||
ItemURL = SelfURL : '/' : ScanID
|
||||
GoSub CreateHALItem
|
||||
end else
|
||||
Message = Error_Services('GetMessage')
|
||||
HTTP_Services('SetResponseStatus', 500, Message)
|
||||
end
|
||||
SRP_JSON(hBody, 'Release')
|
||||
end else
|
||||
HTTP_Services('SetResponseStatus', 400, 'Unable to parse the scanData JSON.')
|
||||
end
|
||||
end else
|
||||
HTTP_Services('SetResponseStatus', 400, 'JSON object is missing from the request.')
|
||||
end
|
||||
|
||||
return
|
||||
|
||||
|
||||
//----------------------------------------------------------------------------------------------------------------------
|
||||
// PatchItem
|
||||
//
|
||||
// Attempts to update the indicated scan resource with the incoming JSON object. The only permissible field to be
|
||||
// updated is "accept".
|
||||
//----------------------------------------------------------------------------------------------------------------------
|
||||
PatchItem:
|
||||
|
||||
ScanID = NextSegment
|
||||
|
||||
// First confirm that this is a valid Scan ID.
|
||||
jsonScan = Scan_Services('GetScansRow', ScanID, True$)
|
||||
If Error_Services('NoError') then
|
||||
// Confirm that all required data has been scanned before allowing the "accept" field to be updated.
|
||||
ParseResponse = SRP_JSON(objResource, 'Parse', jsonScan)
|
||||
If ParseResponse EQ '' then
|
||||
ScanAcceptable = SRP_JSON(objResource, 'GetValue', 'scan.acceptable', False$)
|
||||
If ScanAcceptable NE True$ then
|
||||
ScanNotAcceptableReason = SRP_JSON(objResource, 'GetValue', 'scan.notAcceptableReason')
|
||||
Error_Services('Add', ScanNotAcceptableReason)
|
||||
end
|
||||
SRP_JSON(objResource, 'Release')
|
||||
end else
|
||||
Error_Services('Add', 'Unable to parse the JSON scan resource.')
|
||||
end
|
||||
|
||||
If Error_Services('NoError') then
|
||||
// The resource will have been put into the POST string.
|
||||
Body = HTTP_Services('GetHTTPPostString')
|
||||
If Body NE '' then
|
||||
// The POST string will have been encoded so use percent (URL) decoding.
|
||||
Body = HTTP_Services('DecodePercentString', Body)
|
||||
ParseResponse = SRP_JSON(hBody, 'PARSE', Body)
|
||||
If ParseResponse EQ '' then
|
||||
AcceptedStatus = SRP_JSON(hBody, 'GetValue', 'accepted.status')
|
||||
If AcceptedStatus NE '' then
|
||||
ScansRow = Scan_Services('GetScansRow', ScanID, False$)
|
||||
ScansRow<SCANS.ACCEPTED$> = AcceptedStatus
|
||||
If AcceptedStatus EQ True$ then
|
||||
ScansRow<SCANS.ACCEPTED_DATE$> = Date()
|
||||
ScansRow<SCANS.ACCEPTED_TIME$> = Time()
|
||||
end
|
||||
Scan_Services('SetScansRow', ScanID, ScansRow)
|
||||
If Error_Services('NoError') then
|
||||
ItemURL = SelfURL : '/' : ScanID
|
||||
StatusCode = 200
|
||||
GoSub CreateHALItem
|
||||
end else
|
||||
Message = Error_Services('GetMessage')
|
||||
HTTP_Services('SetResponseStatus', 500, Message)
|
||||
end
|
||||
end else
|
||||
HTTP_Services('SetResponseStatus', 400, 'accepted.status field is missing from the JSON object.')
|
||||
end
|
||||
SRP_JSON(hBody, 'Release')
|
||||
end else
|
||||
HTTP_Services('SetResponseStatus', 400, 'Unable to parse the scanData JSON.')
|
||||
end
|
||||
end else
|
||||
HTTP_Services('SetResponseStatus', 400, 'JSON object is missing from the request.')
|
||||
end
|
||||
end else
|
||||
Message = Error_Services('GetMessage')
|
||||
HTTP_Services('SetResponseStatus', 400, Message)
|
||||
end
|
||||
end else
|
||||
Message = Error_Services('GetMessage')
|
||||
HTTP_Services('SetResponseStatus', 404, Message)
|
||||
end
|
||||
|
||||
return
|
||||
|
||||
|
||||
//----------------------------------------------------------------------------------------------------------------------
|
||||
// DeleteItem
|
||||
//
|
||||
// Attempts to delete the resource. Deleting a resource which is a database row follows these guidelines:
|
||||
//
|
||||
// - Any unexpected system errors will return a 500 status code (Internal Server Error).
|
||||
// - If no errors occur then a 204 (No Content) status code is returned.
|
||||
// - If the resource was already deleted then a 204 (No Content) status code is returned.
|
||||
// - If there is an error locking the resource then a 423 status code (Locked) is returned.
|
||||
//----------------------------------------------------------------------------------------------------------------------
|
||||
DeleteItem:
|
||||
|
||||
ScanID = NextSegment
|
||||
|
||||
ScanRow = Database_Services('ReadDataRow', 'SCANS', ScanID)
|
||||
If Error_Services('NoError') then
|
||||
If ScanRow<SCANS.ACCEPTED$> NE True$ then
|
||||
Database_Services('DeleteDataRow', 'SCANS', ScanID, True$, False$)
|
||||
If Error_Services('NoError') then
|
||||
HTTP_Services('SetResponseStatus', 200)
|
||||
end else
|
||||
Message = Error_Services('GetMessage')
|
||||
HTTP_Services('SetResponseStatus', 500, Message)
|
||||
end
|
||||
end else
|
||||
HTTP_Services('SetResponseStatus', 403, 'This scan is already accepted and cannot be deleted.')
|
||||
end
|
||||
end else
|
||||
Message = Error_Services('GetMessage')
|
||||
HTTP_Services('SetResponseStatus', 404, Message)
|
||||
end
|
||||
|
||||
return
|
||||
|
||||
|
||||
//----------------------------------------------------------------------------------------------------------------------
|
||||
// OptionsItem
|
||||
//
|
||||
// Sets the appropriate response header fields for an OPTIONS request.
|
||||
//----------------------------------------------------------------------------------------------------------------------
|
||||
OptionsItem:
|
||||
|
||||
GoSub SetCommonOptionResponseHeaders
|
||||
|
||||
return
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Internal GoSubs
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//----------------------------------------------------------------------------------------------------------------------
|
||||
// SetCommonOptionResponseHeaders
|
||||
//
|
||||
// Sets the response headers that will be common for all OPTIONS methods.
|
||||
//----------------------------------------------------------------------------------------------------------------------
|
||||
SetCommonOptionResponseHeaders:
|
||||
|
||||
HTTP_Services('SetResponseHeaderField', 'Access-Control-Allow-Headers', 'authorization', True$)
|
||||
HTTP_Services('SetResponseHeaderField', 'Access-Control-Allow-Headers', 'x-authorization', True$)
|
||||
HTTP_Services('SetResponseHeaderField', 'Access-Control-Max-Age', 1728000)
|
||||
|
||||
GoSub SetAllowedMethods
|
||||
|
||||
return
|
||||
|
||||
|
||||
//----------------------------------------------------------------------------------------------------------------------
|
||||
// SetAllowedMethods
|
||||
//
|
||||
// Sets the Allow response header field as appropriate for the requested URL.
|
||||
//----------------------------------------------------------------------------------------------------------------------
|
||||
SetAllowedMethods:
|
||||
|
||||
If AllowedMethods NE '' then
|
||||
For Each Method in AllowedMethods using ','
|
||||
HTTP_Services('SetResponseHeaderField', 'Allow', Method, True$)
|
||||
Next Method
|
||||
end
|
||||
|
||||
return
|
||||
|
||||
|
||||
//----------------------------------------------------------------------------------------------------------------------
|
||||
// CreateHALItem
|
||||
//
|
||||
// Creates a HAL+JSON object based on the OpenInsight data row representation of the scan.
|
||||
//----------------------------------------------------------------------------------------------------------------------
|
||||
CreateHALItem:
|
||||
|
||||
jsonScan = Scan_Services('ConvertMVScanToJSON', ScanID, '', itemURL)
|
||||
|
||||
If Error_Services('NoError') then
|
||||
If SRP_JSON(objResource, 'Parse', jsonScan) EQ '' then
|
||||
lastModified = SRP_JSON(objResource, 'GetValue', 'lastModified')
|
||||
end else
|
||||
lastModified = ''
|
||||
end
|
||||
SRP_JSON(objResource, 'Release')
|
||||
HTTP_Services('SetResponseHeaderField', 'Content-Location', ItemURL)
|
||||
HTTP_Services('SetResponseHeaderField', 'Last-Modified', lastModified)
|
||||
HTTP_Services('SetResponseBody', jsonScan, False$, 'application/hal+json')
|
||||
HTTP_Services('SetResponseStatus', StatusCode)
|
||||
end else
|
||||
Message = Error_Services('GetMessage')
|
||||
HTTP_Services('SetResponseStatus', 500, 'Error in the ' : CurrentServiceHandler : ' service. Message: ': Message)
|
||||
end
|
||||
|
||||
return
|
Reference in New Issue
Block a user