* Support for content-disposition: attachment

This commit is contained in:
Michaël Van Canneyt 2023-08-27 16:09:43 +02:00
parent 1886fad528
commit 81a1447b54
7 changed files with 85 additions and 8 deletions

View File

@ -85,7 +85,9 @@ Type
Public
Destructor Destroy; override;
Class Function GetContentType: String; override;
Class function FileExtension : string; override;
function RequireMetadata : Boolean; override;
procedure InitStreaming; override;
Property DataName : UTF8String Read FDataName Write FDataName;
Property RowName : UTF8String Read FRowName Write FRowName;
@ -359,6 +361,13 @@ begin
Result:='text/xml';
end;
Class function TADOOutputStreamer.FileExtension : string;
begin
Result:='.xml';
end;
function TADOOutputStreamer.RequireMetadata: Boolean;
begin
Result:=True;

View File

@ -310,6 +310,8 @@ Type
function ResolvedCORSAllowedOrigins(aRequest: TRequest): String; virtual;
procedure HandleCORSRequest(aConnection: TSQLDBConnectionDef; IO: TRestIO); virtual;
procedure HandleResourceRequest(aConnection : TSQLDBConnectionDef; IO: TRestIO); virtual;
procedure HandleCorsResponseHeaders(IO: TRestIO); virtual;
procedure HandleOtherResponseHeaders(IO: TRestIO); virtual;
procedure DoHandleRequest(IO: TRestIO); virtual;
Public
Class Procedure SetIOClass (aClass: TRestIOClass);
@ -1937,6 +1939,41 @@ begin
end;
end;
procedure TSQLDBRestDispatcher.HandleCorsResponseHeaders(IO : TRestIO);
begin
if (rdoHandleCORS in DispatchOptions) then
begin
IO.Response.SetCustomHeader('Access-Control-Allow-Origin',ResolvedCORSAllowedOrigins(IO.Request));
IO.Response.SetCustomHeader('Access-Control-Allow-Credentials',BoolToStr(CORSAllowCredentials,'true','false'));
end;
end;
procedure TSQLDBRestDispatcher.HandleOtherResponseHeaders(IO : TRestIO);
Var
Qn,CD : String;
HaveHeader : Boolean;
begin
QN:=IO.RestStrings.AttachmentParam;
With IO.Request.QueryFields do
begin
HaveHeader:=(IndexOfName(QN)<>-1);
Cd:=values[QN];
end;
if (CD<>'') or HaveHeader then
begin
If CD='' then
begin
CD:=IO.ResourceName;
CD:=CD+IO.RESTOutput.FileExtension;
end;
IO.Response.SetCustomHeader('Content-Disposition',Format('attachment; filename="%s"',[CD]));
end;
end;
procedure TSQLDBRestDispatcher.HandleResourceRequest(aConnection : TSQLDBConnectionDef; IO : TRestIO);
Var
@ -1964,15 +2001,12 @@ begin
Conn.LogEvents:=LogSQLOptions;
Conn.OnLog:=@IO.DoSQLLog;
end;
if (rdoHandleCORS in DispatchOptions) then
begin
IO.Response.SetCustomHeader('Access-Control-Allow-Origin',ResolvedCORSAllowedOrigins(IO.Request));
IO.Response.SetCustomHeader('Access-Control-Allow-Credentials',BoolToStr(CORSAllowCredentials,'true','false'));
end;
HandleCorsResponseHeaders(IO);
if not AuthenticateRequest(IO,True) then
exit;
if Not CheckResourceAccess(IO) then
exit;
HandleOtherResponseHeaders(IO);
DoHandleEvent(True,IO);
H:=CreateDBHandler(IO);
if IsSpecialResource(IO.Resource) then

View File

@ -81,6 +81,7 @@ Type
Public
Destructor Destroy; override;
Class Function GetContentType: String; override;
Class Function FileExtension : String; override;
procedure InitStreaming; override;
end;
@ -354,6 +355,11 @@ begin
Result:='text/xml';
end;
class function TCDSOutputStreamer.FileExtension: String;
begin
Result:='xml';
end;
procedure TCDSOutputStreamer.CreateErrorContent(aCode: Integer; const aMessage: String);
Var

