added frameworks entities
This commit is contained in:
535
FRAMEWORKS/STPROC/HTTP_CONTACTS_SERVICES.txt
Normal file
535
FRAMEWORKS/STPROC/HTTP_CONTACTS_SERVICES.txt
Normal file
@ -0,0 +1,535 @@
|
||||
Function HTTP_Contacts_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_Contacts_Services
|
||||
|
||||
Description : Handler program for the HTTP Contacts service module.
|
||||
|
||||
Notes : In the comments below, the term "resource" will be used. In most cases this is synonymous with a
|
||||
database row, but the web (and especially REST) abstracts all information being returned simply as a
|
||||
"resource". This provides developers more flexibility in their web API designs. For instance, a
|
||||
resource can be a combination of various different database rows and other data (like images,
|
||||
documents, etc.)
|
||||
|
||||
In this sample service, the "contact" resource will closely map to a sample CONTACTS database table.
|
||||
This is meant to provide the OpenInsight web API developer an easy way to create a web-based CRUD
|
||||
API that can also be extended as needed. Locking is performed on the resource at the database row
|
||||
level using the Lock statement, but this is only done just prior to the Write statement since HTTP
|
||||
is a stateless protocol. While some attempts to wait for the lock to be available could be added,
|
||||
this is normally discouraged since this could cause the HTTP request to take too long to finish.
|
||||
|
||||
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)
|
||||
04/17/15 dmb Original programmer. - [SRPFW-96]
|
||||
03/09/16 dmb Refactor to use the updated RunHTTPService service. - [SRPFW-112]
|
||||
07/01/17 dmb Refactor using Enhanced BASIC+ syntax. - [SRPFW-184]
|
||||
07/07/17 dmb Add support for PUT and PATCH so this routine can serve as a more complete CRUD example.
|
||||
- [SRPFW-187]
|
||||
07/08/17 dmb Remove checks for query parameters from the main router and make this a function of the
|
||||
GET method/URL handler. - [SRPFW-187]
|
||||
07/19/18 dmb Fix minor typo in the NextSegment variable in the GetItem method. - [SRPFW-248]
|
||||
|
||||
***********************************************************************************************************************/
|
||||
|
||||
#pragma precomp SRP_PreCompiler
|
||||
|
||||
$insert APP_INSERTS
|
||||
$insert HTTP_SERVICE_SETUP
|
||||
$insert HTTP_INSERTS
|
||||
|
||||
// In the comments related to URL examples, words surrounded by "{" and "}" represent the names of values that
|
||||
// will appear in the actual URL. Words surrounded by "<" and ">" represent variables that contain values relevant to
|
||||
// the actual URL. See the Notes above for a list of the most important variables.
|
||||
//
|
||||
// For instance, <APIURL>/contacts/{KeyID} could look like https://api.mysite.com/v1/contacts/1000, assuming <APIURL>
|
||||
// resolves to "https://api.mysite.com/v1" and {KeyID} resolves to "1000".
|
||||
//
|
||||
// The type of request being made needs to be determined based on the URL content. There are only a few possibilities
|
||||
// that this API will support:
|
||||
//
|
||||
// All Resources = <APIURL>/contacts
|
||||
// Specific Resource = <APIURL>/contacts/{KeyID}
|
||||
// Specific Resource Property = <APIURL>/contacts/{KeyID}/{property}
|
||||
//
|
||||
// Also, any URL can end with query parameters like this:
|
||||
//
|
||||
// Resource Query = <APIURL>/contacts?{property}={value}
|
||||
//
|
||||
// The request will go to the same handler as if the query parameters were missing but that handler itself will
|
||||
// determine if the query parameters will be used or ignored.
|
||||
|
||||
// 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 = 'picture'
|
||||
|
||||
// Handle the HTTP request as needed.
|
||||
Begin Case
|
||||
Case RemainingURL _EQC ''
|
||||
// This means the URL ends with /contacts, 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 Key ID, which will be returned in the
|
||||
// HTTP response.
|
||||
// GET - The client is requesting a collection of all contacts.
|
||||
AllowedMethods = 'POST,GET,OPTIONS'
|
||||
Locate HTTPMethod in AllowedMethods using ',' setting MethodPos then
|
||||
On MethodPos GoSub Post, Get, Options
|
||||
end else
|
||||
ValidMethod = False$
|
||||
end
|
||||
|
||||
Case Count(RemainingURL, '/') EQ 0
|
||||
// This means the URL ends with /contacts/{KeyID}. {KeyID} 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 = 'PUT,GET,DELETE,PATCH,OPTIONS'
|
||||
Locate HTTPMethod in AllowedMethods using ',' setting MethodPos then
|
||||
On MethodPos GoSub PutItem, GetItem, DeleteItem, PatchItem, OptionsItem
|
||||
end else
|
||||
ValidMethod = False$
|
||||
end
|
||||
|
||||
Case Count(RemainingURL, '/') GE 1
|
||||
// This means the URL ends with /contacts/{KeyID}/{property}. A property can be any specific data that is
|
||||
// associated with the resource. It could be a column value, an image, a PDF document, etc. In this case, the
|
||||
// only property supported by this web API is the contact's "picture". The developer can put add code in this
|
||||
// service to update the picture or the developer can create another HTTP service to handle this. Since a
|
||||
// "picture" service might be useful as a property for other types of resources, a call to a dedicated "picture"
|
||||
// HTTP service will be made "as is" so it can handle the request. Calling another HTTP service is similar to
|
||||
// the way one MFS calls another MFS by modifying the FS list. In this case, the NextSegment and RemainingURL
|
||||
// variables will need to be modified.
|
||||
Property = FullEndPointURL[-1, 'B/']
|
||||
Locate Property in AllowedServices using ',' setting ServicePos then
|
||||
NextSegment = Property ; // This allows the RunHTTPService to call HTTP_PICTURE_SERVICES.
|
||||
RemainingURL = '' ; // This variable won't be used in the HTTP_PICTURE_SERVICES code, but to keep the
|
||||
; // variables well formed, this should be cleared.
|
||||
HTTP_Services('RunHTTPService', NextSegment, RemainingURL)
|
||||
end else
|
||||
ValidService = 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 resource. Creating a new 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 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:
|
||||
|
||||
HTTP_Resource_Services('PostDatabaseItem', 'CONTACTS', SelfURL)
|
||||
|
||||
return
|
||||
|
||||
|
||||
//----------------------------------------------------------------------------------------------------------------------
|
||||
// Get
|
||||
//
|
||||
// Returns a collection of resources.
|
||||
//
|
||||
// The easiest way to return a list of resources that are mapped to a database table is to use the GetDatabaseItems
|
||||
// service. This is being done in the code below. This URL also supports the passing in of query parameters, which in
|
||||
// this case will be used to return those items that match the property/value query.
|
||||
//
|
||||
// A property can be any specific data that is associated with the resource. It could be a column value, an image, a PDF
|
||||
// document, etc. In this case, only properties that match the name of database columns in the CONTACTS table will be
|
||||
// supported by this web API. Note, developers can limit the properties (aka columns) to those that are indexed in order
|
||||
// to avoid having a request take too long.
|
||||
//----------------------------------------------------------------------------------------------------------------------
|
||||
Get:
|
||||
|
||||
HAL = '' ; // Initialize the response.
|
||||
|
||||
If HTTP_Services('GetHTTPGetString') NE '' then
|
||||
// This means the URL ends with /contacts?{property}={value}. The client is searching for one or more contacts
|
||||
// that match the query parameters. This is equivalent to doing a filtered RLIST search.
|
||||
|
||||
// Get the query string passed into the URL.
|
||||
GetString = HTTP_Services('GetHTTPGetString')
|
||||
// Get the name of the property being queried.
|
||||
Property = GetString[1, 'F=']
|
||||
// Get the value being searched for.
|
||||
Value = HTTP_Services('GetQueryField', Property)
|
||||
// Get the database columns for the table.
|
||||
ColumnNames = HTTP_Resource_Services('GetColumnNames', 'CONTACTS')
|
||||
ColumnName = Property
|
||||
Convert @Lower_Case to @Upper_Case in ColumnName
|
||||
// Verify the property matches a valid column in the table.
|
||||
Locate ColumnName in ColumnNames using @FM setting fPos then
|
||||
// Use the GetDatabaseItems service to perform the search and prepare the HAL+JSON response. If a more complex
|
||||
// or optimized solution is needed, then replace the following with custom code.
|
||||
Filter = 'SELECT CONTACTS WITH ' : ColumnName : ' CONTAINING ' : Quote(Value)
|
||||
// The GetDatabaseItems service will return all database column values unless otherwise specified. Since a query
|
||||
// search might generated several results, it is sometimes best to pass in just those columns that are important
|
||||
// for the query result.
|
||||
ColumnNames = 'first_name' : @FM : 'last_name' : @FM : 'email'
|
||||
Locate ColumnName in ColumnNames using @FM setting fPos else
|
||||
// Make sure the property being searched is included in the columns being returned.
|
||||
ColumnNames := @FM : Property
|
||||
end
|
||||
HAL = HTTP_Resource_Services('GetDatabaseItems', Filter, 'CONTACTS', SelfURL, ColumnNames)
|
||||
end else
|
||||
// This is not a valid property, which means the URL does not resolve. Set a 404 error. Add a description if
|
||||
// desired.
|
||||
HTTP_Services('SetResponseStatus', 404)
|
||||
end
|
||||
|
||||
end else
|
||||
// This means the URL ends with /contacts. The client is requesting all resources available at this URL.
|
||||
// This is equivalent to performing an unfiltered SELECT statement. The ColumnNames argument for the
|
||||
// GetDatabaseItems service specifies which values should be represented in the JSON response.
|
||||
|
||||
Filter = ''
|
||||
ColumnNames = 'first_name' : @FM : 'last_name' : @FM : 'email'
|
||||
HAL = HTTP_Resource_Services('GetDatabaseItems', Filter, 'CONTACTS', SelfURL, ColumnNames)
|
||||
|
||||
end
|
||||
|
||||
Response = HAL
|
||||
|
||||
return
|
||||
|
||||
|
||||
//----------------------------------------------------------------------------------------------------------------------
|
||||
// Options
|
||||
//
|
||||
// Sets the appropriate response header fields for an OPTIONS request.
|
||||
//----------------------------------------------------------------------------------------------------------------------
|
||||
Options:
|
||||
|
||||
GoSub SetCommonOptionResponseHeaders
|
||||
|
||||
return
|
||||
|
||||
|
||||
//----------------------------------------------------------------------------------------------------------------------
|
||||
// PutItem
|
||||
//
|
||||
// Attempts to update the resource. If the resource does not already exist then a new one will be created. Updating 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 200 (OK) status code is returned if the resource previously existed. Otherwise,
|
||||
// a 201 (Created) status code is returned and the Content-Location response header will be set to the value of the
|
||||
// URL that will allow the client to GET a newly created resource.
|
||||
// - If there is an error locking the resource then a 423 status code (Locked) is returned.
|
||||
//----------------------------------------------------------------------------------------------------------------------
|
||||
PutItem:
|
||||
|
||||
KeyID = NextSegment
|
||||
|
||||
HTTP_Resource_Services('PutDatabaseItem', 'CONTACTS', SelfURL : '/' : KeyID, KeyID)
|
||||
|
||||
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:
|
||||
|
||||
KeyID = NextSegment
|
||||
|
||||
// Calling this service alone would be sufficient to return a HAL+JSON representation of the specified contact.
|
||||
HAL = HTTP_Resource_Services('GetDatabaseItem', 'CONTACTS', SelfURL : '/' : KeyID, KeyID)
|
||||
|
||||
// Since the Contact resource can also have an image, the following code will generate a valid URL for this image
|
||||
// in case the client wants to retrieve it. The URL will then be added to the HAL+JSON response so this comes
|
||||
// back as a single representation of the resource.
|
||||
If HAL NE '' then
|
||||
// Make the JSON content an object so the SRP_JSON API can work with it.
|
||||
ParseResponse = SRP_JSON(HALRootObj, 'PARSE', HAL)
|
||||
If ParseResponse EQ '' then
|
||||
// The CONTACTS table has a PICTURE data column. This stores the physical path to the image, but this is
|
||||
// not useful to the HTTP client. Create a URL that will allow the client to retrieve the image.
|
||||
PictureValue = SRP_JSON(HALRootObj, 'GETVALUE', 'picture', '')
|
||||
If PictureValue NE '' then
|
||||
If SRP_JSON(PictureObj, 'NEW', 'OBJECT') then
|
||||
// Create the URL and add it to the JSON object.
|
||||
ImageURL = SelfURL : '/' : KeyID : '/picture'
|
||||
SRP_JSON(PictureObj, 'SETVALUE', 'href', ImageURL)
|
||||
SRP_JSON(PictureObj, 'SETVALUE', 'name', 'picture-' : KeyID)
|
||||
SRP_JSON(HALRootObj, 'SET', 'picture', PictureObj)
|
||||
HAL = SRP_JSON(HALRootObj, 'STRINGIFY', 'STYLED')
|
||||
// Set the HTTP response body with the final HAL+JSON results.
|
||||
HTTP_Services('SetResponseBody', HAL, False$, 'application/hal+json')
|
||||
SRP_JSON(PictureObj, 'RELEASE')
|
||||
end
|
||||
end
|
||||
SRP_JSON(HALRootObj, 'RELEASE')
|
||||
end
|
||||
end
|
||||
|
||||
Response = HAL
|
||||
|
||||
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:
|
||||
|
||||
KeyID = NextSegment
|
||||
|
||||
HTTP_Resource_Services('DeleteDatabaseItem', 'CONTACTS', KeyID)
|
||||
|
||||
return
|
||||
|
||||
|
||||
//----------------------------------------------------------------------------------------------------------------------
|
||||
// PatchItem
|
||||
//
|
||||
// Attempts to update the resource. Updating 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 200 (OK) status code is returned.
|
||||
// - If the resource is new then a 404 (Not Found) status code is returned. PATCH only works with existing resources.
|
||||
// - Only those properties (columns) which are passed in will get updated.
|
||||
// - If there is an error locking the resource then a 423 status code (Locked) is returned.
|
||||
//----------------------------------------------------------------------------------------------------------------------
|
||||
PatchItem:
|
||||
|
||||
KeyID = NextSegment
|
||||
|
||||
HTTP_Resource_Services('PatchDatabaseItem', 'CONTACTS', SelfURL : '/' : KeyID, KeyID)
|
||||
|
||||
return
|
||||
|
||||
|
||||
//----------------------------------------------------------------------------------------------------------------------
|
||||
// OptionsItem
|
||||
//
|
||||
// Sets the appropriate response header fields for an OPTIONS request.
|
||||
//----------------------------------------------------------------------------------------------------------------------
|
||||
OptionsItem:
|
||||
|
||||
GoSub SetCommonOptionResponseHeaders
|
||||
|
||||
return
|
||||
|
||||
|
||||
//----------------------------------------------------------------------------------------------------------------------
|
||||
// PutItemProperty
|
||||
//
|
||||
// Attempts to update the property of a specific resource.
|
||||
//
|
||||
// A property can be any specific data that is associated with the resource. It could be a column value, an image, a PDF
|
||||
// document, etc. In this case, the only property supported by this web API is the contact's "picture". The developer
|
||||
// can put add code here to update the picture or the developer can create another HTTP service to handle this. Since a
|
||||
// "picture" service might be useful as a property for other types of resources, a call to a dedicated "picture" HTTP
|
||||
// service will be made.
|
||||
//
|
||||
// Calling another HTTP service is similar to the way one MFS calls another MFS by modifying the FS list. In this case,
|
||||
// the NextSegment and RemainingURL variables will need to be modified. At this point in the stack the following
|
||||
// API variables look like this:
|
||||
//
|
||||
// HTTPMethod : PUT
|
||||
// SelfURL : <APIURL>/contacts
|
||||
// NextSegment : {KeyID}
|
||||
// FullEndPointURL : <APIURL>/contacts/{KeyID}/{property}
|
||||
//
|
||||
// The code will need to determine if a supported property has been passed in. If so, then the next HTTP service will
|
||||
// need to be called with the appropriate modifications to the variables.
|
||||
//----------------------------------------------------------------------------------------------------------------------
|
||||
PutItemProperty:
|
||||
|
||||
// Get the name of the property by looking at the last segment in the FullEndPointURL variable. An assumption is
|
||||
// being made that there are no other segments in the URL that follow the property name.
|
||||
Property = FullEndPointURL[-1, 'B/']
|
||||
Locate Property in AllowedServices using ',' setting ServicePos then
|
||||
// A supported property has been passed in the URL. Modify the NextSegment and RemainingURL variables so the
|
||||
// next HTTP service can be called correctly.
|
||||
NextSegment = Property ; // This allows the RunHTTPService to call HTTP_PICTURE_SERVICES.
|
||||
RemainingURL = '' ; // This variable won't be used in the HTTP_PICTURE_SERVICES code, but to keep the
|
||||
; // variables well formed, this should be cleared.
|
||||
HTTP_Services('RunHTTPService', NextSegment, RemainingURL)
|
||||
end else
|
||||
// The URL contains an unsupported property. Return a 404 error.
|
||||
HTTP_Services('SetResponseStatus', 404, Property : ' is not a valid service request within the ' : CurrentServiceHandler : ' module.')
|
||||
end
|
||||
|
||||
return
|
||||
|
||||
|
||||
//----------------------------------------------------------------------------------------------------------------------
|
||||
// GetItemProperty
|
||||
//
|
||||
// Returns the property of a specific resource.
|
||||
//
|
||||
// A property can be any specific data that is associated with the resource. It could be a column value, an image, a PDF
|
||||
// document, etc. In this case, the only property supported by this web API is the contact's "picture". The developer
|
||||
// can put add code here to return the picture or the developer can create another HTTP service to handle this. Since a
|
||||
// "picture" service might be useful as a property for other types of resources, a call to a dedicated "picture" HTTP
|
||||
// service will be made.
|
||||
//
|
||||
// Calling another HTTP service is similar to the way one MFS calls another MFS by modifying the FS list. In this case,
|
||||
// the NextSegment and RemainingURL variables will need to be modified. At this point in the stack the following
|
||||
// API variables look like this:
|
||||
//
|
||||
// HTTPMethod : GET
|
||||
// SelfURL : <APIURL>/contacts
|
||||
// NextSegment : {KeyID}
|
||||
// FullEndPointURL : <APIURL>/contacts/{KeyID}/{property}
|
||||
//
|
||||
// The code will need to determine if a supported property has been passed in. If so, then the next HTTP service will
|
||||
// need to be called with the appropriate modifications to the variables.
|
||||
//----------------------------------------------------------------------------------------------------------------------
|
||||
GetItemProperty:
|
||||
|
||||
// Get the name of the property by looking at the last segment in the FullEndPointURL variable. An assumption is
|
||||
// being made that there are no other segments in the URL that follow the property name.
|
||||
Property = FullEndPointURL[-1, 'B/']
|
||||
If Property _EQC 'picture' then
|
||||
// A supported property has been passed in the URL. Modify the NextSegment and RemainingURL variables so the
|
||||
// next HTTP service can be called correctly.
|
||||
NextSegment = Property ; // This allows the RunHTTPService to call HTTP_PICTURE_SERVICES.
|
||||
RemainingURL = '' ; // This variable won't be used in the HTTP_PICTURE_SERVICES code, but to keep the
|
||||
; // variables well formed, this should be cleared.
|
||||
HTTP_Services('RunHTTPService', NextSegment, RemainingURL)
|
||||
end else
|
||||
// The URL contains an unsupported property. Return a 404 error.
|
||||
HTTP_Services('SetResponseStatus', 404, Property : ' is not a valid service request within the ' : CurrentServiceHandler : ' module.')
|
||||
end
|
||||
|
||||
return
|
||||
|
||||
|
||||
//----------------------------------------------------------------------------------------------------------------------
|
||||
// OptionsItemProperty
|
||||
//
|
||||
// Sets the appropriate response header fields for an OPTIONS request.
|
||||
//----------------------------------------------------------------------------------------------------------------------
|
||||
OptionsItemProperty:
|
||||
|
||||
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
|
Reference in New Issue
Block a user