Quellcode durchsuchen

* error handling is slightly different in ext.direct. Create virtual method so it can be overridden

git-svn-id: trunk@15668 -
michael vor 15 Jahren
Ursprung
Commit
e1a8b5ad38
1 geänderte Dateien mit 46 neuen und 24 gelöschten Zeilen
  1. 46 24
      packages/fcl-web/src/jsonrpc/fpjsonrpc.pp

+ 46 - 24
packages/fcl-web/src/jsonrpc/fpjsonrpc.pp

@@ -133,6 +133,7 @@ Type
     FOnStartBatch: TNotifyEvent;
     FOptions: TJSONRPCDispatchOptions;
   Protected
+
     // Find handler. If none found, nil is returned. Executes OnFindHandler if needed.
     // On return 'DoFree' must be set to indicate that the hand
     Function FindHandler(Const AClassName,AMethodName : TJSONStringType;AContext : TJSONRPCCallContext; Out FreeObject : TComponent) : TCustomJSONRPCHandler; virtual;
@@ -151,6 +152,9 @@ Type
     Function CheckRequests(Requests : TJSONData) : TJSONData; virtual;
     // Format result of a single request. Result is returned to the client, possibly in an array if multiple requests were received in batch.
     Function FormatResult(const AClassName, AMethodName: TJSONStringType;  const Params, ID, Return: TJSONData) : TJSONData; virtual;
+    // Format error of a single request.
+    function CreateJSON2Error(Const AMessage : String; Const ACode : Integer; ID : TJSONData = Nil; idname : TJSONStringType = 'id' ) : TJSONObject; virtual;
+    function CreateJSON2Error(Const AFormat : String; Args : Array of const; Const ACode : Integer; ID : TJSONData = Nil; idname : TJSONStringType = 'id') : TJSONObject;
     // Hooks for user.
     Property OnStartBatch : TNotifyEvent Read FOnStartBatch Write FOnStartBatch;
     Property OnDispatchRequest : TDispatchRequestEvent Read FOnDispatchRequest Write FOnDispatchRequest;
@@ -414,11 +418,18 @@ end;
 { TJSONParamDef }
 
 procedure TJSONParamDef.SetName(const AValue: TJSONStringType);
+
+Var
+  D: TJSONParamDef;
+
 begin
   if FName=AValue then exit;
   If Assigned(Collection) and (Collection is TJSONParamDefs) then
-    if (Collection as TJSONParamDefs).FindParamDef(AValue)<>Nil then
+    begin
+    D:=(Collection as TJSONParamDefs).FindParamDef(AValue);
+    If (D<>Nil) and (D<>Self) then
       JSONRPCError(SErrDuplicateParam,[AValue]);
+    end;
   FName:=AValue;
 end;
 
@@ -646,9 +657,9 @@ begin
   H:=FindHandler(AClassName,AMethodName,AContext,FreeObject);
   If (H=Nil) then
     if (AClassName='') then
-      Exit(CreateJSON2ErrorResponse(SErrInvalidMethodName,[AMethodName],EJSONRPCMethodNotFound,ID.Clone,transactionProperty))
+      Exit(CreateJSON2Error(SErrInvalidMethodName,[AMethodName],EJSONRPCMethodNotFound,ID.Clone,transactionProperty))
     else
-      Exit(CreateJSON2ErrorResponse(SErrInvalidClassMethodName,[AClassName,AMethodName],EJSONRPCMethodNotFound,ID.Clone,transactionProperty));
+      Exit(CreateJSON2Error(SErrInvalidClassMethodName,[AClassName,AMethodName],EJSONRPCMethodNotFound,ID.Clone,transactionProperty));
   try
     If Assigned(FOndispatchRequest) then
       FOndispatchRequest(Self,AClassName,AMethodName,Params);
@@ -668,6 +679,19 @@ begin
     TJSONObject(Result).Add('jsonrpc','2.0');
 end;
 
+function TCustomJSONRPCDispatcher.CreateJSON2Error(const AMessage: String;
+  const ACode: Integer; ID: TJSONData; idname: TJSONStringType): TJSONObject;
+begin
+  Result:=CreateJSON2ErrorResponse(AMessage,ACode,ID,IDName);
+end;
+
+function TCustomJSONRPCDispatcher.CreateJSON2Error(const AFormat: String;
+  Args: array of const; const ACode: Integer; ID: TJSONData;
+  idname: TJSONStringType): TJSONObject;
+begin
+  Result:=CreateJSON2Error(Format(AFormat,Args),ACode,ID,IDName);
+end;
+
 function TCustomJSONRPCDispatcher.ExecuteRequest(ARequest: TJSONData;AContext : TJSONRPCCallContext): TJSONData;
 
 Var
