mirror of
https://github.com/danieleteti/delphimvcframework.git
synced 2024-11-15 07:45:54 +01:00
Improvements in the submission of the request body and corrections in handling the response.
This commit is contained in:
parent
465a7ffad4
commit
715a31c0f6
@ -55,7 +55,13 @@ type
|
||||
TMVCRESTClientHelper = class sealed
|
||||
public
|
||||
class function URIEncode(const aURI: string): string;
|
||||
/// <summary>
|
||||
/// Convert response content to byte array. If the response is compressed, it is decompressed in the process.
|
||||
/// </summary>
|
||||
class function GetResponseContentAsRawBytes(aContentStream: TStream; const aContentEncoding: string): TArray<Byte>;
|
||||
/// <summary>
|
||||
/// Get the response string, if it is of any type of text.
|
||||
/// </summary>
|
||||
class function GetResponseContentAsString(aContentRawBytes: TArray<Byte>; const aContentType: string): string;
|
||||
end;
|
||||
|
||||
@ -68,22 +74,21 @@ type
|
||||
AUTHORIZATION_HEADER = 'Authorization';
|
||||
BASIC_AUTH_PREFIX = 'Basic ';
|
||||
BEARER_AUTH_PREFIX = 'Bearer ';
|
||||
HEADER_RESPONSE_COOKIES = 'Cookies';
|
||||
SERVER_HEADER = 'server';
|
||||
REST_UNSAFE_CHARS: TURLEncoding.TUnsafeChars = [Ord('"'), Ord('<'), Ord('>'), Ord('^'), Ord('`'), Ord('{'),
|
||||
Ord('}'), Ord('|'), Ord('/'), Ord('\'), Ord('?'), Ord('#'), Ord('+'), Ord('.')];
|
||||
QUERY_NAME_UNSAFE_CHARS: TURLEncoding.TUnsafeChars = [Ord('"'), Ord(''''), Ord(':'), Ord(';'), Ord('<'), Ord('='),
|
||||
REST_UNSAFE_CHARS: TURLEncoding.TUnsafeChars = [Ord('"'), Ord(''''), Ord(':'), Ord(';'), Ord('<'), Ord('='),
|
||||
Ord('>'), Ord('@'), Ord('['), Ord(']'), Ord('^'), Ord('`'), Ord('{'), Ord('}'), Ord('|'), Ord('/'), Ord('\'),
|
||||
Ord('?'), Ord('#'), Ord('&'), Ord('!'), Ord('$'), Ord('('), Ord(')'), Ord(','), Ord('~'), Ord(' '), Ord('*'),
|
||||
Ord('+')];
|
||||
PATH_UNSAFE_CHARS: TURLEncoding.TUnsafeChars = [Ord('"'), Ord('<'), Ord('>'), Ord('^'), Ord('`'), Ord('{'),
|
||||
Ord('}'), Ord('|'), Ord('/'), Ord('\'), Ord('?'), Ord('#'), Ord('+'), Ord('.')];
|
||||
end;
|
||||
|
||||
|
||||
implementation
|
||||
|
||||
uses
|
||||
IdCompressorZLib,
|
||||
MVCFramework.Commons, System.Net.Mime;
|
||||
MVCFramework.Commons,
|
||||
System.Net.Mime;
|
||||
|
||||
{ TMVCRESTParam }
|
||||
|
||||
@ -107,11 +112,11 @@ begin
|
||||
try
|
||||
lDecompressor := TIdCompressorZLib.Create(nil);
|
||||
try
|
||||
if SameText(aContentEncoding, 'gzip') then
|
||||
if SameText(aContentEncoding, MVC_COMPRESSION_TYPE_AS_STRING[TMVCCompressionType.ctGZIP]) then
|
||||
begin
|
||||
lDecompressor.DecompressGZipStream(aContentStream, lDecompressed);
|
||||
end
|
||||
else if SameText(aContentEncoding, 'deflate') then
|
||||
else if SameText(aContentEncoding, MVC_COMPRESSION_TYPE_AS_STRING[TMVCCompressionType.ctDeflate]) then
|
||||
begin
|
||||
lDecompressor.DecompressHTTPDeflate(aContentStream, lDecompressed);
|
||||
end
|
||||
@ -162,12 +167,13 @@ begin
|
||||
begin
|
||||
if lCharset.isEmpty then
|
||||
begin
|
||||
lCharset := 'utf-8';
|
||||
lCharset := TMVCCharSet.UTF_8;
|
||||
end;
|
||||
lEncoding := TEncoding.GetEncoding(lCharset);
|
||||
|
||||
lReader := TStringStream.Create('', lEncoding);
|
||||
try
|
||||
lReader.Write(aContentRawBytes, Length(aContentRawBytes));
|
||||
Result := lReader.DataString;
|
||||
finally
|
||||
FreeAndNil(lReader);
|
||||
|
@ -69,7 +69,8 @@ type
|
||||
function UserAgent: string; overload;
|
||||
|
||||
/// <summary>
|
||||
/// Clears all parameters, except authorization headers. This method is executed after each request is completed.
|
||||
/// Clears all parameters (headers, body, path params and query params). This method is executed after each
|
||||
/// request is completed.
|
||||
/// </summary>
|
||||
function ClearAllParams: IMVCRESTClient;
|
||||
|
||||
@ -93,7 +94,7 @@ type
|
||||
/// <summary>
|
||||
/// Add bearer authorization header. Authorization = Bearer <Token>
|
||||
/// </summary>
|
||||
function SetBearerAuthorization(const aToken: string): IMVCRESTClient;
|
||||
function SetBearerAuthorization(const aAccessToken: string): IMVCRESTClient;
|
||||
|
||||
/// <summary>
|
||||
/// Add a header.
|
||||
@ -229,7 +230,7 @@ type
|
||||
const aContentType: string = ''): IMVCRESTClient; overload;
|
||||
|
||||
/// <summary>
|
||||
/// Add a field to the x-www-form-urlencoded body. You must set ContentType to application/x-www-form-urlencoded
|
||||
/// Add a field to the x-www-form-urlencoded body. You must set ContentType to application/x-www-form-urlencoded
|
||||
/// </summary>
|
||||
function AddBodyFieldURLEncoded(const aName, aValue: string): IMVCRESTClient;
|
||||
|
||||
@ -257,16 +258,16 @@ type
|
||||
function Get: IMVCRESTResponse; overload;
|
||||
|
||||
/// <summary>
|
||||
/// Execute a Post request.
|
||||
/// Execute a Post request.
|
||||
/// </summary>
|
||||
/// <param name="aResource">
|
||||
/// Resource path
|
||||
/// Resource path
|
||||
/// </param>
|
||||
/// <param name="aBody">
|
||||
/// Object to be serialized. It can be a simple object or a list of objects (TObjectList <T>)
|
||||
/// Object to be serialized. It can be a simple object or a list of objects (TObjectList <T>)
|
||||
/// </param>
|
||||
/// <param name="aOwnsBody">
|
||||
/// If OwnsBody is true, Body will be destroyed by IMVCRESTClient. <br />
|
||||
/// If OwnsBody is true, Body will be destroyed by IMVCRESTClient. <br />
|
||||
/// </param>
|
||||
function Post(const aResource: string; aBody: TObject; const aOwnsBody: Boolean = True): IMVCRESTResponse; overload;
|
||||
function Post(const aResource: string; const aBody: string = '';
|
||||
|
@ -77,6 +77,7 @@ type
|
||||
fHTTPClient: THTTPClient;
|
||||
fBaseURL: string;
|
||||
fResource: string;
|
||||
fInternalContentType: string;
|
||||
fProxySettings: TProxySettings;
|
||||
fParameters: TList<TMVCRESTParam>;
|
||||
fRawBody: TStringStream;
|
||||
@ -84,7 +85,6 @@ type
|
||||
fSerializer: IMVCSerializer;
|
||||
fRttiContext: TRttiContext;
|
||||
function GetBodyFormData: TMultipartFormData;
|
||||
function GetContentTypeCharset(const aContentType: string): string;
|
||||
function ObjectIsList(aObject: TObject): Boolean;
|
||||
function SerializeObject(aObject: TObject): string;
|
||||
procedure SetContentType(const aContentType: string);
|
||||
@ -99,6 +99,7 @@ type
|
||||
procedure DoApplyHeaders;
|
||||
procedure DoApplyCookies(const aURL: string);
|
||||
procedure DoEncodeURL(var aURL: string);
|
||||
procedure DoPrepareBodyRequest(var aBodyStream: TStream);
|
||||
|
||||
function ExecuteRequest(const aMethod: TMVCHTTPMethodType): IMVCRESTResponse;
|
||||
public
|
||||
@ -130,7 +131,8 @@ type
|
||||
function UserAgent: string; overload;
|
||||
|
||||
/// <summary>
|
||||
/// Clears all parameters, except authorization headers. This method is executed after each request is completed.
|
||||
/// Clears all parameters (headers, body, path params and query params). This method is executed after each
|
||||
/// request is completed.
|
||||
/// </summary>
|
||||
function ClearAllParams: IMVCRESTClient;
|
||||
|
||||
@ -154,7 +156,7 @@ type
|
||||
/// <summary>
|
||||
/// Add bearer authorization header. Authorization = Bearer <Token>
|
||||
/// </summary>
|
||||
function SetBearerAuthorization(const aToken: string): IMVCRESTClient;
|
||||
function SetBearerAuthorization(const aAccessToken: string): IMVCRESTClient;
|
||||
|
||||
/// <summary>
|
||||
/// Add a header.
|
||||
@ -464,12 +466,12 @@ var
|
||||
lContentCharset: string;
|
||||
lEncoding: TEncoding;
|
||||
lBytes: TArray<Byte>;
|
||||
lContentType: string;
|
||||
begin
|
||||
Result := Self;
|
||||
|
||||
SetContentType(aContentType);
|
||||
SplitContentMediaTypeAndCharset(aContentType, lContentType, lContentCharset);
|
||||
|
||||
lContentCharset := GetContentTypeCharset(aContentType);
|
||||
if lContentCharset.IsEmpty then
|
||||
begin
|
||||
lContentCharset := TMVCCharSet.UTF_8;
|
||||
@ -477,8 +479,11 @@ begin
|
||||
lEncoding := TEncoding.GetEncoding(lContentCharset);
|
||||
try
|
||||
fRawBody.Clear;
|
||||
|
||||
lBytes := TEncoding.Convert(TEncoding.Default, lEncoding, TEncoding.Default.GetBytes(aBody));
|
||||
lBytes := lEncoding.GetBytes(aBody);
|
||||
fRawBody.WriteData(lBytes, Length(lBytes));
|
||||
SetContentType(BuildContentType(lContentType, lContentCharset));
|
||||
finally
|
||||
FreeAndNil(lEncoding);
|
||||
end;
|
||||
@ -657,7 +662,7 @@ end;
|
||||
function TMVCRESTClient.Async(aCompletionHandler: TProc<IMVCRESTResponse>;
|
||||
aCompletionHandlerWithError: TProc<Exception>; const aSynchronized: Boolean): IMVCRESTClient;
|
||||
begin
|
||||
|
||||
// Needs implementation
|
||||
end;
|
||||
|
||||
function TMVCRESTClient.BaseURL(const aBaseURL: string): IMVCRESTClient;
|
||||
@ -685,6 +690,7 @@ function TMVCRESTClient.ClearAllParams: IMVCRESTClient;
|
||||
begin
|
||||
Result := Self;
|
||||
fParameters.Clear;
|
||||
ClearBody;
|
||||
end;
|
||||
|
||||
function TMVCRESTClient.ClearBody: IMVCRESTClient;
|
||||
@ -693,7 +699,9 @@ begin
|
||||
if Assigned(fBodyFormData) then
|
||||
FreeAndNil(fBodyFormData);
|
||||
|
||||
Result := Self;
|
||||
ClearParameters(TMVCRESTParamType.FormURLEncoded);
|
||||
fInternalContentType := '';
|
||||
end;
|
||||
|
||||
function TMVCRESTClient.ClearCookies: IMVCRESTClient;
|
||||
@ -829,6 +837,7 @@ procedure TMVCRESTClient.DoApplyHeaders;
|
||||
var
|
||||
lParam: TMVCRESTParam;
|
||||
begin
|
||||
fHTTPClient.CustHeaders.Clear;
|
||||
for lParam in fParameters do
|
||||
begin
|
||||
if lParam.&Type = TMVCRESTParamType.Header then
|
||||
@ -849,7 +858,8 @@ begin
|
||||
if lParam.&Type = TMVCRESTParamType.Path then
|
||||
begin
|
||||
lReplace := '{' + lParam.Name + '}';
|
||||
lEncodedParam := TMVCRESTClientHelper.URIEncode(lParam.Value);
|
||||
lEncodedParam := TNetEncoding.URL.Encode(lParam.Value, TMVCRESTClientConsts.PATH_UNSAFE_CHARS,
|
||||
[TURLEncoding.TEncodeOption.EncodePercent]);
|
||||
aURL := aURL.Replace(lReplace, lEncodedParam, [rfReplaceAll, rfIgnoreCase]);
|
||||
end;
|
||||
end;
|
||||
@ -866,8 +876,7 @@ begin
|
||||
begin
|
||||
if lParam.&Type = TMVCRESTParamType.Query then
|
||||
begin
|
||||
lName := TNetEncoding.URL.Encode(lParam.Name, TMVCRESTClientConsts.QUERY_NAME_UNSAFE_CHARS,
|
||||
[TURLEncoding.TEncodeOption.EncodePercent]);
|
||||
lName := TMVCRESTClientHelper.URIEncode(lParam.Name);
|
||||
lValue := TNetEncoding.URL.EncodeForm(lParam.Value);
|
||||
|
||||
if aURL.Contains('?') then
|
||||
@ -896,11 +905,55 @@ begin
|
||||
aURL := TURI.Create(aURL).Encode;
|
||||
end;
|
||||
|
||||
procedure TMVCRESTClient.DoPrepareBodyRequest(var aBodyStream: TStream);
|
||||
var
|
||||
lContentType: string;
|
||||
lContentCharset: string;
|
||||
lParam: TMVCRESTParam;
|
||||
lName: string;
|
||||
lValue: string;
|
||||
lBody: string;
|
||||
begin
|
||||
SplitContentMediaTypeAndCharset(fInternalContentType, lContentType, lContentCharset);
|
||||
|
||||
if SameText(lContentType, TMVCMediaType.MULTIPART_FORM_DATA) then
|
||||
begin
|
||||
aBodyStream := GetBodyFormData.Stream;
|
||||
SetContentType(GetBodyFormData.MimeTypeHeader);
|
||||
fHTTPClient.CustHeaders[sContentType] := GetBodyFormData.MimeTypeHeader;
|
||||
end
|
||||
else if SameText(lContentType, TMVCMediaType.APPLICATION_FORM_URLENCODED) then
|
||||
begin
|
||||
lBody := '';
|
||||
for lParam in fParameters do
|
||||
begin
|
||||
if lParam.&Type = TMVCRESTParamType.FormURLEncoded then
|
||||
begin
|
||||
lName := TMVCRESTClientHelper.URIEncode(lParam.Name);
|
||||
lValue := TNetEncoding.URL.EncodeForm(lParam.Value);
|
||||
if not lBody.IsEmpty then
|
||||
lBody := lBody + '&';
|
||||
lBody := lBody + lName + '=' + lValue;
|
||||
end;
|
||||
end;
|
||||
AddBody(lBody, fInternalContentType);
|
||||
aBodyStream := fRawBody;
|
||||
end
|
||||
else
|
||||
begin
|
||||
aBodyStream := fRawBody;
|
||||
end;
|
||||
aBodyStream.Position := 0;
|
||||
end;
|
||||
|
||||
function TMVCRESTClient.ExecuteRequest(const aMethod: TMVCHTTPMethodType): IMVCRESTResponse;
|
||||
var
|
||||
lURL: string;
|
||||
lResponse: IHTTPResponse;
|
||||
lBodyStream: TStream;
|
||||
begin
|
||||
fHTTPClient.ProxySettings := fProxySettings;
|
||||
|
||||
lURL := GetFullURL;
|
||||
DoConvertMVCPathParamsToRESTParams(lURL);
|
||||
DoApplyPathParams(lURL);
|
||||
@ -909,23 +962,30 @@ begin
|
||||
DoApplyHeaders;
|
||||
DoApplyCookies(lURL);
|
||||
|
||||
lBodyStream := nil;
|
||||
DoPrepareBodyRequest(lBodyStream);
|
||||
|
||||
case aMethod of
|
||||
httpGET:
|
||||
lResponse := fHTTPClient.Get(lURL, nil, []);
|
||||
begin
|
||||
lResponse := fHTTPClient.Get(lURL, nil, [])
|
||||
end;
|
||||
httpPOST:
|
||||
;
|
||||
begin
|
||||
lResponse := fHTTPClient.Post(lURL, lBodyStream, nil, []);
|
||||
end;
|
||||
httpPUT:
|
||||
;
|
||||
httpDELETE:
|
||||
;
|
||||
httpHEAD:
|
||||
;
|
||||
httpOPTIONS:
|
||||
;
|
||||
begin
|
||||
lResponse := fHTTPClient.Put(lURL, lBodyStream, nil, []);
|
||||
end;
|
||||
httpPATCH:
|
||||
;
|
||||
httpTRACE:
|
||||
;
|
||||
begin
|
||||
lResponse := fHTTPClient.Patch(lURL, lBodyStream, nil, []);
|
||||
end;
|
||||
httpDELETE:
|
||||
begin
|
||||
lResponse := fHTTPClient.Delete(lURL, nil, []);
|
||||
end;
|
||||
end;
|
||||
|
||||
Result := TMVCRESTResponse.Create(lResponse);
|
||||
@ -946,13 +1006,6 @@ begin
|
||||
Result := fBodyFormData;
|
||||
end;
|
||||
|
||||
function TMVCRESTClient.GetContentTypeCharset(const aContentType: string): string;
|
||||
var
|
||||
lContentType: string;
|
||||
begin
|
||||
SplitContentMediaTypeAndCharset(aContentType, lContentType, Result);
|
||||
end;
|
||||
|
||||
function TMVCRESTClient.GetFullURL: string;
|
||||
var
|
||||
lResource: string;
|
||||
@ -1206,17 +1259,29 @@ begin
|
||||
end;
|
||||
|
||||
function TMVCRESTClient.SetBasicAuthorization(const aUsername, aPassword: string): IMVCRESTClient;
|
||||
var
|
||||
lBase64: TNetEncoding;
|
||||
lAuthValue: string;
|
||||
begin
|
||||
|
||||
// Do not use TNetEncoding.Base64 here, because it may break long line
|
||||
lBase64 := TBase64Encoding.Create(0, '');
|
||||
try
|
||||
lAuthValue := TMVCRESTClientConsts.BASIC_AUTH_PREFIX + lBase64.Encode(aUsername + ':' + aPassword);
|
||||
finally
|
||||
FreeAndNil(lBase64);
|
||||
end;
|
||||
Result := AddHeader(TMVCRESTClientConsts.AUTHORIZATION_HEADER, lAuthValue);
|
||||
end;
|
||||
|
||||
function TMVCRESTClient.SetBearerAuthorization(const aToken: string): IMVCRESTClient;
|
||||
function TMVCRESTClient.SetBearerAuthorization(const aAccessToken: string): IMVCRESTClient;
|
||||
begin
|
||||
|
||||
Result := AddHeader(TMVCRESTClientConsts.AUTHORIZATION_HEADER, TMVCRESTClientConsts.BEARER_AUTH_PREFIX +
|
||||
aAccessToken);
|
||||
end;
|
||||
|
||||
procedure TMVCRESTClient.SetContentType(const aContentType: string);
|
||||
begin
|
||||
fInternalContentType := aContentType;
|
||||
AddHeader(sContentType, aContentType);
|
||||
end;
|
||||
|
||||
@ -1302,7 +1367,7 @@ begin
|
||||
fServer := aHTTPResponse.HeaderValue[TMVCRESTClientConsts.SERVER_HEADER];
|
||||
fRawBytes := TMVCRESTClientHelper.GetResponseContentAsRawBytes(aHTTPResponse.ContentStream,
|
||||
aHTTPResponse.ContentEncoding);
|
||||
fContent := TMVCRESTClientHelper.GetResponseContentAsString(fRawBytes, aHTTPResponse.ContentCharSet);
|
||||
fContent := TMVCRESTClientHelper.GetResponseContentAsString(fRawBytes, aHTTPResponse.HeaderValue[sContentType]);
|
||||
fContentType := aHTTPResponse.HeaderValue[sContentType];
|
||||
fContentEncoding := aHTTPResponse.ContentEncoding;
|
||||
fContentLength := aHTTPResponse.ContentLength;
|
||||
|
@ -1,7 +1,7 @@
|
||||
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<ProjectGuid>{0582DE6A-D716-46D3-8CBD-84AD73A4B536}</ProjectGuid>
|
||||
<ProjectVersion>19.0</ProjectVersion>
|
||||
<ProjectVersion>19.1</ProjectVersion>
|
||||
<FrameworkType>VCL</FrameworkType>
|
||||
<Base>True</Base>
|
||||
<Config Condition="'$(Config)'==''">GUI</Config>
|
||||
@ -709,6 +709,32 @@
|
||||
<Operation>0</Operation>
|
||||
</Platform>
|
||||
</DeployClass>
|
||||
<DeployClass Name="iOS_AppStore1024">
|
||||
<Platform Name="iOSDevice64">
|
||||
<RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset</RemoteDir>
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
</DeployClass>
|
||||
<DeployClass Name="iPad_AppIcon152">
|
||||
<Platform Name="iOSDevice64">
|
||||
<RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset</RemoteDir>
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
<Platform Name="iOSSimulator">
|
||||
<RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset</RemoteDir>
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
</DeployClass>
|
||||
<DeployClass Name="iPad_AppIcon167">
|
||||
<Platform Name="iOSDevice64">
|
||||
<RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset</RemoteDir>
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
<Platform Name="iOSSimulator">
|
||||
<RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset</RemoteDir>
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
</DeployClass>
|
||||
<DeployClass Name="iPad_Launch1024">
|
||||
<Platform Name="iOSDevice">
|
||||
<Operation>1</Operation>
|
||||
@ -871,6 +897,56 @@
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
</DeployClass>
|
||||
<DeployClass Name="iPad_Notification40">
|
||||
<Platform Name="iOSDevice64">
|
||||
<RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset</RemoteDir>
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
<Platform Name="iOSSimulator">
|
||||
<RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset</RemoteDir>
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
</DeployClass>
|
||||
<DeployClass Name="iPad_Setting58">
|
||||
<Platform Name="iOSDevice64">
|
||||
<RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset</RemoteDir>
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
<Platform Name="iOSSimulator">
|
||||
<RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset</RemoteDir>
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
</DeployClass>
|
||||
<DeployClass Name="iPad_SpotLight80">
|
||||
<Platform Name="iOSDevice64">
|
||||
<RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset</RemoteDir>
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
<Platform Name="iOSSimulator">
|
||||
<RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset</RemoteDir>
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
</DeployClass>
|
||||
<DeployClass Name="iPhone_AppIcon120">
|
||||
<Platform Name="iOSDevice64">
|
||||
<RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset</RemoteDir>
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
<Platform Name="iOSSimulator">
|
||||
<RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset</RemoteDir>
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
</DeployClass>
|
||||
<DeployClass Name="iPhone_AppIcon180">
|
||||
<Platform Name="iOSDevice64">
|
||||
<RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset</RemoteDir>
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
<Platform Name="iOSSimulator">
|
||||
<RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset</RemoteDir>
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
</DeployClass>
|
||||
<DeployClass Name="iPhone_Launch1125">
|
||||
<Platform Name="iOSDevice32">
|
||||
<Operation>1</Operation>
|
||||
@ -1065,6 +1141,66 @@
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
</DeployClass>
|
||||
<DeployClass Name="iPhone_Notification40">
|
||||
<Platform Name="iOSDevice64">
|
||||
<RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset</RemoteDir>
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
<Platform Name="iOSSimulator">
|
||||
<RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset</RemoteDir>
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
</DeployClass>
|
||||
<DeployClass Name="iPhone_Notification60">
|
||||
<Platform Name="iOSDevice64">
|
||||
<RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset</RemoteDir>
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
<Platform Name="iOSSimulator">
|
||||
<RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset</RemoteDir>
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
</DeployClass>
|
||||
<DeployClass Name="iPhone_Setting58">
|
||||
<Platform Name="iOSDevice64">
|
||||
<RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset</RemoteDir>
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
<Platform Name="iOSSimulator">
|
||||
<RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset</RemoteDir>
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
</DeployClass>
|
||||
<DeployClass Name="iPhone_Setting87">
|
||||
<Platform Name="iOSDevice64">
|
||||
<RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset</RemoteDir>
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
<Platform Name="iOSSimulator">
|
||||
<RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset</RemoteDir>
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
</DeployClass>
|
||||
<DeployClass Name="iPhone_Spotlight120">
|
||||
<Platform Name="iOSDevice64">
|
||||
<RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset</RemoteDir>
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
<Platform Name="iOSSimulator">
|
||||
<RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset</RemoteDir>
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
</DeployClass>
|
||||
<DeployClass Name="iPhone_Spotlight80">
|
||||
<Platform Name="iOSDevice64">
|
||||
<RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset</RemoteDir>
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
<Platform Name="iOSSimulator">
|
||||
<RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset</RemoteDir>
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
</DeployClass>
|
||||
<DeployClass Name="ProjectAndroidManifest">
|
||||
<Platform Name="Android">
|
||||
<Operation>1</Operation>
|
||||
|
@ -678,7 +678,7 @@ begin
|
||||
try
|
||||
// no request body
|
||||
lRes := RESTClient
|
||||
.AddBody('', False, TMVCMediaType.APPLICATION_JSON) // To define a Content-Type add an empty body with the type.
|
||||
.AddBody('', TMVCMediaType.APPLICATION_JSON) // To define a Content-Type add an empty body with the type.
|
||||
.Post('/system/users/logged');
|
||||
Assert.areEqual<Integer>(HTTP_STATUS.BadRequest, lRes.StatusCode,
|
||||
'Empty request body doesn''t return HTTP 400 Bad Request');
|
||||
@ -1153,7 +1153,7 @@ procedure TServerTest.TestProducesConsumes02;
|
||||
var
|
||||
res: IMVCRESTResponse;
|
||||
begin
|
||||
res := RESTClient.Accept('text/plain').Post('/testconsumes', 'Hello World', False, TMVCMediaType.TEXT_PLAIN);
|
||||
res := RESTClient.Accept('text/plain').Post('/testconsumes', 'Hello World', TMVCMediaType.TEXT_PLAIN);
|
||||
Assert.areEqual('Hello World', res.Content);
|
||||
Assert.areEqual(TMVCMediaType.TEXT_PLAIN, res.ContentType, True);
|
||||
|
||||
@ -1173,7 +1173,7 @@ begin
|
||||
// Assert.areEqual(BuildContentType(TMVCMediaType.TEXT_PLAIN, TMVCCharSet.ISO88591), res.ContentType, True);
|
||||
|
||||
res := RESTClient.Accept(TMVCMediaType.TEXT_PLAIN)
|
||||
.Post('/testconsumes/textiso8859_1', 'this is an iso8859-1 text', False, TMVCMediaType.TEXT_PLAIN);
|
||||
.Post('/testconsumes/textiso8859_1', 'this is an iso8859-1 text', TMVCMediaType.TEXT_PLAIN);
|
||||
Assert.areEqual<Integer>(HTTP_STATUS.OK, res.StatusCode);
|
||||
Assert.areEqual('this is an iso8859-1 text', res.Content);
|
||||
Assert.areEqual(TMVCMediaType.TEXT_PLAIN, res.ContentType, True);
|
||||
|
@ -7,7 +7,7 @@
|
||||
<TargetedPlatforms>129</TargetedPlatforms>
|
||||
<AppType>Console</AppType>
|
||||
<FrameworkType>None</FrameworkType>
|
||||
<ProjectVersion>19.0</ProjectVersion>
|
||||
<ProjectVersion>19.1</ProjectVersion>
|
||||
<Platform Condition="'$(Platform)'==''">Win32</Platform>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Config)'=='Base' or '$(Base)'!=''">
|
||||
@ -146,12 +146,6 @@
|
||||
<Overwrite>true</Overwrite>
|
||||
</Platform>
|
||||
</DeployFile>
|
||||
<DeployFile LocalName="TestServer" Configuration="CI" Class="ProjectOutput">
|
||||
<Platform Name="Linux64">
|
||||
<RemoteName>TestServer</RemoteName>
|
||||
<Overwrite>true</Overwrite>
|
||||
</Platform>
|
||||
</DeployFile>
|
||||
<DeployFile LocalName="bin\www\index.html" Configuration="CI" Class="File">
|
||||
<Platform Name="Linux64">
|
||||
<RemoteDir>.\www</RemoteDir>
|
||||
@ -159,6 +153,12 @@
|
||||
<Overwrite>true</Overwrite>
|
||||
</Platform>
|
||||
</DeployFile>
|
||||
<DeployFile LocalName="TestServer" Configuration="CI" Class="ProjectOutput">
|
||||
<Platform Name="Linux64">
|
||||
<RemoteName>TestServer</RemoteName>
|
||||
<Overwrite>true</Overwrite>
|
||||
</Platform>
|
||||
</DeployFile>
|
||||
<DeployFile LocalName="bin\customers.json" Configuration="CI" Class="File">
|
||||
<Platform Name="Linux64">
|
||||
<RemoteName>customers.json</RemoteName>
|
||||
@ -541,6 +541,32 @@
|
||||
<Operation>0</Operation>
|
||||
</Platform>
|
||||
</DeployClass>
|
||||
<DeployClass Name="iOS_AppStore1024">
|
||||
<Platform Name="iOSDevice64">
|
||||
<RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset</RemoteDir>
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
</DeployClass>
|
||||
<DeployClass Name="iPad_AppIcon152">
|
||||
<Platform Name="iOSDevice64">
|
||||
<RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset</RemoteDir>
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
<Platform Name="iOSSimulator">
|
||||
<RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset</RemoteDir>
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
</DeployClass>
|
||||
<DeployClass Name="iPad_AppIcon167">
|
||||
<Platform Name="iOSDevice64">
|
||||
<RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset</RemoteDir>
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
<Platform Name="iOSSimulator">
|
||||
<RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset</RemoteDir>
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
</DeployClass>
|
||||
<DeployClass Name="iPad_Launch1024x768">
|
||||
<Platform Name="iOSDevice32">
|
||||
<Operation>1</Operation>
|
||||
@ -671,6 +697,56 @@
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
</DeployClass>
|
||||
<DeployClass Name="iPad_Notification40">
|
||||
<Platform Name="iOSDevice64">
|
||||
<RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset</RemoteDir>
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
<Platform Name="iOSSimulator">
|
||||
<RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset</RemoteDir>
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
</DeployClass>
|
||||
<DeployClass Name="iPad_Setting58">
|
||||
<Platform Name="iOSDevice64">
|
||||
<RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset</RemoteDir>
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
<Platform Name="iOSSimulator">
|
||||
<RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset</RemoteDir>
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
</DeployClass>
|
||||
<DeployClass Name="iPad_SpotLight80">
|
||||
<Platform Name="iOSDevice64">
|
||||
<RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset</RemoteDir>
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
<Platform Name="iOSSimulator">
|
||||
<RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset</RemoteDir>
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
</DeployClass>
|
||||
<DeployClass Name="iPhone_AppIcon120">
|
||||
<Platform Name="iOSDevice64">
|
||||
<RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset</RemoteDir>
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
<Platform Name="iOSSimulator">
|
||||
<RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset</RemoteDir>
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
</DeployClass>
|
||||
<DeployClass Name="iPhone_AppIcon180">
|
||||
<Platform Name="iOSDevice64">
|
||||
<RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset</RemoteDir>
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
<Platform Name="iOSSimulator">
|
||||
<RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset</RemoteDir>
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
</DeployClass>
|
||||
<DeployClass Name="iPhone_Launch1125">
|
||||
<Platform Name="iOSDevice32">
|
||||
<Operation>1</Operation>
|
||||
@ -865,6 +941,66 @@
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
</DeployClass>
|
||||
<DeployClass Name="iPhone_Notification40">
|
||||
<Platform Name="iOSDevice64">
|
||||
<RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset</RemoteDir>
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
<Platform Name="iOSSimulator">
|
||||
<RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset</RemoteDir>
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
</DeployClass>
|
||||
<DeployClass Name="iPhone_Notification60">
|
||||
<Platform Name="iOSDevice64">
|
||||
<RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset</RemoteDir>
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
<Platform Name="iOSSimulator">
|
||||
<RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset</RemoteDir>
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
</DeployClass>
|
||||
<DeployClass Name="iPhone_Setting58">
|
||||
<Platform Name="iOSDevice64">
|
||||
<RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset</RemoteDir>
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
<Platform Name="iOSSimulator">
|
||||
<RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset</RemoteDir>
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
</DeployClass>
|
||||
<DeployClass Name="iPhone_Setting87">
|
||||
<Platform Name="iOSDevice64">
|
||||
<RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset</RemoteDir>
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
<Platform Name="iOSSimulator">
|
||||
<RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset</RemoteDir>
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
</DeployClass>
|
||||
<DeployClass Name="iPhone_Spotlight120">
|
||||
<Platform Name="iOSDevice64">
|
||||
<RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset</RemoteDir>
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
<Platform Name="iOSSimulator">
|
||||
<RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset</RemoteDir>
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
</DeployClass>
|
||||
<DeployClass Name="iPhone_Spotlight80">
|
||||
<Platform Name="iOSDevice64">
|
||||
<RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset</RemoteDir>
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
<Platform Name="iOSSimulator">
|
||||
<RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset</RemoteDir>
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
</DeployClass>
|
||||
<DeployClass Name="ProjectAndroidManifest">
|
||||
<Platform Name="Android">
|
||||
<Operation>1</Operation>
|
||||
|
Loading…
Reference in New Issue
Block a user