View File

@ -65,6 +65,7 @@ Type
Public
Destructor Destroy; override;
Class Function GetContentType: String; override;
Class Function FileExtension : String; override;
procedure InitStreaming; override;
end;
@ -188,6 +189,11 @@ begin
Result:='text/csv';
end;
Class Function TCSVOutputStreamer.FileExtension : String;
begin
Result:='.csv';
end;
procedure TCSVOutputStreamer.CreateErrorContent(aCode: Integer; const aMessage: String);
Var

View File

@ -83,7 +83,8 @@ Type
rpXMLDocumentRoot,
rpConnectionResourceName,
rpParametersResourceName,
rpParametersRoutePart
rpParametersRoutePart,
rpAttachment
);
TRestStringProperties = Set of TRestStringProperty;
@ -144,6 +145,7 @@ Type
Property CustomViewSQLParam : UTF8string Index ord(rpCustomViewSQLParam) Read GetRestPropName Write SetRestPropName Stored IsRestStringStored;
Property XMLDocumentRoot : UTF8string Index ord(rpXMLDocumentRoot) Read GetRestPropName Write SetRestPropName Stored IsRestStringStored;
Property ConnectionResourceName : UTF8string Index ord(rpConnectionResourceName) Read GetRestPropName Write SetRestPropName Stored IsRestStringStored;
Property AttachmentParam : UTF8String Index ord(rpAttachment) Read GetRestPropName Write SetRestPropName Stored IsRestStringStored;
end;
TRestStatus = (rsError, // Internal logic/unexpected error (500)
@ -263,6 +265,7 @@ Type
Public
Class Procedure RegisterStreamer(Const aName : String);
Class Procedure UnRegisterStreamer(Const aName : String);
Class Function FileExtension : String; virtual;
function RequireMetadata : Boolean; virtual;
Function FieldToString(aFieldType : TRestFieldType; F : TField) : UTF8string; virtual;
function FieldToBase64(F: TField): UTF8String; virtual;
@ -476,7 +479,8 @@ Const
'datapacket', { rpXMLDocumentRoot}
'_connection', { rpConnectionResourceName }
'_parameters', { rpParametersResourceName }
'parameters' { rpParametersRoutePart }
'parameters', { rpParametersRoutePart }
'att' { rpAttachment }
);
DefaultStatuses : Array[TRestStatus] of Word = (
500, { rsError }
@ -919,11 +923,16 @@ begin
TStreamerFactory.Instance.RegisterStreamer(rstOutput,aName,Self)
end;
class procedure TRestOutPutStreamer.UnRegisterStreamer(const aName: String);
class procedure TRestOutputStreamer.UnRegisterStreamer(const aName: String);
begin
TStreamerFactory.Instance.UnRegisterStreamer(rstOutput,aName)
end;
class function TRestOutputStreamer.FileExtension: String;
begin
Result:='';
end;
function TRestOutputStreamer.RequireMetadata: Boolean;
begin
Result:=False;

View File

@ -67,6 +67,7 @@ Type
Public
Destructor Destroy; override;
Class Function GetContentType: String; override;
Class Function FileExtension : String; override;
procedure InitStreaming; override;
end;
@ -250,6 +251,11 @@ begin
Result:='application/json';
end;
Class Function TJSONOutputStreamer.FileExtension : String;
begin
Result:='.json';
end;
procedure TJSONOutputStreamer.CreateErrorContent(aCode: Integer; const aMessage: String);
Var

View File

@ -77,6 +77,7 @@ Type
Public
Destructor Destroy; override;
Class Function GetContentType: String; override;
Class Function FileExtension: String; override;
procedure InitStreaming; override;
end;
@ -101,6 +102,12 @@ begin
Result:='text/xml';
end;
Class Function TXMLOutputStreamer.FileExtension: String;
begin
Result:='.xml';
end;
function TXMLInputStreamer.SelectObject(aIndex: Integer): Boolean;
Var