@@ -687,21 +711,19 @@ begin
         begin
         // No response, and a response was expected.
         if (ID<>Nil) or not (jdoNotifications in Options) then
-          Result:=CreateJSON2ErrorResponse(SErrNoResponse,[M],EJSONRPCInternalError,ID,transactionProperty);
+          Result:=CreateJSON2Error(SErrNoResponse,[M],EJSONRPCInternalError,ID,transactionProperty);
         end
       else
         begin
         // A response was received, and no response was expected.
         if ((ID=Nil) or (ID is TJSONNull))  and (jdoStrictNotifications in Options) then
-          Result:=CreateJSON2ErrorResponse(SErrResponseFromNotification,[M],EJSONRPCInternalError,ID,transactionProperty);
+          Result:=CreateJSON2Error(SErrResponseFromNotification,[M],EJSONRPCInternalError,ID,transactionProperty);
         If (ID=Nil) or (ID is TJSONNull) then // Notification method, discard result.
           FreeAndNil(Result);
         end;
       end;
     If Assigned(Result) and not (Result is TJSONErrorObject) then
-      begin
-      Result:=FormatResult(C,M,P,ID,Result);
-      end;
+        Result:=FormatResult(C,M,P,ID,Result)
   except
     // Something went really wrong if we end up here.
     On E : Exception do
@@ -709,9 +731,9 @@ begin
       If (Result<>Nil) then
         FreeAndNil(Result);
       If Assigned(ID) then
-        Result:=CreateJSON2ErrorResponse(E.Message,EJSONRPCInternalError,ID.Clone,transactionproperty)
+        Result:=CreateJSON2Error(E.Message,EJSONRPCInternalError,ID.Clone,transactionproperty)
       else
-        Result:=CreateJSON2ErrorResponse(E.Message,EJSONRPCInternalError,Nil,transactionproperty)
+        Result:=CreateJSON2Error(E.Message,EJSONRPCInternalError,Nil,transactionproperty);
       end;
   end;
 end;
@@ -757,7 +779,7 @@ begin
   Params:=Nil;
   Result:=Nil;
   If Not (Request is TJSONObject) then
-    Exit(CreateJSON2ErrorResponse(SErrRequestMustBeObject,EJSONRPCInvalidRequest,Nil,transactionproperty));
+    Exit(CreateJSON2Error(SErrRequestMustBeObject,EJSONRPCInvalidRequest,Nil,transactionproperty));
   O:=TJSONObject(Request);
   // Get ID object, if it exists.
   I:=O.IndexOfName(TransactionProperty);
@@ -765,31 +787,31 @@ begin
     ID:=O.Items[i];
   // Check ID
   If (ID=Nil) and not (jdoNotifications in Options) then
-    Exit(CreateJSON2ErrorResponse(SErrNoIDProperty,EJSONRPCInvalidRequest,Nil,transactionproperty));
+    Exit(CreateJSON2Error(SErrNoIDProperty,EJSONRPCInvalidRequest,Nil,transactionproperty));
   OJ2:=(jdoJSONRPC2 in Options) and not (jdoJSONRPC1 in Options);
   If OJ2 then
     begin
     if Assigned(ID) and not (ID.JSONType in [jtNull,jtString,jtNumber]) then
-      Exit(CreateJSON2ErrorResponse(SErrINvalidIDProperty,EJSONRPCInvalidRequest,Nil,transactionproperty));
+      Exit(CreateJSON2Error(SErrINvalidIDProperty,EJSONRPCInvalidRequest,Nil,transactionproperty));
     // Check presence and value of jsonrpc property
     I:=O.IndexOfName('jsonrpc');
     If (I=-1) then
-      Exit(CreateJSON2ErrorResponse(SErrNoJSONRPCProperty,EJSONRPCInvalidRequest,ID,transactionproperty));
+      Exit(CreateJSON2Error(SErrNoJSONRPCProperty,EJSONRPCInvalidRequest,ID,transactionproperty));
     If (O.Items[i].JSONType<>jtString) or (O.Items[i].AsString<>'2.0') then
