MATLAB: Handling errors of type application/json when using webread

error handlingjsonMATLABwebread

Having trouble with how MATLAB interpret's the message of a server error when type is of application/json.
Problem
Calling a local API, the following error is returned:
{"errorCode":401,"message":"Access to mylocalapi not authorized"}
Calling this using webread in MATLAB, the following exception is generated. Note the message has been stripped out of the exception.
Error using matlab.internal.webservices.HTTPConnectionAdapter/copyContentToByteArray
The server returned the status 401 with message "" in response to the request to URL http://mylocalapi
Error in webread (line 125)
[varargout{1:nargout}] = readContentFromWebService(connection, options);
Assessment
The error handler in HTTPConnectionAdapter does not seem to find the message part of the error. The response was compliant with the odata and Google API standards, but need to recognise there is no clear standard here. My problem is that the content has been stripped out by the time the response is returned as an MException object.
The only way around this seems to be to define a custom ContentReader in weboptions, however this has a performance impact across the full application, due to local disk i/o and poor ContentReader code on the part of the user.
Otherwise, the HTTPConnector generates the following MException
e =
MException with properties:
identifier: 'MATLAB:webservices:StatusError'
message: 'The server returned the status 401 with message "" in response to the request to URL http://mylocalapi.'
cause: {0×1 cell}
stack: [11×1 struct]
e.stack(1)
ans =
struct with fields:
file: 'D:\MATLAB\R2018b\toolbox\matlab\external\interfaces\webservices\restful\+matlab\+internal\+webservices\HTTPConnector.m'
name: 'HTTPConnector.copyContentToByteArray'
line: 361
Might it be possible to extend the MException class to have a HTTPException with additional fields such as the full error response?
For info, the following weboptions are being sent with the request.
options =
weboptions with properties:
CharacterEncoding: 'auto'
UserAgent: 'MATLAB 9.5.0.1067069 (R2018b) Update 4'
Timeout: 5
Username: ''
Password: ''
KeyName: ''
KeyValue: ''
ContentType: 'json'
ContentReader: []
MediaType: 'application/json'
RequestMethod: 'get'
ArrayFormat: 'json'
HeaderFields: {1×2 cell}
CertificateFilename: 'D:\MATLAB\R2018b\sys\certificates\ca\rootcerts.pem'
Apologies if this is non-reproducable, however it is using a local service.

Best Answer

Hi Ciaran,
I'm not sure I completely understand what your API returns. It's not clear to me that the HTTP Response has a status code 401 and a Body "Access to mylocalapi not authorized", or if it returns some 2XX code with a JSON payload as you describe.
I'm not aware of a way to get "webread" to return the response payload in case of non 2XX or 3XX status code.
Maybe to get a better understanding of this, could you use the HTTP interface to see what response you get, using this starting snippet?
request = matlab.net.http.RequestMessage();
request.Method = 'GET';
request.Header = [ ...
matlab.net.http.field.ContentTypeField( 'application/json' ), ...
matlab.net.http.field.AcceptField( 'application/json' ), ...
];
response = request.send( 'https://www.google.com/doesntexist' );
disp( response )
disp( response.Body )
For reference, not the outcome of:
webreadResponse = webread( 'https://www.google.com/doesntexist' )
From this, you can see you get an MException, whose message is completely formed from the response.StatusLine. It makes no use of the response payload, that you can see in the reponse.Body.
Can you post what the reponse and response.Body would be in your case?