You are not logged in.
Pages: 1
Hi All,
I see that when implementing services interface based the framework always return 200.
But we whould like return others httpstatus.
then we discover TServiceCustomAnswer. this resolve the httpstatus problem, but this return do not accept parameters out neither var
sample. What i would like do:
function TProjetoService.GetProjetoPaineis(out pProjeto: TOrmProjeto): TServiceCustomAnswer;
begin
if not FRestOrm.Retrieve(pProjeto.Id, pProjeto) then
Result := ReturnError(Format('(%s) '+cErrorRecordNotFound, [GetClassName]), HTTP_NOTFOUND)
// else following the course, will return 200 ok!!!!
end;
function TServiceBase.ReturnError(const pErrorMessage: RawUTF8; pStatus: cardinal): TServiceCustomAnswer;
var
vError: Variant;
begin
TDocVariant.New(vError);
vError.ErrorMessage := pErrorMessage;
vError.StatusCode := pStatus;
Result.Content := VariantSaveJson(vError);
Result.Status := pStatus;
end;
How we can do this? What the recomendation?
Last edited by mrbar2000 (2023-03-06 14:01:48)
Offline
You are right, by design, interface-based services always return 200, as part of the routing scheme.
This is expected by the mORMot client.
If you want something more complex, for a non mORMot client, only method-based services are to be used.
Offline
Problem with this is that we have to treat all input/output parameters of service method, getting of Ctx. very hard work!
There are some other way?
Offline
> Problem with this is that we have to treat all input/output parameters of service method, getting of Ctx. very hard work!
Note for parsing input params you can use Ctx.GetInputAsTDocVariant to receive params as JSON document which is easy to parse.
Also when sending result you can do that as JSON which is easy to write/read on both server and client side.
Offline
Since it is not the first time this feature is asked, I have implemented it.
Please try
https://github.com/synopse/mORMot2/commit/7d36f145
Now you can write:
function TProjetoService.GetProjetoPaineis(out pProjeto: TOrmProjeto): TServiceCustomStatus;
This TServiceCustomStatus type is just a specific kind of cardinal parameter.
But now the result value (in range 200..599) will be propagated as HTTP response code.
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.
Offline
Very fast, Very thanks.
Offline
Hi, I make some changes in TServiceCustomStatus
and put a PR #160
What did u think?
Are u see some problem in my changes?
Offline
Good Morning Arnold,
I thought TServiceCustomStatus was only for non mormot clients.
Atualmente o mormot traz no result uma matriz com valores diversos. E não é possível ler isso de clientes não mormot. Veja isso.
TPaineis = array or TPainel
function BuscaPaineis(idProject: integer; out paineis: TPaineis): boolean;
// if I put an idProject that doesn't exist, for example, a Json arrives in this format:
{
"result" = [ [], false ]
}
// if I put an idProject that exists for example a Json arrives in this format:
{
"result" = [ [{"painel": 'painel1'}, {"painel": 'painel1'}], true ]
}
A non-mormot client is expecting just an array of TPainel. Which is not the case with the true and false into array.
An example response that mormot could return and handle without impacting applications that use interface-based SOA could look like this:
function BuscaPaineis(idProject: integer; out paineis: TPaineis): boolean;
{
"result" = [{"painel": 'painel1'}, {"painel": 'painel1'}],
"return" = true
}
I will further detail the problems I am trying to solve as I want to work with interface based SOA. But I need the mormot server to return the JSON in a way that can be read by any 3rd party application.
1) Return the custom HTTP code
2) The returned JSON should follow a pattern for when the result is 200..399.
3) When the return is 400..599 I need the returned JSON to follow an exception pattern with the proper error message. This type really should not be an exception, even though they are expected errors. They should not be logged or handled by the framework.
When I use TServiceCustomStatus I can return the statuscode that I want, great!
But when I return a code between 400...599 I have to return a Json with the reason for this error.
So I thought of TServiceCustomStatus as a record. And I adjusted the code so that anyone who wants to use Mormot and is not using a Mormot client.
Maybe a way to standardize this would be that every return from mormot would return
{
"<result> or <classname>": <Jsonobject> or <JsonArray>
"errormessage": "<empty> or <custom error message>" <<< not out parameter but a TServiceCustomStatus.ErroMessage field
"return" : <null is procedure> or <value of function result> <<< if function is TServiceCustomStatus then TServiceCustomStatus.Status
}
Without losing the cardinal TServiceCustomStatus obviously. HTTPStatus code would return TServiceCustomStatus.Status too.
I'm asking this because my frontend tool (as well as many others) already evaluates the http statuscode to be able to direct the workflow to a success or error routine.
We don't always have control over the frontend that will be using our API, and some of these clients don't have the facility to change their programming.
I know someone here may say that it is the clients that should implement according to the API specification, but I have clients that use no-code tools that just receive the json and treat this json according to the returned http statuscode.
In summary. Your mormot clients would not have to change their programming at all, because if I have the following methods in the interface they would return the following json:
function TABC.FindOrder(Id: Integer; out Order: TOrder; out Items: TItems): TServiceCustomStatus;
{
"output1" or "order": { "id": 1, ... }
"output2" or "items": [{ "id": 10, ... }, { "id": 11, ... }, { "id": 12, ... }]
"errormessage": ""
"return" : 200 <<<< the same of HTTPStatus code returned
}
function TABC.FindOrder(Id: Integer; out Order: TOrder; out Items: TItems): boolean;
{
"output1" or "order": { "id": 1, ... }
"output2" or "items": [{ "id": 10, ... }, { "id": 11, ... }, { "id": 12, ... }]
"errormessage": ""
"return" : true <<<< HTTPStatus code always 200 if result <> TServiceCustomStatus
}
To internaol SOA process, "errormessage" field would be ignored unless the programmer put an out errormessage in the parameters.
Offline
What u think Arnold?
What i can see about the code, all workflow abou soa via interfaces is internal. Then i think this idea is viable.
Offline
Arnold, I would like to thank you for your comments here and apologize for the lack of knowledge in the framework, I'm still new to mormot, but I'll get there. Digging around the framework I discovered the properties:
TServiceFactoryServer's SetWholeOption([???])
optResultAsJsonObjectWithoutResult or optResultAsJsonObject
I just put the optResultAsJsonObjectWithoutResult option and the json I wanted was already returned the way I needed it.
function Busca(pId: Int64; var abc: TDTOProjeto; out pProjeto: TDTOProjeto; out pPaineis: TDTOPaineis): TServiceCustomStatus;
{
"abc": {
"RowID": 1,
"Nome": "Projeto c",
"DataCriacao": "2023-03-18T12:34:09",
"UltimaAlteracao": "2023-03-18T12:34:09",
"IdCriador": 5,
"Paineis": []
},
"pProjeto": {
"RowID": 1,
"Nome": "Projeto c",
"DataCriacao": "2023-03-18T12:34:09",
"UltimaAlteracao": "2023-03-18T12:34:09",
"IdCriador": 5,
"Paineis": [
{
"RowID": 1,
"Nome": "painel a",
"DataCriacao": "2023-03-20T10:08:48",
"UltimaAlteracao": "2023-03-20T10:08:48",
"IdCriador": 5,
"IdProjeto": 1
}
]
},
"pPaineis": [
{
"RowID": 1,
"Nome": "painel a",
"DataCriacao": "2023-03-20T10:08:48",
"UltimaAlteracao": "2023-03-20T10:08:48",
"IdCriador": 5,
"IdProjeto": 1
}
],
"Result": 0
}
long live the mormot!
Offline
Pages: 1