2016-06-22 17:49:16 +02:00
|
|
|
|
// ***************************************************************************
|
|
|
|
|
//
|
|
|
|
|
// Delphi MVC Framework
|
|
|
|
|
//
|
|
|
|
|
// Copyright (c) 2010-2016 Daniele Teti and the DMVCFramework Team
|
|
|
|
|
//
|
|
|
|
|
// https://github.com/danieleteti/delphimvcframework
|
|
|
|
|
//
|
|
|
|
|
// ***************************************************************************
|
|
|
|
|
//
|
|
|
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
|
// you may not use this file except in compliance with the License.
|
|
|
|
|
// You may obtain a copy of the License at
|
|
|
|
|
//
|
|
|
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
|
//
|
|
|
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
|
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
|
// See the License for the specific language governing permissions and
|
|
|
|
|
// limitations under the License.
|
|
|
|
|
//
|
|
|
|
|
// *************************************************************************** }
|
2015-12-22 12:38:17 +01:00
|
|
|
|
|
2013-10-30 00:48:23 +01:00
|
|
|
|
unit MVCFramework.Router;
|
|
|
|
|
|
|
|
|
|
interface
|
|
|
|
|
|
|
|
|
|
uses
|
|
|
|
|
Web.HTTPApp,
|
2016-09-30 11:44:11 +02:00
|
|
|
|
MVCFramework.RTTIUtils,
|
2013-10-30 00:48:23 +01:00
|
|
|
|
MVCFramework.Commons,
|
|
|
|
|
System.RTTI,
|
|
|
|
|
MVCFramework,
|
|
|
|
|
System.Generics.Collections;
|
|
|
|
|
|
|
|
|
|
type
|
|
|
|
|
TMVCRouter = class
|
|
|
|
|
private
|
2014-04-01 00:02:31 +02:00
|
|
|
|
FCTX: TRttiContext;
|
2013-10-30 00:48:23 +01:00
|
|
|
|
FMethodToCall: TRTTIMethod;
|
|
|
|
|
FMVCControllerClass: TMVCControllerClass;
|
2016-02-29 13:48:36 +01:00
|
|
|
|
FMVCControllerDelegate: TMVCControllerDelegate;
|
2013-10-30 00:48:23 +01:00
|
|
|
|
FMVCConfig: TMVCConfig;
|
2015-04-01 17:01:23 +02:00
|
|
|
|
function IsHTTPContentTypeCompatible(AWebRequestMethodType: TMVCHTTPMethodType;
|
2016-08-24 15:34:26 +02:00
|
|
|
|
AContentType: string; AAttributes: TArray<TCustomAttribute>): Boolean;
|
2015-04-01 17:01:23 +02:00
|
|
|
|
function IsHTTPAcceptCompatible(AWebRequestMethodType: TMVCHTTPMethodType; AAccept: string;
|
2013-11-09 14:22:11 +01:00
|
|
|
|
AAttributes: TArray<TCustomAttribute>): Boolean;
|
2014-06-27 15:30:39 +02:00
|
|
|
|
function GetFirstMimeType(const AContentType: string): string;
|
2013-10-30 00:48:23 +01:00
|
|
|
|
protected
|
|
|
|
|
function IsHTTPMethodCompatible(AMethodType: TMVCHTTPMethodType;
|
|
|
|
|
AAttributes: TArray<TCustomAttribute>): Boolean; virtual;
|
2015-04-01 17:01:23 +02:00
|
|
|
|
function IsCompatiblePath(AMVCPath: string; APath: string; var AParams: TMVCRequestParamsTable)
|
|
|
|
|
: Boolean; virtual;
|
|
|
|
|
function GetAttribute<T: TCustomAttribute>(AAttributes: TArray<TCustomAttribute>): T;
|
2013-10-30 00:48:23 +01:00
|
|
|
|
|
|
|
|
|
public
|
2015-04-01 17:01:23 +02:00
|
|
|
|
class function StringMethodToHTTPMetod(const Value: AnsiString): TMVCHTTPMethodType;
|
2013-10-30 00:48:23 +01:00
|
|
|
|
constructor Create(AMVCConfig: TMVCConfig);
|
2016-09-27 14:22:17 +02:00
|
|
|
|
function ExecuteRouting(const AWebRequestPathInfo: AnsiString;
|
|
|
|
|
AWebRequestMethodType: TMVCHTTPMethodType; const AWebRequestContentType: AnsiString;
|
|
|
|
|
const AWebRequestAccept: AnsiString; AMVCControllers: TObjectList<TMVCControllerRoutable>;
|
|
|
|
|
const ADefaultContentType: string; const ADefaultContentCharset: string;
|
2015-04-01 17:01:23 +02:00
|
|
|
|
var AMVCRequestParams: TMVCRequestParamsTable; out AResponseContentType: string;
|
|
|
|
|
out AResponseContentEncoding: string): Boolean; overload;
|
2013-10-30 00:48:23 +01:00
|
|
|
|
property MethodToCall: TRTTIMethod read FMethodToCall;
|
|
|
|
|
property MVCControllerClass: TMVCControllerClass read FMVCControllerClass;
|
2016-02-29 13:48:36 +01:00
|
|
|
|
property MVCControllerDelegate: TMVCControllerDelegate read FMVCControllerDelegate;
|
2013-10-30 00:48:23 +01:00
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
implementation
|
|
|
|
|
|
|
|
|
|
uses
|
2015-04-01 17:01:23 +02:00
|
|
|
|
System.AnsiStrings,
|
2013-10-30 00:48:23 +01:00
|
|
|
|
System.StrUtils,
|
|
|
|
|
System.RegularExpressions,
|
|
|
|
|
System.SysUtils,
|
|
|
|
|
idURI;
|
|
|
|
|
|
|
|
|
|
{ TMVCRouter }
|
|
|
|
|
|
|
|
|
|
constructor TMVCRouter.Create(AMVCConfig: TMVCConfig);
|
|
|
|
|
begin
|
|
|
|
|
inherited Create;
|
|
|
|
|
FMVCConfig := AMVCConfig;
|
|
|
|
|
end;
|
|
|
|
|
|
2016-09-27 14:22:17 +02:00
|
|
|
|
function TMVCRouter.ExecuteRouting(const AWebRequestPathInfo: AnsiString;
|
|
|
|
|
AWebRequestMethodType: TMVCHTTPMethodType; const AWebRequestContentType: AnsiString;
|
|
|
|
|
const AWebRequestAccept: AnsiString; AMVCControllers: TObjectList<TMVCControllerRoutable>;
|
|
|
|
|
const ADefaultContentType, ADefaultContentCharset: string;
|
2015-04-01 17:01:23 +02:00
|
|
|
|
var AMVCRequestParams: TMVCRequestParamsTable; out AResponseContentType: string;
|
2014-06-27 15:30:39 +02:00
|
|
|
|
out AResponseContentEncoding: string): Boolean;
|
2013-10-30 00:48:23 +01:00
|
|
|
|
var
|
2016-02-29 13:48:36 +01:00
|
|
|
|
controllerRoutable: TMVCControllerRoutable;
|
2013-10-30 00:48:23 +01:00
|
|
|
|
_type: TRttiType;
|
|
|
|
|
_methods: TArray<TRTTIMethod>;
|
|
|
|
|
_method: TRTTIMethod;
|
|
|
|
|
_attribute: TCustomAttribute;
|
2014-04-01 00:02:31 +02:00
|
|
|
|
_attributes: TArray<TCustomAttribute>;
|
2013-10-30 00:48:23 +01:00
|
|
|
|
i: Integer;
|
|
|
|
|
ControllerMappedPath: string;
|
|
|
|
|
MethodPathAttribute: string;
|
2013-11-09 14:22:11 +01:00
|
|
|
|
MVCProduceAttr: MVCProducesAttribute;
|
2014-10-26 20:48:52 +01:00
|
|
|
|
Found: Boolean;
|
2015-04-01 17:01:23 +02:00
|
|
|
|
LWebRequestPathInfo: string;
|
2016-08-24 15:34:26 +02:00
|
|
|
|
LWebRequestAccept: string;
|
2013-10-30 00:48:23 +01:00
|
|
|
|
begin
|
|
|
|
|
FMethodToCall := nil;
|
|
|
|
|
FMVCControllerClass := nil;
|
2016-02-29 13:48:36 +01:00
|
|
|
|
FMVCControllerDelegate := nil;
|
2016-08-24 15:34:26 +02:00
|
|
|
|
LWebRequestAccept := string(AWebRequestAccept);
|
2013-10-30 00:48:23 +01:00
|
|
|
|
|
2015-04-01 17:01:23 +02:00
|
|
|
|
LWebRequestPathInfo := string(AWebRequestPathInfo);
|
|
|
|
|
if Trim(LWebRequestPathInfo) = EmptyStr then
|
|
|
|
|
LWebRequestPathInfo := '/'
|
2013-10-30 00:48:23 +01:00
|
|
|
|
else
|
|
|
|
|
begin
|
2015-04-01 17:01:23 +02:00
|
|
|
|
if LWebRequestPathInfo[1] <> '/' then
|
|
|
|
|
LWebRequestPathInfo := '/' + LWebRequestPathInfo;
|
2013-10-30 00:48:23 +01:00
|
|
|
|
end;
|
|
|
|
|
|
2016-06-22 17:49:16 +02:00
|
|
|
|
// FIX https://github.com/danieleteti/delphimvcframework/issues/17
|
2015-11-15 18:31:08 +01:00
|
|
|
|
LWebRequestPathInfo := TIdURI.PathEncode(LWebRequestPathInfo);
|
2013-10-30 00:48:23 +01:00
|
|
|
|
|
2014-02-24 10:20:34 +01:00
|
|
|
|
{ ISAPI CHANGE THE REQUEST PATH INFO START }
|
|
|
|
|
if IsLibrary then
|
|
|
|
|
begin
|
2015-04-01 17:01:23 +02:00
|
|
|
|
if string(LWebRequestPathInfo).StartsWith(FMVCConfig.Value[TMVCConfigKey.ISAPIPath]) then
|
|
|
|
|
LWebRequestPathInfo := LWebRequestPathInfo.Remove(0,
|
|
|
|
|
FMVCConfig.Value[TMVCConfigKey.ISAPIPath].Length);
|
|
|
|
|
if Length(LWebRequestPathInfo) = 0 then
|
|
|
|
|
LWebRequestPathInfo := '/';
|
2014-02-24 10:20:34 +01:00
|
|
|
|
end;
|
|
|
|
|
{ ISAPI CHANGE THE REQUEST PATH INFO END }
|
|
|
|
|
|
2014-04-01 00:02:31 +02:00
|
|
|
|
TMonitor.Enter(Lock); // start of lock
|
|
|
|
|
try
|
2013-10-30 00:48:23 +01:00
|
|
|
|
|
2014-04-01 00:02:31 +02:00
|
|
|
|
Result := False;
|
|
|
|
|
ControllerMappedPath := '';
|
2016-02-29 13:48:36 +01:00
|
|
|
|
for controllerRoutable in AMVCControllers do
|
2014-04-01 00:02:31 +02:00
|
|
|
|
begin
|
|
|
|
|
SetLength(_attributes, 0);
|
2016-02-29 13:48:36 +01:00
|
|
|
|
_type := FCTX.GetType(controllerRoutable.&Class.ClassInfo);
|
2014-04-01 00:02:31 +02:00
|
|
|
|
_attributes := _type.GetAttributes;
|
2015-04-01 17:01:23 +02:00
|
|
|
|
if _attributes = nil then
|
2014-04-01 00:02:31 +02:00
|
|
|
|
Continue;
|
2013-10-30 00:48:23 +01:00
|
|
|
|
|
2014-10-26 20:48:52 +01:00
|
|
|
|
Found := False;
|
2014-04-01 00:02:31 +02:00
|
|
|
|
for _attribute in _attributes do
|
|
|
|
|
if _attribute is MVCPathAttribute then
|
|
|
|
|
begin
|
2014-10-26 20:48:52 +01:00
|
|
|
|
Found := True;
|
2014-04-01 00:02:31 +02:00
|
|
|
|
ControllerMappedPath := MVCPathAttribute(_attribute).Path;
|
|
|
|
|
Break;
|
|
|
|
|
end;
|
2013-10-30 00:48:23 +01:00
|
|
|
|
|
2014-10-26 20:48:52 +01:00
|
|
|
|
if not Found then
|
2015-04-01 17:01:23 +02:00
|
|
|
|
raise EMVCException.Create('Controller ' + _type.Name + ' doesn''t have MVCPath attribute');
|
2013-10-30 00:48:23 +01:00
|
|
|
|
|
2014-04-01 00:02:31 +02:00
|
|
|
|
if ControllerMappedPath = '/' then // WE WANT TO AVOID '//' AS MVCPATH
|
|
|
|
|
ControllerMappedPath := '';
|
2013-10-30 00:48:23 +01:00
|
|
|
|
|
2015-04-01 17:01:23 +02:00
|
|
|
|
if (not ControllerMappedPath.IsEmpty) and (Pos(ControllerMappedPath, LWebRequestPathInfo) <> 1)
|
|
|
|
|
then
|
2014-04-01 00:02:31 +02:00
|
|
|
|
Continue;
|
|
|
|
|
|
|
|
|
|
_methods := _type.GetMethods;
|
|
|
|
|
for _method in _methods do
|
2013-10-30 00:48:23 +01:00
|
|
|
|
begin
|
2014-04-01 00:02:31 +02:00
|
|
|
|
_attributes := _method.GetAttributes;
|
|
|
|
|
for i := 0 to Length(_attributes) - 1 do
|
2013-10-30 00:48:23 +01:00
|
|
|
|
begin
|
2014-04-01 00:02:31 +02:00
|
|
|
|
_attribute := _attributes[i];
|
|
|
|
|
if _attribute is MVCPathAttribute then
|
2013-10-30 00:48:23 +01:00
|
|
|
|
begin
|
2014-04-01 00:02:31 +02:00
|
|
|
|
if IsHTTPMethodCompatible(AWebRequestMethodType, _attributes) and
|
2016-08-24 15:34:26 +02:00
|
|
|
|
IsHTTPContentTypeCompatible(AWebRequestMethodType, string(AWebRequestContentType),
|
2015-04-01 17:01:23 +02:00
|
|
|
|
_attributes) and IsHTTPAcceptCompatible(AWebRequestMethodType, LWebRequestAccept,
|
2014-10-26 20:48:52 +01:00
|
|
|
|
_attributes) then
|
2013-10-30 00:48:23 +01:00
|
|
|
|
begin
|
2014-04-01 00:02:31 +02:00
|
|
|
|
MethodPathAttribute := MVCPathAttribute(_attribute).Path;
|
2015-04-01 17:01:23 +02:00
|
|
|
|
if IsCompatiblePath(ControllerMappedPath + MethodPathAttribute, LWebRequestPathInfo,
|
|
|
|
|
AMVCRequestParams) then
|
2013-11-08 23:10:25 +01:00
|
|
|
|
begin
|
2014-04-01 00:02:31 +02:00
|
|
|
|
FMethodToCall := _method;
|
2016-02-29 13:48:36 +01:00
|
|
|
|
FMVCControllerClass := controllerRoutable.&Class;
|
|
|
|
|
FMVCControllerDelegate := controllerRoutable.Delegate;
|
2014-04-01 00:02:31 +02:00
|
|
|
|
// getting the default contenttype using MVCProduceAttribute
|
2015-04-01 17:01:23 +02:00
|
|
|
|
MVCProduceAttr := GetAttribute<MVCProducesAttribute>(_attributes);
|
|
|
|
|
if MVCProduceAttr <> nil then
|
2014-04-01 00:02:31 +02:00
|
|
|
|
begin
|
|
|
|
|
AResponseContentType := MVCProduceAttr.Value;
|
|
|
|
|
AResponseContentEncoding := MVCProduceAttr.ProduceEncoding;
|
|
|
|
|
end
|
|
|
|
|
else
|
|
|
|
|
begin
|
|
|
|
|
AResponseContentType := ADefaultContentType;
|
2014-04-10 13:56:23 +02:00
|
|
|
|
AResponseContentEncoding := ADefaultContentCharset;
|
2014-04-01 00:02:31 +02:00
|
|
|
|
end;
|
2014-10-26 20:48:52 +01:00
|
|
|
|
Exit(True);
|
2014-04-01 00:02:31 +02:00
|
|
|
|
end; // if is compatible path
|
|
|
|
|
end; // if is compatible method, contenttype and accept
|
|
|
|
|
end; // if attribute is mvcpath
|
|
|
|
|
end; // for each attributes on method
|
|
|
|
|
end; // for each methods
|
|
|
|
|
end; // for each controllers
|
|
|
|
|
finally
|
|
|
|
|
TMonitor.Exit(Lock);
|
2013-10-30 00:48:23 +01:00
|
|
|
|
end;
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
function TMVCRouter.GetAttribute<T>(AAttributes: TArray<TCustomAttribute>): T;
|
|
|
|
|
var
|
|
|
|
|
a: TCustomAttribute;
|
|
|
|
|
begin
|
|
|
|
|
Result := nil;
|
|
|
|
|
for a in AAttributes do
|
|
|
|
|
if a is T then
|
|
|
|
|
Exit(T(a));
|
|
|
|
|
end;
|
|
|
|
|
|
2014-10-26 20:48:52 +01:00
|
|
|
|
function TMVCRouter.GetFirstMimeType(const AContentType: string): string;
|
2014-06-27 15:30:39 +02:00
|
|
|
|
begin
|
|
|
|
|
Result := AContentType;
|
|
|
|
|
while Pos(',', Result) > 0 do
|
|
|
|
|
Result := Copy(Result, 1, Pos(',', Result) - 1);
|
|
|
|
|
while Pos(';', Result) > 0 do
|
2014-10-26 20:48:52 +01:00
|
|
|
|
Result := Copy(Result, 1, Pos(';', Result) - 1);
|
|
|
|
|
// application/json;charset=UTF-8 {daniele}
|
2014-06-27 15:30:39 +02:00
|
|
|
|
end;
|
|
|
|
|
|
2013-10-30 00:48:23 +01:00
|
|
|
|
function TMVCRouter.IsCompatiblePath(AMVCPath: string; APath: string;
|
|
|
|
|
var AParams: TMVCRequestParamsTable): Boolean;
|
|
|
|
|
function ToPattern(const V: string; Names: TList<string>): string;
|
|
|
|
|
var
|
|
|
|
|
s: string;
|
|
|
|
|
begin
|
|
|
|
|
Result := V;
|
|
|
|
|
for s in Names do
|
2015-06-08 10:51:08 +02:00
|
|
|
|
Result := StringReplace(Result, '($' + s + ')', '([ <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>@\.\_\,%\w\d\x2D\x3A]*)',
|
2015-04-01 17:01:23 +02:00
|
|
|
|
[rfReplaceAll]);
|
2013-10-30 00:48:23 +01:00
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
function GetParametersNames(const V: string): TList<string>;
|
|
|
|
|
var
|
|
|
|
|
s: string;
|
|
|
|
|
matches: TMatchCollection;
|
|
|
|
|
match: TMatch;
|
|
|
|
|
i: Integer;
|
|
|
|
|
begin
|
|
|
|
|
Result := TList<string>.Create;
|
2016-08-24 15:34:26 +02:00
|
|
|
|
s := '\(\$([A-Za-z0-9\_]+)\)';
|
|
|
|
|
// dt 2/08/2016 added "_" as allowed character in the parameter name
|
2013-10-30 00:48:23 +01:00
|
|
|
|
matches := TRegEx.matches(V, s, [roIgnoreCase, roCompiled, roSingleLine]);
|
|
|
|
|
for match in matches do
|
|
|
|
|
for i := 0 to match.Groups.Count - 1 do
|
|
|
|
|
begin
|
|
|
|
|
s := match.Groups[i].Value;
|
|
|
|
|
if (Length(s) > 0) and (s[1] <> '(') then
|
|
|
|
|
begin
|
|
|
|
|
Result.Add(s);
|
|
|
|
|
Break;
|
|
|
|
|
end;
|
|
|
|
|
end;
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
var
|
|
|
|
|
re: TRegEx;
|
|
|
|
|
m: TMatch;
|
|
|
|
|
pattern: string;
|
|
|
|
|
i: Integer;
|
|
|
|
|
Names: TList<string>;
|
|
|
|
|
begin
|
|
|
|
|
Names := GetParametersNames(AMVCPath);
|
|
|
|
|
try
|
|
|
|
|
pattern := ToPattern(AMVCPath, Names);
|
|
|
|
|
if APath = AMVCPath then
|
2014-10-26 20:48:52 +01:00
|
|
|
|
Exit(True)
|
2013-10-30 00:48:23 +01:00
|
|
|
|
else
|
|
|
|
|
begin
|
2015-04-01 17:01:23 +02:00
|
|
|
|
re := TRegEx.Create('^' + pattern + '$', [roIgnoreCase, roCompiled, roSingleLine]);
|
2013-10-30 00:48:23 +01:00
|
|
|
|
m := re.match(APath);
|
|
|
|
|
Result := m.Success;
|
|
|
|
|
if Result then
|
|
|
|
|
for i := 1 to pred(m.Groups.Count) do
|
|
|
|
|
AParams.Add(Names[i - 1], TIdURI.URLDecode(m.Groups[i].Value));
|
|
|
|
|
end;
|
|
|
|
|
finally
|
|
|
|
|
Names.Free;
|
|
|
|
|
end;
|
|
|
|
|
end;
|
|
|
|
|
|
2015-04-01 17:01:23 +02:00
|
|
|
|
function TMVCRouter.IsHTTPAcceptCompatible(AWebRequestMethodType: TMVCHTTPMethodType;
|
|
|
|
|
AAccept: string; AAttributes: TArray<TCustomAttribute>): Boolean;
|
2013-11-09 14:22:11 +01:00
|
|
|
|
var
|
|
|
|
|
i: Integer;
|
2014-04-01 00:02:31 +02:00
|
|
|
|
MethodAccept: string;
|
|
|
|
|
FoundOneAttribProduces: Boolean;
|
|
|
|
|
begin
|
|
|
|
|
Result := False;
|
|
|
|
|
FoundOneAttribProduces := False;
|
|
|
|
|
for i := 0 to high(AAttributes) do
|
|
|
|
|
begin
|
|
|
|
|
if AAttributes[i] is MVCProducesAttribute then
|
|
|
|
|
begin
|
2014-10-26 20:48:52 +01:00
|
|
|
|
FoundOneAttribProduces := True;
|
2014-04-01 00:02:31 +02:00
|
|
|
|
MethodAccept := MVCProducesAttribute(AAttributes[i]).Value;
|
2014-06-27 15:30:39 +02:00
|
|
|
|
AAccept := GetFirstMimeType(AAccept);
|
2014-06-30 17:00:46 +02:00
|
|
|
|
// while Pos(',', AAccept) > 0 do
|
|
|
|
|
// AAccept := Copy(AAccept, 1, Pos(',', AAccept) - 1);
|
2014-06-27 15:30:39 +02:00
|
|
|
|
|
2014-04-01 00:02:31 +02:00
|
|
|
|
Result := SameText(AAccept, MethodAccept, loInvariantLocale);
|
|
|
|
|
if Result then
|
|
|
|
|
Break;
|
|
|
|
|
end;
|
|
|
|
|
end;
|
|
|
|
|
Result := (not FoundOneAttribProduces) or (FoundOneAttribProduces and Result);
|
|
|
|
|
end;
|
|
|
|
|
|
2015-04-01 17:01:23 +02:00
|
|
|
|
function TMVCRouter.IsHTTPContentTypeCompatible(AWebRequestMethodType: TMVCHTTPMethodType;
|
2016-08-24 15:34:26 +02:00
|
|
|
|
AContentType: string; AAttributes: TArray<TCustomAttribute>): Boolean;
|
2014-04-01 00:02:31 +02:00
|
|
|
|
var
|
|
|
|
|
i: Integer;
|
|
|
|
|
MethodContentType: string;
|
2013-11-09 14:22:11 +01:00
|
|
|
|
FoundOneAttribConsumes: Boolean;
|
|
|
|
|
begin
|
2014-03-24 17:37:08 +01:00
|
|
|
|
// content type is applicable only for PUT, POST and PATCH
|
|
|
|
|
if AWebRequestMethodType in [httpGET, httpDELETE, httpHEAD, httpOPTIONS] then
|
2014-10-26 20:48:52 +01:00
|
|
|
|
Exit(True);
|
2014-03-24 17:37:08 +01:00
|
|
|
|
|
2013-11-09 14:22:11 +01:00
|
|
|
|
Result := False;
|
|
|
|
|
FoundOneAttribConsumes := False;
|
|
|
|
|
for i := 0 to high(AAttributes) do
|
|
|
|
|
begin
|
|
|
|
|
if AAttributes[i] is MVCConsumesAttribute then
|
|
|
|
|
begin
|
2014-10-26 20:48:52 +01:00
|
|
|
|
FoundOneAttribConsumes := True;
|
2014-04-01 00:02:31 +02:00
|
|
|
|
MethodContentType := MVCConsumesAttribute(AAttributes[i]).Value;
|
2014-06-27 15:30:39 +02:00
|
|
|
|
AContentType := GetFirstMimeType(AContentType);
|
2014-04-01 00:02:31 +02:00
|
|
|
|
Result := SameText(AContentType, MethodContentType, loInvariantLocale);
|
|
|
|
|
if Result then
|
|
|
|
|
Break;
|
2013-11-09 14:22:11 +01:00
|
|
|
|
end;
|
|
|
|
|
end;
|
|
|
|
|
Result := (not FoundOneAttribConsumes) or (FoundOneAttribConsumes and Result);
|
|
|
|
|
end;
|
|
|
|
|
|
2013-10-30 00:48:23 +01:00
|
|
|
|
function TMVCRouter.IsHTTPMethodCompatible(AMethodType: TMVCHTTPMethodType;
|
|
|
|
|
AAttributes: TArray<TCustomAttribute>): Boolean;
|
|
|
|
|
var
|
|
|
|
|
i: Integer;
|
|
|
|
|
MustBeCompatible: Boolean;
|
|
|
|
|
CompatibleMethods: TMVCHTTPMethods;
|
|
|
|
|
begin
|
|
|
|
|
Result := False;
|
2013-11-09 14:22:11 +01:00
|
|
|
|
// if there aren't MVCHTTPMethod attributes defined, the action is compatibile with all methods
|
2013-10-30 00:48:23 +01:00
|
|
|
|
MustBeCompatible := False;
|
|
|
|
|
for i := 0 to high(AAttributes) do
|
|
|
|
|
begin
|
|
|
|
|
if AAttributes[i] is MVCHTTPMethodAttribute then
|
|
|
|
|
begin
|
2014-10-26 20:48:52 +01:00
|
|
|
|
MustBeCompatible := True;
|
2015-04-01 17:01:23 +02:00
|
|
|
|
CompatibleMethods := MVCHTTPMethodAttribute(AAttributes[i]).MVCHTTPMethods;
|
2013-10-30 00:48:23 +01:00
|
|
|
|
Result := (AMethodType in CompatibleMethods);
|
|
|
|
|
end;
|
|
|
|
|
end;
|
2013-11-09 14:22:11 +01:00
|
|
|
|
Result := (not MustBeCompatible) or (MustBeCompatible and Result);
|
2013-10-30 00:48:23 +01:00
|
|
|
|
end;
|
|
|
|
|
|
2015-04-01 17:01:23 +02:00
|
|
|
|
class function TMVCRouter.StringMethodToHTTPMetod(const Value: AnsiString): TMVCHTTPMethodType;
|
2013-10-30 00:48:23 +01:00
|
|
|
|
begin
|
|
|
|
|
if Value = 'GET' then
|
|
|
|
|
Exit(httpGET);
|
|
|
|
|
if Value = 'POST' then
|
|
|
|
|
Exit(httpPOST);
|
|
|
|
|
if Value = 'DELETE' then
|
|
|
|
|
Exit(httpDELETE);
|
|
|
|
|
if Value = 'PUT' then
|
|
|
|
|
Exit(httpPUT);
|
|
|
|
|
if Value = 'HEAD' then
|
|
|
|
|
Exit(httpHEAD);
|
|
|
|
|
if Value = 'OPTIONS' then
|
|
|
|
|
Exit(httpOPTIONS);
|
2014-03-24 17:37:08 +01:00
|
|
|
|
if Value = 'PATCH' then
|
|
|
|
|
Exit(httpPATCH);
|
|
|
|
|
if Value = 'TRACE' then
|
|
|
|
|
Exit(httpTRACE);
|
2013-10-30 00:48:23 +01:00
|
|
|
|
raise EMVCException.CreateFmt('Unknown HTTP method [%s]', [Value]);
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
end.
|