#1 2024-01-18 18:16:49

RaelB
Member
Registered: 2010-08-04
Posts: 57

Returning TServiceCustomStatus from interface method

Hi,

In SOA by Interfaces with custom HTTP Status you mention that TServiceCustomStatus was added and can be used as a return type for interface methods:

It won't change anything for mORMot client/server communication - just for non-mORMot HTTP clients, they will be able to check the HTTP response code.

So I have a method like this:

  INoteService = interface(IInvokable)
    ['{2B97D344-F806-4D6B-A3D9-56C61F9276BE}']
    ...
    function Delete(const NoteId: TID): TServiceCustomStatus;
  end;

  TNoteService = class(TInjectableObjectRest, INoteService)
  public
    ....
    function Delete(const NoteId: TID): TServiceCustomStatus;
  end;

function TNoteService.Delete(const NoteId: TID): TServiceCustomStatus;
begin
  Result := HTTP_NOCONTENT;
  Self.Server.Orm.Delete(TOrmNote, NoteId);
end;

If called from the mormot client: (vcl app)
NoteService.Delete(OrmNote.ID)

I get this error

Exception class EInterfaceFactory with message 'TInterfacedObjectFakeClient.FakeCall(INoteService.Delete) failed: 'Invalid returned JSON content: expects {result:...}, got ''. Process Project04InterfaceBasedClient.exe

If the delete method returns HTTP_SUCCESS, then there is no error.

I am doing this wrong?

Offline

#2 2024-01-19 11:13:32

RaelB
Member
Registered: 2010-08-04
Posts: 57

Re: Returning TServiceCustomStatus from interface method

I did a bit more testing. The error occurs only with a return of HTTP_NOCONTENT. Other return values, such as HTTP_BADREQUEST, HTTP_FORBIDDEN don't cause a problem.

Offline

#3 2024-01-19 14:19:40

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 14,686
Website

Re: Returning TServiceCustomStatus from interface method

This is as expected.
HTTP_NOCONTENT means no content returned, i.e. no response body.
So if you force HTTP_NOCONTENT in your method, nothing is returned (body length = 0).
And our REST protocol REQUIRES something to be returned.
Therefore, it fails.

TServiceCustomStatus is meant for web clients, not for mORMot clients.
HTTP_NOCONTENT should never be set in methods. It is an internal implementation detail of HTTP.
If your method returns HTTP_SUCESS with no body, then the web server itself will return a HTTP_NOCONTENT. Don't assign this status code manually.

Offline

#4 2024-01-19 15:38:30

RaelB
Member
Registered: 2010-08-04
Posts: 57

Re: Returning TServiceCustomStatus from interface method

I see, thanks for the info.

Offline

#5 2024-01-19 16:39:36

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 14,686
Website

Re: Returning TServiceCustomStatus from interface method

I have documented this behavior to be more explicit:
https://github.com/synopse/mORMot2/commit/3812dfb8

Offline

#6 2024-01-20 23:34:05

RaelB
Member
Registered: 2010-08-04
Posts: 57

Re: Returning TServiceCustomStatus from interface method

ab wrote:

If your method returns HTTP_SUCCESS with no body, then the web server itself will return a HTTP_NOCONTENT.

So I take it you're referring to when the rsoHttp200WithNoBodyReturns204 flag has been set. If this flag is not set, (and you want to return NOCONTENT) then you need to use TServiceCustomAnswer.

Offline

#7 2024-01-21 07:52:46

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 14,686
Website

Re: Returning TServiceCustomStatus from interface method

rsoHttp200WithNoBodyReturns204 is at REST level, but there is a similar automatic feature - with no flag, at HTTP server level IIRC.

Edit: I was wrong, there is no automated HTTP_NOCONTENT setting at HTTP server level.
But if you use TServiceCustomStatus, it is likely to have a JSON result content generated by the REST routing class, so there will be a body output, and HTTP_NOCONTENT won't be correct.
So you can't use TServiceCustomStatus to generate void content, but need to use TServiceCustomAnswer.

I tried to refine the doc again
https://github.com/synopse/mORMot2/commit/332ff138

Offline

Board footer

Powered by FluxBB