mirror of
https://github.com/danieleteti/delphimvcframework.git
synced 2024-11-15 15:55: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
|
TMVCRESTClientHelper = class sealed
|
||||||
public
|
public
|
||||||
class function URIEncode(const aURI: string): string;
|
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>;
|
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;
|
class function GetResponseContentAsString(aContentRawBytes: TArray<Byte>; const aContentType: string): string;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@ -68,22 +74,21 @@ type
|
|||||||
AUTHORIZATION_HEADER = 'Authorization';
|
AUTHORIZATION_HEADER = 'Authorization';
|
||||||
BASIC_AUTH_PREFIX = 'Basic ';
|
BASIC_AUTH_PREFIX = 'Basic ';
|
||||||
BEARER_AUTH_PREFIX = 'Bearer ';
|
BEARER_AUTH_PREFIX = 'Bearer ';
|
||||||
HEADER_RESPONSE_COOKIES = 'Cookies';
|
|
||||||
SERVER_HEADER = 'server';
|
SERVER_HEADER = 'server';
|
||||||
REST_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('.')];
|
|
||||||
QUERY_NAME_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('?'), 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;
|
end;
|
||||||
|
|
||||||
|
|
||||||
implementation
|
implementation
|
||||||
|
|
||||||
uses
|
uses
|
||||||
IdCompressorZLib,
|
IdCompressorZLib,
|
||||||
MVCFramework.Commons, System.Net.Mime;
|
MVCFramework.Commons,
|
||||||
|
System.Net.Mime;
|
||||||
|
|
||||||
{ TMVCRESTParam }
|
{ TMVCRESTParam }
|
||||||
|
|
||||||
@ -107,11 +112,11 @@ begin
|
|||||||
try
|
try
|
||||||
lDecompressor := TIdCompressorZLib.Create(nil);
|
lDecompressor := TIdCompressorZLib.Create(nil);
|
||||||
try
|
try
|
||||||
if SameText(aContentEncoding, 'gzip') then
|
if SameText(aContentEncoding, MVC_COMPRESSION_TYPE_AS_STRING[TMVCCompressionType.ctGZIP]) then
|
||||||
begin
|
begin
|
||||||
lDecompressor.DecompressGZipStream(aContentStream, lDecompressed);
|
lDecompressor.DecompressGZipStream(aContentStream, lDecompressed);
|
||||||
end
|
end
|
||||||
else if SameText(aContentEncoding, 'deflate') then
|
else if SameText(aContentEncoding, MVC_COMPRESSION_TYPE_AS_STRING[TMVCCompressionType.ctDeflate]) then
|
||||||
begin
|
begin
|
||||||
lDecompressor.DecompressHTTPDeflate(aContentStream, lDecompressed);
|
lDecompressor.DecompressHTTPDeflate(aContentStream, lDecompressed);
|
||||||
end
|
end
|
||||||
@ -162,12 +167,13 @@ begin
|
|||||||
begin
|
begin
|
||||||
if lCharset.isEmpty then
|
if lCharset.isEmpty then
|
||||||
begin
|
begin
|
||||||
lCharset := 'utf-8';
|
lCharset := TMVCCharSet.UTF_8;
|
||||||
end;
|
end;
|
||||||
lEncoding := TEncoding.GetEncoding(lCharset);
|
lEncoding := TEncoding.GetEncoding(lCharset);
|
||||||
|
|
||||||
lReader := TStringStream.Create('', lEncoding);
|
lReader := TStringStream.Create('', lEncoding);
|
||||||
try
|
try
|
||||||
|
lReader.Write(aContentRawBytes, Length(aContentRawBytes));
|
||||||
Result := lReader.DataString;
|
Result := lReader.DataString;
|
||||||
finally
|
finally
|
||||||
FreeAndNil(lReader);
|
FreeAndNil(lReader);
|
||||||
|
@ -69,7 +69,8 @@ type
|
|||||||
function UserAgent: string; overload;
|
function UserAgent: string; overload;
|
||||||
|
|
||||||
/// <summary>
|
/// <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>
|
/// </summary>
|
||||||
function ClearAllParams: IMVCRESTClient;
|
function ClearAllParams: IMVCRESTClient;
|
||||||
|
|
||||||
@ -93,7 +94,7 @@ type
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Add bearer authorization header. Authorization = Bearer <Token>
|
/// Add bearer authorization header. Authorization = Bearer <Token>
|
||||||
/// </summary>
|
/// </summary>
|
||||||
function SetBearerAuthorization(const aToken: string): IMVCRESTClient;
|
function SetBearerAuthorization(const aAccessToken: string): IMVCRESTClient;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Add a header.
|
/// Add a header.
|
||||||
@ -229,7 +230,7 @@ type
|
|||||||
const aContentType: string = ''): IMVCRESTClient; overload;
|
const aContentType: string = ''): IMVCRESTClient; overload;
|
||||||
|
|
||||||
/// <summary>
|
/// <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>
|
/// </summary>
|
||||||
function AddBodyFieldURLEncoded(const aName, aValue: string): IMVCRESTClient;
|
function AddBodyFieldURLEncoded(const aName, aValue: string): IMVCRESTClient;
|
||||||
|
|
||||||
@ -257,16 +258,16 @@ type
|
|||||||
function Get: IMVCRESTResponse; overload;
|
function Get: IMVCRESTResponse; overload;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Execute a Post request.
|
/// Execute a Post request.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="aResource">
|
/// <param name="aResource">
|
||||||
/// Resource path
|
/// Resource path
|
||||||
/// </param>
|
/// </param>
|
||||||
/// <param name="aBody">
|
/// <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>
|
||||||
/// <param name="aOwnsBody">
|
/// <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>
|
/// </param>
|
||||||
function Post(const aResource: string; aBody: TObject; const aOwnsBody: Boolean = True): IMVCRESTResponse; overload;
|
function Post(const aResource: string; aBody: TObject; const aOwnsBody: Boolean = True): IMVCRESTResponse; overload;
|
||||||
function Post(const aResource: string; const aBody: string = '';
|
function Post(const aResource: string; const aBody: string = '';
|
||||||
|
@ -77,6 +77,7 @@ type
|
|||||||
fHTTPClient: THTTPClient;
|
fHTTPClient: THTTPClient;
|
||||||
fBaseURL: string;
|
fBaseURL: string;
|
||||||
fResource: string;
|
fResource: string;
|
||||||
|
fInternalContentType: string;
|
||||||
fProxySettings: TProxySettings;
|
fProxySettings: TProxySettings;
|
||||||
fParameters: TList<TMVCRESTParam>;
|
fParameters: TList<TMVCRESTParam>;
|
||||||
fRawBody: TStringStream;
|
fRawBody: TStringStream;
|
||||||
@ -84,7 +85,6 @@ type
|
|||||||
fSerializer: IMVCSerializer;
|
fSerializer: IMVCSerializer;
|
||||||
fRttiContext: TRttiContext;
|
fRttiContext: TRttiContext;
|
||||||
function GetBodyFormData: TMultipartFormData;
|
function GetBodyFormData: TMultipartFormData;
|
||||||
function GetContentTypeCharset(const aContentType: string): string;
|
|
||||||
function ObjectIsList(aObject: TObject): Boolean;
|
function ObjectIsList(aObject: TObject): Boolean;
|
||||||
function SerializeObject(aObject: TObject): string;
|
function SerializeObject(aObject: TObject): string;
|
||||||
procedure SetContentType(const aContentType: string);
|
procedure SetContentType(const aContentType: string);
|
||||||
@ -99,6 +99,7 @@ type
|
|||||||
procedure DoApplyHeaders;
|
procedure DoApplyHeaders;
|
||||||
procedure DoApplyCookies(const aURL: string);
|
procedure DoApplyCookies(const aURL: string);
|
||||||
procedure DoEncodeURL(var aURL: string);
|
procedure DoEncodeURL(var aURL: string);
|
||||||
|
procedure DoPrepareBodyRequest(var aBodyStream: TStream);
|
||||||
|
|
||||||
function ExecuteRequest(const aMethod: TMVCHTTPMethodType): IMVCRESTResponse;
|
function ExecuteRequest(const aMethod: TMVCHTTPMethodType): IMVCRESTResponse;
|
||||||
public
|
public
|
||||||
@ -130,7 +131,8 @@ type
|
|||||||
function UserAgent: string; overload;
|
function UserAgent: string; overload;
|
||||||
|
|
||||||
/// <summary>
|
/// <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>
|
/// </summary>
|
||||||
function ClearAllParams: IMVCRESTClient;
|
function ClearAllParams: IMVCRESTClient;
|
||||||
|
|
||||||
@ -154,7 +156,7 @@ type
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Add bearer authorization header. Authorization = Bearer <Token>
|
/// Add bearer authorization header. Authorization = Bearer <Token>
|
||||||
/// </summary>
|
/// </summary>
|
||||||
function SetBearerAuthorization(const aToken: string): IMVCRESTClient;
|
function SetBearerAuthorization(const aAccessToken: string): IMVCRESTClient;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Add a header.
|
/// Add a header.
|
||||||
@ -464,12 +466,12 @@ var
|
|||||||
lContentCharset: string;
|
lContentCharset: string;
|
||||||
lEncoding: TEncoding;
|
lEncoding: TEncoding;
|
||||||
lBytes: TArray<Byte>;
|
lBytes: TArray<Byte>;
|
||||||
|
lContentType: string;
|
||||||
begin
|
begin
|
||||||
Result := Self;
|
Result := Self;
|
||||||
|
|
||||||
SetContentType(aContentType);
|
SplitContentMediaTypeAndCharset(aContentType, lContentType, lContentCharset);
|
||||||
|
|
||||||
lContentCharset := GetContentTypeCharset(aContentType);
|
|
||||||
if lContentCharset.IsEmpty then
|
if lContentCharset.IsEmpty then
|
||||||
begin
|
begin
|
||||||
lContentCharset := TMVCCharSet.UTF_8;
|
lContentCharset := TMVCCharSet.UTF_8;
|
||||||
@ -477,8 +479,11 @@ begin
|
|||||||
lEncoding := TEncoding.GetEncoding(lContentCharset);
|
lEncoding := TEncoding.GetEncoding(lContentCharset);
|
||||||
try
|
try
|
||||||
fRawBody.Clear;
|
fRawBody.Clear;
|
||||||
|
|
||||||
lBytes := TEncoding.Convert(TEncoding.Default, lEncoding, TEncoding.Default.GetBytes(aBody));
|
lBytes := TEncoding.Convert(TEncoding.Default, lEncoding, TEncoding.Default.GetBytes(aBody));
|
||||||
|
lBytes := lEncoding.GetBytes(aBody);
|
||||||
fRawBody.WriteData(lBytes, Length(lBytes));
|
fRawBody.WriteData(lBytes, Length(lBytes));
|
||||||
|
SetContentType(BuildContentType(lContentType, lContentCharset));
|
||||||
finally
|
finally
|
||||||
FreeAndNil(lEncoding);
|
FreeAndNil(lEncoding);
|
||||||
end;
|
end;
|
||||||
@ -657,7 +662,7 @@ end;
|
|||||||
function TMVCRESTClient.Async(aCompletionHandler: TProc<IMVCRESTResponse>;
|
function TMVCRESTClient.Async(aCompletionHandler: TProc<IMVCRESTResponse>;
|
||||||
aCompletionHandlerWithError: TProc<Exception>; const aSynchronized: Boolean): IMVCRESTClient;
|
aCompletionHandlerWithError: TProc<Exception>; const aSynchronized: Boolean): IMVCRESTClient;
|
||||||
begin
|
begin
|
||||||
|
// Needs implementation
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TMVCRESTClient.BaseURL(const aBaseURL: string): IMVCRESTClient;
|
function TMVCRESTClient.BaseURL(const aBaseURL: string): IMVCRESTClient;
|
||||||
@ -685,6 +690,7 @@ function TMVCRESTClient.ClearAllParams: IMVCRESTClient;
|
|||||||
begin
|
begin
|
||||||
Result := Self;
|
Result := Self;
|
||||||
fParameters.Clear;
|
fParameters.Clear;
|
||||||
|
ClearBody;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TMVCRESTClient.ClearBody: IMVCRESTClient;
|
function TMVCRESTClient.ClearBody: IMVCRESTClient;
|
||||||
@ -693,7 +699,9 @@ begin
|
|||||||
if Assigned(fBodyFormData) then
|
if Assigned(fBodyFormData) then
|
||||||
FreeAndNil(fBodyFormData);
|
FreeAndNil(fBodyFormData);
|
||||||
|
|
||||||
|
Result := Self;
|
||||||
ClearParameters(TMVCRESTParamType.FormURLEncoded);
|
ClearParameters(TMVCRESTParamType.FormURLEncoded);
|
||||||
|
fInternalContentType := '';
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TMVCRESTClient.ClearCookies: IMVCRESTClient;
|
function TMVCRESTClient.ClearCookies: IMVCRESTClient;
|
||||||
@ -829,6 +837,7 @@ procedure TMVCRESTClient.DoApplyHeaders;
|
|||||||
var
|
var
|
||||||
lParam: TMVCRESTParam;
|
lParam: TMVCRESTParam;
|
||||||
begin
|
begin
|
||||||
|
fHTTPClient.CustHeaders.Clear;
|
||||||
for lParam in fParameters do
|
for lParam in fParameters do
|
||||||
begin
|
begin
|
||||||
if lParam.&Type = TMVCRESTParamType.Header then
|
if lParam.&Type = TMVCRESTParamType.Header then
|
||||||
@ -849,7 +858,8 @@ begin
|
|||||||
if lParam.&Type = TMVCRESTParamType.Path then
|
if lParam.&Type = TMVCRESTParamType.Path then
|
||||||
begin
|
begin
|
||||||
lReplace := '{' + lParam.Name + '}';
|
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]);
|
aURL := aURL.Replace(lReplace, lEncodedParam, [rfReplaceAll, rfIgnoreCase]);
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
@ -866,8 +876,7 @@ begin
|
|||||||
begin
|
begin
|
||||||
if lParam.&Type = TMVCRESTParamType.Query then
|
if lParam.&Type = TMVCRESTParamType.Query then
|
||||||
begin
|
begin
|
||||||
lName := TNetEncoding.URL.Encode(lParam.Name, TMVCRESTClientConsts.QUERY_NAME_UNSAFE_CHARS,
|
lName := TMVCRESTClientHelper.URIEncode(lParam.Name);
|
||||||
[TURLEncoding.TEncodeOption.EncodePercent]);
|
|
||||||
lValue := TNetEncoding.URL.EncodeForm(lParam.Value);
|
lValue := TNetEncoding.URL.EncodeForm(lParam.Value);
|
||||||
|
|
||||||
if aURL.Contains('?') then
|
if aURL.Contains('?') then
|
||||||
@ -896,11 +905,55 @@ begin
|
|||||||
aURL := TURI.Create(aURL).Encode;
|
aURL := TURI.Create(aURL).Encode;
|
||||||
end;
|
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;
|
function TMVCRESTClient.ExecuteRequest(const aMethod: TMVCHTTPMethodType): IMVCRESTResponse;
|
||||||
var
|
var
|
||||||
lURL: string;
|
lURL: string;
|
||||||
lResponse: IHTTPResponse;
|
lResponse: IHTTPResponse;
|
||||||
|
lBodyStream: TStream;
|
||||||
begin
|
begin
|
||||||
|
fHTTPClient.ProxySettings := fProxySettings;
|
||||||
|
|
||||||
lURL := GetFullURL;
|
lURL := GetFullURL;
|
||||||
DoConvertMVCPathParamsToRESTParams(lURL);
|
DoConvertMVCPathParamsToRESTParams(lURL);
|
||||||
DoApplyPathParams(lURL);
|
DoApplyPathParams(lURL);
|
||||||
@ -909,23 +962,30 @@ begin
|
|||||||
DoApplyHeaders;
|
DoApplyHeaders;
|
||||||
DoApplyCookies(lURL);
|
DoApplyCookies(lURL);
|
||||||
|
|
||||||
|
lBodyStream := nil;
|
||||||
|
DoPrepareBodyRequest(lBodyStream);
|
||||||
|
|
||||||
case aMethod of
|
case aMethod of
|
||||||
httpGET:
|
httpGET:
|
||||||
lResponse := fHTTPClient.Get(lURL, nil, []);
|
begin
|
||||||
|
lResponse := fHTTPClient.Get(lURL, nil, [])
|
||||||
|
end;
|
||||||
httpPOST:
|
httpPOST:
|
||||||
;
|
begin
|
||||||
|
lResponse := fHTTPClient.Post(lURL, lBodyStream, nil, []);
|
||||||
|
end;
|
||||||
httpPUT:
|
httpPUT:
|
||||||
;
|
begin
|
||||||
httpDELETE:
|
lResponse := fHTTPClient.Put(lURL, lBodyStream, nil, []);
|
||||||
;
|
end;
|
||||||
httpHEAD:
|
|
||||||
;
|
|
||||||
httpOPTIONS:
|
|
||||||
;
|
|
||||||
httpPATCH:
|
httpPATCH:
|
||||||
;
|
begin
|
||||||
httpTRACE:
|
lResponse := fHTTPClient.Patch(lURL, lBodyStream, nil, []);
|
||||||
;
|
end;
|
||||||
|
httpDELETE:
|
||||||
|
begin
|
||||||
|
lResponse := fHTTPClient.Delete(lURL, nil, []);
|
||||||
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
Result := TMVCRESTResponse.Create(lResponse);
|
Result := TMVCRESTResponse.Create(lResponse);
|
||||||
@ -946,13 +1006,6 @@ begin
|
|||||||
Result := fBodyFormData;
|
Result := fBodyFormData;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TMVCRESTClient.GetContentTypeCharset(const aContentType: string): string;
|
|
||||||
var
|
|
||||||
lContentType: string;
|
|
||||||
begin
|
|
||||||
SplitContentMediaTypeAndCharset(aContentType, lContentType, Result);
|
|
||||||
end;
|
|
||||||
|
|
||||||
function TMVCRESTClient.GetFullURL: string;
|
function TMVCRESTClient.GetFullURL: string;
|
||||||
var
|
var
|
||||||
lResource: string;
|
lResource: string;
|
||||||
@ -1206,17 +1259,29 @@ begin
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
function TMVCRESTClient.SetBasicAuthorization(const aUsername, aPassword: string): IMVCRESTClient;
|
function TMVCRESTClient.SetBasicAuthorization(const aUsername, aPassword: string): IMVCRESTClient;
|
||||||
|
var
|
||||||
|
lBase64: TNetEncoding;
|
||||||
|
lAuthValue: string;
|
||||||
begin
|
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;
|
end;
|
||||||
|
|
||||||
function TMVCRESTClient.SetBearerAuthorization(const aToken: string): IMVCRESTClient;
|
function TMVCRESTClient.SetBearerAuthorization(const aAccessToken: string): IMVCRESTClient;
|
||||||
begin
|
begin
|
||||||
|
Result := AddHeader(TMVCRESTClientConsts.AUTHORIZATION_HEADER, TMVCRESTClientConsts.BEARER_AUTH_PREFIX +
|
||||||
|
aAccessToken);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TMVCRESTClient.SetContentType(const aContentType: string);
|
procedure TMVCRESTClient.SetContentType(const aContentType: string);
|
||||||
begin
|
begin
|
||||||
|
fInternalContentType := aContentType;
|
||||||
AddHeader(sContentType, aContentType);
|
AddHeader(sContentType, aContentType);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@ -1302,7 +1367,7 @@ begin
|
|||||||
fServer := aHTTPResponse.HeaderValue[TMVCRESTClientConsts.SERVER_HEADER];
|
fServer := aHTTPResponse.HeaderValue[TMVCRESTClientConsts.SERVER_HEADER];
|
||||||
fRawBytes := TMVCRESTClientHelper.GetResponseContentAsRawBytes(aHTTPResponse.ContentStream,
|
fRawBytes := TMVCRESTClientHelper.GetResponseContentAsRawBytes(aHTTPResponse.ContentStream,
|
||||||
aHTTPResponse.ContentEncoding);
|
aHTTPResponse.ContentEncoding);
|
||||||
fContent := TMVCRESTClientHelper.GetResponseContentAsString(fRawBytes, aHTTPResponse.ContentCharSet);
|
fContent := TMVCRESTClientHelper.GetResponseContentAsString(fRawBytes, aHTTPResponse.HeaderValue[sContentType]);
|
||||||
fContentType := aHTTPResponse.HeaderValue[sContentType];
|
fContentType := aHTTPResponse.HeaderValue[sContentType];
|
||||||
fContentEncoding := aHTTPResponse.ContentEncoding;
|
fContentEncoding := aHTTPResponse.ContentEncoding;
|
||||||
fContentLength := aHTTPResponse.ContentLength;
|
fContentLength := aHTTPResponse.ContentLength;
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<ProjectGuid>{0582DE6A-D716-46D3-8CBD-84AD73A4B536}</ProjectGuid>
|
<ProjectGuid>{0582DE6A-D716-46D3-8CBD-84AD73A4B536}</ProjectGuid>
|
||||||
<ProjectVersion>19.0</ProjectVersion>
|
<ProjectVersion>19.1</ProjectVersion>
|
||||||
<FrameworkType>VCL</FrameworkType>
|
<FrameworkType>VCL</FrameworkType>
|
||||||
<Base>True</Base>
|
<Base>True</Base>
|
||||||
<Config Condition="'$(Config)'==''">GUI</Config>
|
<Config Condition="'$(Config)'==''">GUI</Config>
|
||||||
@ -709,6 +709,32 @@
|
|||||||
<Operation>0</Operation>
|
<Operation>0</Operation>
|
||||||
</Platform>
|
</Platform>
|
||||||
</DeployClass>
|
</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">
|
<DeployClass Name="iPad_Launch1024">
|
||||||
<Platform Name="iOSDevice">
|
<Platform Name="iOSDevice">
|
||||||
<Operation>1</Operation>
|
<Operation>1</Operation>
|
||||||
@ -871,6 +897,56 @@
|
|||||||
<Operation>1</Operation>
|
<Operation>1</Operation>
|
||||||
</Platform>
|
</Platform>
|
||||||
</DeployClass>
|
</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">
|
<DeployClass Name="iPhone_Launch1125">
|
||||||
<Platform Name="iOSDevice32">
|
<Platform Name="iOSDevice32">
|
||||||
<Operation>1</Operation>
|
<Operation>1</Operation>
|
||||||
@ -1065,6 +1141,66 @@
|
|||||||
<Operation>1</Operation>
|
<Operation>1</Operation>
|
||||||
</Platform>
|
</Platform>
|
||||||
</DeployClass>
|
</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">
|
<DeployClass Name="ProjectAndroidManifest">
|
||||||
<Platform Name="Android">
|
<Platform Name="Android">
|
||||||
<Operation>1</Operation>
|
<Operation>1</Operation>
|
||||||
|
@ -678,7 +678,7 @@ begin
|
|||||||
try
|
try
|
||||||
// no request body
|
// no request body
|
||||||
lRes := RESTClient
|
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');
|
.Post('/system/users/logged');
|
||||||
Assert.areEqual<Integer>(HTTP_STATUS.BadRequest, lRes.StatusCode,
|
Assert.areEqual<Integer>(HTTP_STATUS.BadRequest, lRes.StatusCode,
|
||||||
'Empty request body doesn''t return HTTP 400 Bad Request');
|
'Empty request body doesn''t return HTTP 400 Bad Request');
|
||||||
@ -1153,7 +1153,7 @@ procedure TServerTest.TestProducesConsumes02;
|
|||||||
var
|
var
|
||||||
res: IMVCRESTResponse;
|
res: IMVCRESTResponse;
|
||||||
begin
|
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('Hello World', res.Content);
|
||||||
Assert.areEqual(TMVCMediaType.TEXT_PLAIN, res.ContentType, True);
|
Assert.areEqual(TMVCMediaType.TEXT_PLAIN, res.ContentType, True);
|
||||||
|
|
||||||
@ -1173,7 +1173,7 @@ begin
|
|||||||
// Assert.areEqual(BuildContentType(TMVCMediaType.TEXT_PLAIN, TMVCCharSet.ISO88591), res.ContentType, True);
|
// Assert.areEqual(BuildContentType(TMVCMediaType.TEXT_PLAIN, TMVCCharSet.ISO88591), res.ContentType, True);
|
||||||
|
|
||||||
res := RESTClient.Accept(TMVCMediaType.TEXT_PLAIN)
|
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<Integer>(HTTP_STATUS.OK, res.StatusCode);
|
||||||
Assert.areEqual('this is an iso8859-1 text', res.Content);
|
Assert.areEqual('this is an iso8859-1 text', res.Content);
|
||||||
Assert.areEqual(TMVCMediaType.TEXT_PLAIN, res.ContentType, True);
|
Assert.areEqual(TMVCMediaType.TEXT_PLAIN, res.ContentType, True);
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
<TargetedPlatforms>129</TargetedPlatforms>
|
<TargetedPlatforms>129</TargetedPlatforms>
|
||||||
<AppType>Console</AppType>
|
<AppType>Console</AppType>
|
||||||
<FrameworkType>None</FrameworkType>
|
<FrameworkType>None</FrameworkType>
|
||||||
<ProjectVersion>19.0</ProjectVersion>
|
<ProjectVersion>19.1</ProjectVersion>
|
||||||
<Platform Condition="'$(Platform)'==''">Win32</Platform>
|
<Platform Condition="'$(Platform)'==''">Win32</Platform>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition="'$(Config)'=='Base' or '$(Base)'!=''">
|
<PropertyGroup Condition="'$(Config)'=='Base' or '$(Base)'!=''">
|
||||||
@ -146,12 +146,6 @@
|
|||||||
<Overwrite>true</Overwrite>
|
<Overwrite>true</Overwrite>
|
||||||
</Platform>
|
</Platform>
|
||||||
</DeployFile>
|
</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">
|
<DeployFile LocalName="bin\www\index.html" Configuration="CI" Class="File">
|
||||||
<Platform Name="Linux64">
|
<Platform Name="Linux64">
|
||||||
<RemoteDir>.\www</RemoteDir>
|
<RemoteDir>.\www</RemoteDir>
|
||||||
@ -159,6 +153,12 @@
|
|||||||
<Overwrite>true</Overwrite>
|
<Overwrite>true</Overwrite>
|
||||||
</Platform>
|
</Platform>
|
||||||
</DeployFile>
|
</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">
|
<DeployFile LocalName="bin\customers.json" Configuration="CI" Class="File">
|
||||||
<Platform Name="Linux64">
|
<Platform Name="Linux64">
|
||||||
<RemoteName>customers.json</RemoteName>
|
<RemoteName>customers.json</RemoteName>
|
||||||
@ -541,6 +541,32 @@
|
|||||||
<Operation>0</Operation>
|
<Operation>0</Operation>
|
||||||
</Platform>
|
</Platform>
|
||||||
</DeployClass>
|
</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">
|
<DeployClass Name="iPad_Launch1024x768">
|
||||||
<Platform Name="iOSDevice32">
|
<Platform Name="iOSDevice32">
|
||||||
<Operation>1</Operation>
|
<Operation>1</Operation>
|
||||||
@ -671,6 +697,56 @@
|
|||||||
<Operation>1</Operation>
|
<Operation>1</Operation>
|
||||||
</Platform>
|
</Platform>
|
||||||
</DeployClass>
|
</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">
|
<DeployClass Name="iPhone_Launch1125">
|
||||||
<Platform Name="iOSDevice32">
|
<Platform Name="iOSDevice32">
|
||||||
<Operation>1</Operation>
|
<Operation>1</Operation>
|
||||||
@ -865,6 +941,66 @@
|
|||||||
<Operation>1</Operation>
|
<Operation>1</Operation>
|
||||||
</Platform>
|
</Platform>
|
||||||
</DeployClass>
|
</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">
|
<DeployClass Name="ProjectAndroidManifest">
|
||||||
<Platform Name="Android">
|
<Platform Name="Android">
|
||||||
<Operation>1</Operation>
|
<Operation>1</Operation>
|
||||||
|
Loading…
Reference in New Issue
Block a user