-      Exit(CreateJSON2ErrorResponse(SErrInvalidJSONRPCProperty,EJSONRPCInvalidRequest,ID,transactionproperty));
+      Exit(CreateJSON2Error(SErrInvalidJSONRPCProperty,EJSONRPCInvalidRequest,ID,transactionproperty));
     end;
   // Get method name, if it exists.
   I:=O.IndexOfName(MethodProperty);
   If (I<>-1) then
     D:=O.Items[i]
   else
-    Exit(CreateJSON2ErrorResponse(SErrNoMethodName,[MethodProperty],EJSONRPCInvalidRequest,ID,transactionproperty));
+    Exit(CreateJSON2Error(SErrNoMethodName,[MethodProperty],EJSONRPCInvalidRequest,ID,transactionproperty));
   // Check if it is a string
   if Not (D is TJSONString) then
-    Exit(CreateJSON2ErrorResponse(SErrInvalidMethodType,[MethodProperty],EJSONRPCInvalidRequest,ID,transactionproperty));
+    Exit(CreateJSON2Error(SErrInvalidMethodType,[MethodProperty],EJSONRPCInvalidRequest,ID,transactionproperty));
   AMethodName:=D.AsString;
   If (AMethodName='') then
-    Exit(CreateJSON2ErrorResponse(SErrNoMethodName,[MethodProperty],EJSONRPCInvalidRequest,ID,transactionproperty));
+    Exit(CreateJSON2Error(SErrNoMethodName,[MethodProperty],EJSONRPCInvalidRequest,ID,transactionproperty));
   // Get class name, if it exists and is required
   If (ClassNameProperty<>'') then
     begin
@@ -797,31 +819,31 @@ begin
     If (I<>-1) then
       D:=O.Items[i]
     else if (jdoRequireClass in options) then
-      Exit(CreateJSON2ErrorResponse(SErrNoClassName,[ClassNameProperty],EJSONRPCInvalidRequest,ID,transactionproperty));
+      Exit(CreateJSON2Error(SErrNoClassName,[ClassNameProperty],EJSONRPCInvalidRequest,ID,transactionproperty));
     // Check if it is a string
     if Not (D is TJSONString) then
-      Exit(CreateJSON2ErrorResponse(SErrInvalidClassNameType,[ClassNameProperty],EJSONRPCInvalidRequest,ID,transactionproperty));
+      Exit(CreateJSON2Error(SErrInvalidClassNameType,[ClassNameProperty],EJSONRPCInvalidRequest,ID,transactionproperty));
     AClassName:=D.AsString;
     If (AMethodName='') and (jdoRequireClass in options)  then
-      Exit(CreateJSON2ErrorResponse(SErrNoClassName,[ClassNameProperty],EJSONRPCInvalidRequest,ID,transactionproperty));
+      Exit(CreateJSON2Error(SErrNoClassName,[ClassNameProperty],EJSONRPCInvalidRequest,ID,transactionproperty));
     end;
   // Get params, if they exist
   I:=O.IndexOfName(ParamsProperty);
   If (I<>-1) then
     D:=O.Items[i]
   else
-    Exit(CreateJSON2ErrorResponse(SErrNoParams,[ParamsProperty],EJSONRPCInvalidParams,ID,transactionproperty));
+    Exit(CreateJSON2Error(SErrNoParams,[ParamsProperty],EJSONRPCInvalidParams,ID,transactionproperty));
   if OJ2 then
     begin
     // Allow array or object
     If Not (D.JSONType in [jtArray,jtObject]) then
-      Exit(CreateJSON2ErrorResponse(SErrParamsMustBeArrayorObject,EJSONRPCInvalidParams,ID,transactionproperty));
+      Exit(CreateJSON2Error(SErrParamsMustBeArrayorObject,EJSONRPCInvalidParams,ID,transactionproperty));
     end
   else if not (jdoJSONRPC2 in Options) then
     begin
     // Allow only array
     If Not (D.JSONType in [jtArray]) then
-      Exit(CreateJSON2ErrorResponse(SErrParamsMustBeArray,EJSONRPCInvalidParams,ID,transactionproperty));
+      Exit(CreateJSON2Error(SErrParamsMustBeArray,EJSONRPCInvalidParams,ID,transactionproperty));
     end;
   Params:=D;
 end;