matlab.net.http.io.ContentProvider - ContentProvider for HTTP message payloads - MATLAB (original) (raw)
Namespace: matlab.net.http.io
Superclasses: handle, matlab.mixin.Heterogeneous
ContentProvider for HTTP message payloads
Description
A ContentProvider supplies data for an HTTPRequestMessage
while the message is being sent. A simple provider converts data from a MATLABĀ® type to a byte stream. More complex providers can stream data to the server, obtaining or generating the data at the same time it is being sent, which avoids the need to have all the data in memory before the start of the message.
Normally, when sending data to a web service (typically in a PUT or POST request), you would create a RequestMessage
and insert data in the form of aMessageBody
object in the RequestMessage.Body
property. When you send that message using RequestMessage.send
, MATLAB converts that data into a byte stream to be sent to the server, converting it based on the Content-Type of the message and the type of data inBody.Data
. See MessageBody.Data
for these conversion rules.
Instead of inserting a MessageBody
object into theRequestMessage.Body
property, you can create aContentProvider
object and insert that instead. Then, when you send the message, MATLAB calls methods in the ContentProvider
to obtain buffers of data to send, while the message is being sent.
Whether you insert a MessageBody
or a ContentProvider
into the message, the call to RequestMessage.send
does not return (that is, it is blocked) until the entire message has been sent and a response has been received, or an error has occurred. But with a ContentProvider
, MATLAB makes periodic callbacks into the provider to obtain buffers of data to send, during the time send is blocked. In these callbacks, your ContentProvider
can obtain data from any source such as a file, a MATLAB array, a hardware sensor, a MATLAB function, etc. The provider's job is to convert that data to a byte stream, in the form of uint8 buffers, that can be sent to the web.
ContentProvider
is an abstract class designed for class authors to subclass with their own data generator or converter, or you can use (or subclass) one of the MATLAB providers that generate the data for you from various sources, without writing a subclass. These providers have options that give you more flexible control over how data is obtained and converted, compared to the automatic conversions that occur when you insert data directly into a MessageBody
. Use one of the ContentProvider
subclasses:
- FileProvider
- StringProvider
- JSONProvider
- ImageProvider
- FormProvider
- MultipartProvider
- MultipartFormProvider
- GenericProvider
Even if you do not need to stream data, using one of these providers can simplify the process of sending certain types of content, as they convert data from an internal form into auint8
stream. For example, FormProvider
lets you send form responses to a server, where you can conveniently express the data as an array ofQueryParameter
objects. MultipartFormProvider
lets you send multipart form responses, simplifying the creation of responses to multipart forms. To use anyContentProvider
, you need to understand the type of content that the server expects you to send.
The matlab.net.http.io.ContentProvider
class is a handle class.
Subclass Authors
The simplest possible ContentProvider
need only implement agetData
method to provide buffers of data as MATLAB requests them. To use your provider, insert it into in theBody
property of the RequestMessage
. In this example, the third argument to the RequestMessage
constructor, aMyProvider
object, goes into the Body
:
provider = MyProvider; req = matlab.net.http.RequestMessage('put', headers, provider); resp = req.send(uri);
Here is an example a MyProvider
class that reads from a file name passed in as an argument to the constructor and sends it to the web. For good measure, we close the file at the end or when this provider is deleted.
classdef MyProvider < matlab.net.http.io.ContentProvider
properties
FileID double
end
methods
function obj = MyProvider(name)
obj.FileID = fopen(name);
end
function [data, stop] = getData(obj, length)
[data, len] = fread(obj.FileID, length, '*uint8');
stop = len < length;
if (stop)
fclose(obj.FileID);
obj.FileID = [];
end
end
function delete(obj)
if ~isempty(obj.FileID)
fclose(obj.FileID);
obj.FileID = [];
end
end
end
end
MATLAB calls a provider's complete
method when it is forming a new message to send. The purpose is to allow the provider to prepare for a new message and add any required header fields to the message. MATLAB calls a provider's start
method when it is time to send the data, but before the first call to getData
.
Properties
Public Properties
Header fields of the message or part, specified as a vector of one or morematlab.net.http.HeaderField
objects.
This property is only used by subclass authors. MATLAB sets this property before calling the provider's complete method. For non-multipart messages, MATLAB initializes this property to the contents ofRequest.Header
, minus any matlab.net.http.field.GenericFields or empty-valued fields. The ContentProvider
uses this property to add header fields that describe the data to be sent, or to add parameters to header fields already in the message. In a delegate for a MultipartProvider
, MATLAB initializes this property to header fields that the delegating provider intends to insert for the part. Delegates can modify or change these fields.
Upon return from the provider's complete
method, if this not a multipart message, then MATLAB reads this property and merges its contents into the header ofRequest
. Fields in this Header
withNames
that do not already appear inRequest.Header
are added to the end ofRequest.Header
. If a field in this Header
has a Name
that is the same as one inRequest.Header
, and both have nonemptyValues
, then:
- If the one in
Request.Header
is aGenericField
, then ignore the one inHeader
. - If the one in
Request.Header
is not aGenericField
, then replace it with the one inHeader
.
If one or both of these has an empty Value
, then the field is removed from Request.Header
and it is not added as part of normal message completion.
If this is a delegate of a MultipartProvider
, then the entire contents of this Header
is used as the header of the part. Multipart delegates must not assume that Request.Header
contains any fields pertaining to their own Header
. A provider can determine whether it is a multipart delegate by checking whether MyDelegator
is aMultipartProvider
, though this test is unlikely to be needed.
MATLAB reads this property only on return from calling the provider'scomplete
method. Changes to this array are ignored once MATLAB calls start
.
Class authors should be aware that their subclasses might have added fields to thisHeader
(in their complete
method) before calling complete
in their superclass. It is best to preserve such fields and not to add fields with the same names. However, adding a parameter to a field is permissible. For example, a superclass can add a charset parameter to an existing Content-Type field that does not already have one.
Attributes:
GetAccess | public |
---|---|
SetAccess | public |
Indicate whether to force chunked transfer coding, specified as boolean. This property is of interest only to subclass authors, and is applicable only to providers that are not multipart delegates. Subclasses set ForceChunked
to control whether contents should be sent using chunked transfer coding. If false
(default), MATLAB decides whether to send the contents chunked, based on whether it knows the content length at the time the message is ready to be sent:
- If MATLAB knows the content length (which is the case if the message contains a Content-Length field, or if this provider's expectedContentLength method returned a number), then MATLAB decides whether to send it chunked or not.
- If MATLAB does not know the content length (no Content-Length field in the header and
expectedContentLength
returned empty), then MATLAB always sends the message chunked.
If ForceChunked
is true
, then MATLAB sends the message chunked regardless of whether it knows the content length, unless the known length is smaller than the chunk size. If this property is true
, then the message must not contain a Content-Length field, because HTTP does not allow a chunked message to have a Content-Length field. However, you can still return a nonzero value in the expectedContentLength
method if you want MATLAB to verify that you are returning the expected length of data.
When MATLAB chooses to send the message chunked, the size of each chunk is equal to the length of data returned by getData.
MATLAB reads this value after calling the complete method, before calling start. It does not set this field.
Attributes:
GetAccess | public |
---|---|
SetAccess | public |
Request message to send, specified as a matlab.net.http.RequestMessage
object.
This property is used only by subclass authors. TheRequestMessage.send
and RequestMessage.complete
methods set this property to the RequestMessage
in whoseBody
this provider has been placed, before calling any other methods in this provider, and before adding any additional header fields or validating the message. The provider can examine this message to see what was contained in the original request.
Delegates see the same value for this property as the delegator.ContentProviders
should be aware that, if they are delegates, they are not necessarily providing the entire body of the request message, so they should not assume that header fields in this Request are pertinent to the data they are providing. Usually, delegates should ignore header fields in this request relevant to the data, such as Content-Type.
If the provider wishes to add any header fields to this message, or to modify existing ones, it should do so in its complete method by adding those fields to the Header
property. The caller ofcomplete
(RequestMessage
or a delegating provider) determines what to do with those fields. RequestMessage.send
andRequestMessage.complete
always copy these fields to theHeader
of the RequestMessage
. A delegating provider can copy the fields to its own Header
property or insert them into the message (as in the case of MultipartProvider
). For more information, see the Header property.
This property is read-only.
Attributes:
GetAccess | public |
---|---|
SetAccess | matlab.net.http.RequestMessage |
Protected Properties
ContentProvider
to which this provider is delegating, specified as a matlab.net.http.io.ContentProvider
object. This property is set in the calling provider (the delegator) by the delegateTo method to indicate the current delegated provider. If there is no current delegation, then the value is empty.
The complete methods set this property to empty.
Attributes:
GetAccess | protected |
---|---|
SetAccess | protected |
ContentProvider
that delegated to this provider, specified as a matlab.net.http.io.ContentProvider
object.
If a ContentProvider
delegates responsibility for sending all or a portion of the message data to another provider, then this property identifies the delegating provider to the delegate. For example, a MultipartProvider
delegates parts of the message to other providers, so it inserts a handle to itself in each delegate. Otherwise, MyDelegator
is empty. The delegateTo method sets this property in the delegate.
Attributes:
GetAccess | protected |
---|---|
SetAccess | protected |
Methods
string | Show ContentProvider as string |
---|---|
show | Display ContentProvider information |
getData | Next buffer of data to send in HTTP request message from ContentProvider |
---|
More About
A provider can be restartable and/or reusable. Restartable means that the provider is able to resend the same message multiple times, with the same data stream each time MATLAB calls start
, even if the previous use did not end in a normal completion. This behavior is needed because the server can redirect a message to a different server, which means the data needs to be retransmitted. In that case MATLAB calls start
without calling complete
again. MATLAB calls the restartable
method to determine whether a provider can be restarted. If false, MATLAB throws an exception if it needs to call start
on a provider that has already been started, if there was no intervening call to complete
(which happens only on a new message).
Reusable means that the provider can be reused for a different (or the same) message, each time MATLAB calls its complete
method. MATLAB calls the reusable
method to determine whether a provider can be reused. If false
, then MATLAB throws an exception if it needs to call complete
on a provider that has already been started. If a provider is reusable, then the assumption is that the next call to start
should succeed, even if the provider is restartable.
ContentProvider
returns false
for bothrestartable
and reusable
, so if you are extending this base class directly with a restartable or reusable provider, you should override one or both of these methods to return true
. All concrete subclasses ofContentProvider
in the matlab.net.http.io
namespace are both restartable and reusable, so they return true for these methods. If you are extending one of those subclasses with a provider that is not reusable or restartable, override one or both of those methods to return false.
The MyProvider
class in this example is not restartable or reusable, because the provider closes the file at the end of the message. To make it reusable, thefopen
call should take place in the complete
method instead of the constructor, thereby restoring the provider's state back to what it was before it was used for a message.
classdef MyProvider < matlab.net.http.io.ContentProvider
properties
FileID double
Name string
end
methods
function obj = MyProvider(name)
obj.Name = name;
end
function [data, stop] = getData(obj, length)
...as above...
end
function complete(obj, uri)
obj.FileID = fopen(name);
obj.complete@matlab.net.http.io.ContentProvider();
end
function tf = reusable(~)
tf = true;
end
function delete(obj)
...as above...
end
end
end
To make the provider restartable, add restartable
andstart
methods and issue an fseek
in thestart
method to "rewind" the file:
function start(obj)
obj.start@matlab.net.http.io.ContentProvider();
fseek(obj.FileID, 0, -1);
end
function tf = restartable(~)
tf = true;
end
When you call complete
or send
on aRequestMessage
that contains a ContentProvider
in its body, MATLAB sets the Request
property in the provider to theRequestMessage
in which the provider was placed and theHeader
property to the headers in the Request
, before adding automatic fields. It then calls the following methods in the provider, in this order:
complete
- called on message completion, which usually happens once per message, when you callRequestMessage.send
orRequestMessage.complete
. The provider is expected to set itsHeader
property to any header fields to be added to the message specific to the provider. If MATLAB calls this method a subsequent time, the provider should assume it is being used for a new message. Most providers need to implement this method to add their headers and then, if they are not a direct subclass of this abstract class, they should call their superclass complete to invoke any additional default behavior. MATLAB does not callcomplete
more than once in a provider, unless its reusable method returns true. This abstract class is not reusable by default, but all concrete providers in thematlab.net.http.io
namespace are reusable.preferredBufferSize
/expectedContentLength
- called fromRequestMessage.send
, sometime aftercomplete
, before a call tostart
. Most providers need not implement these methods, as the default behavior is appropriate. However, providers can override this to support theforce
argument.
After return from these methods, MATLAB sends the header of the RequestMessage
to the server. When it is time to send the body, MATLAB calls these methods.
start
- called fromRequestMessage.send
, sometime after calling the previous methods, when MATLAB has determined that the server is ready to receive the body of the request message. If MATLAB calls this a subsequent time, without an intervening complete, the provider should assume it is being asked to resend the body of the same message (with the same headers) once again. MATLAB does not call start more than once since the last call tocomplete
, unless the provider'srestartable
method returnstrue
. This abstract class is not restartable by default, but all concrete providers in thematlab.net.http.io
namespace, are restartable.getData
- called multiple times after the call tostart
, whileRequestMessage.send
is blocked, each time MATLAB determines that the server is ready for a new buffer of data. The method must return auint8
vector of data. The provider signals the end of the data by returning astop
indicator. All providers must implement this method.
After getData
returns a stop
indicator, MATLAB ends the request message and awaits a response from the server.
A ContentProvider
that is inserted into aRequestMessage.Body
can delegate to one or more other providers to provide all or some of the data for the message. For example, aMultipartProvider
creates a message with multiple parts, each of which is provided by other providers specified to the MultipartProvider
constructor. In this case, MultipartProvider
is the delegator, and the other providers are the delegates, each one being called in turn to provide its own header fields and its portion of the data.
A provider delegates to another by calling delegateTo
, which setsCurrentDelegate
to the delegate and the delegate'sMyDelegator
to the current provider (that is, the delegator), and then calls the delegate's complete
and start
methods and returns a GetDataFcn
function handle. Then the delegator'sgetData
method calls the delegate's GetDataFcn
to obtain the data, possibly altering it before returning it to MATLAB. Providers generally do not have to check whether they are delegates, or who delegated to them.
Version History
Introduced in R2018a