mormot2 http路由
mormot2 http路由
mormot.net.server.pas
重写包括2部分:重写URL+重写HTTP METHOD。如果你用过GO就会惊喜地发现它与GO的HTTP路由非常相似以及更加方便。
mormot2官方关于路由的博客:https://blog.synopse.info/?post/2022/12/25/Efficient-Routing-for-Christmas
/// efficient server-side URI routing for THttpServerGeneric // - Process() is done with no memory allocation for a static route, // using a very efficient Radix Tree for path lookup, over a thread-safe // non-blocking URI parsing with values extractions for rewrite or execution // - here are some numbers from TNetworkProtocols._TUriTree on my laptop: // $ 1000 URI lookups in 37us i.e. 25.7M/s, aver. 37ns // $ 1000 URI static rewrites in 80us i.e. 11.9M/s, aver. 80ns // $ 1000 URI parametrized rewrites in 117us i.e. 8.1M/s, aver. 117ns // $ 1000 URI static execute in 91us i.e. 10.4M/s, aver. 91ns // $ 1000 URI parametrized execute in 162us i.e. 5.8M/s, aver. 162ns TUriRouter = class(TSynPersistentRWLightLock) protected fTree: TUriRouterTree; fTreeOptions: TRadixTreeOptions; fEntries: array[urmGet .. high(TUriRouterMethod)] of integer; procedure Setup(aFrom: TUriRouterMethod; const aFromUri: RawUtf8; aTo: TUriRouterMethod; const aToUri: RawUtf8; const aExecute: TOnHttpServerRequest); public /// initialize this URI routing engine constructor Create(aOptions: TRadixTreeOptions = []); reintroduce; /// finalize this URI routing engine destructor Destroy; override; /// register an URI rewrite with optional <param> place holders // - <param> will be replaced in aToUri // - if aToUri is an '200'..'599' integer, it will return it as HTTP error // - otherwise, the URI will be rewritten into aToUri, e.g. // $ Rewrite(urmGet, '/info', urmGet, 'root/timestamp/info'); // $ Rewrite(urmGet, '/path/from/<from>/to/<to>', urmPost, // $ '/root/myservice/convert?from=<from>&to=<to>'); // for IMyService.Convert // $ Rewrite(urmGet, '/index.php', '400'); // to avoid fuzzing // $ Rewrite(urmGet, '/*', '/static/*' // '*' synonymous to '<path:path>' procedure Rewrite(aFrom: TUriRouterMethod; const aFromUri: RawUtf8; aTo: TUriRouterMethod; const aToUri: RawUtf8); /// just a wrapper around Rewrite(urmGet, aFrom, aToMethod, aTo) // - e.g. Route.Get('/info', 'root/timestamp/info'); // - e.g. Route.Get('/user/<id>', '/root/userservice/new?id=<id>'); will // rewrite internally '/user/1234' URI as '/root/userservice/new?id=1234' // - e.g. Route.Get('/user/<int:id>', '/root/userservice/new?id=<id>'); // to ensure id is a real integer before redirection // - e.g. Route.Get('/admin.php', '403'); // - e.g. Route.Get('/*', '/static/*'); with '*' synonymous to '<path:path>' procedure Get(const aFrom, aTo: RawUtf8; aToMethod: TUriRouterMethod = urmGet); overload; /// just a wrapper around Rewrite(urmPost, aFrom, aToMethod, aTo) // - e.g. Route.Post('/doconvert', '/root/myservice/convert'); procedure Post(const aFrom, aTo: RawUtf8; aToMethod: TUriRouterMethod = urmPost); overload; /// just a wrapper around Rewrite(urmPut, aFrom, aToMethod, aTo) // - e.g. Route.Put('/domodify', '/root/myservice/update', urmPost); procedure Put(const aFrom, aTo: RawUtf8; aToMethod: TUriRouterMethod = urmPut); overload; /// just a wrapper around Rewrite(urmDelete, aFrom, aToMethod, aTo) // - e.g. Route.Delete('/doremove', '/root/myservice/delete', urmPost); procedure Delete(const aFrom, aTo: RawUtf8; aToMethod: TUriRouterMethod = urmDelete); overload; /// just a wrapper around Rewrite(urmOptions, aFrom, aToMethod, aTo) // - e.g. Route.Options('/doremove', '/root/myservice/Options', urmPost); procedure Options(const aFrom, aTo: RawUtf8; aToMethod: TUriRouterMethod = urmOptions); overload; /// just a wrapper around Rewrite(urmHead, aFrom, aToMethod, aTo) // - e.g. Route.Head('/doremove', '/root/myservice/Head', urmPost); procedure Head(const aFrom, aTo: RawUtf8; aToMethod: TUriRouterMethod = urmHead); overload; /// assign a TOnHttpServerRequest callback with a given URI // - <param> place holders will be parsed and available in callback // as Ctxt['param'] default property or Ctxt.RouteInt64/RouteEquals methods // - could be used e.g. for standard REST process as // $ Route.Run([urmGet], '/user/<user>/pic', DoUserPic) // retrieve a list // $ Route.Run([urmGet, urmPost, urmPut, urmDelete], // $ '/user/<user>/pic/<id>', DoUserPic) // CRUD picture access procedure Run(aFrom: TUriRouterMethods; const aFromUri: RawUtf8; const aExecute: TOnHttpServerRequest); /// just a wrapper around Run([urmGet], aUri, aExecute) registration method // - e.g. Route.Get('/plaintext', DoPlainText); procedure Get(const aUri: RawUtf8; const aExecute: TOnHttpServerRequest); overload; /// just a wrapper around Run([urmPost], aUri, aExecute) registration method procedure Post(const aUri: RawUtf8; const aExecute: TOnHttpServerRequest); overload; /// just a wrapper around Run([urmPut], aUri, aExecute) registration method procedure Put(const aUri: RawUtf8; const aExecute: TOnHttpServerRequest); overload; /// just a wrapper around Run([urmDelete], aUri, aExecute) registration method procedure Delete(const aUri: RawUtf8; const aExecute: TOnHttpServerRequest); overload; /// just a wrapper around Run([urmOptions], aUri, aExecute) registration method procedure Options(const aUri: RawUtf8; const aExecute: TOnHttpServerRequest); overload; /// just a wrapper around Run([urmHead], aUri, aExecute) registration method procedure Head(const aUri: RawUtf8; const aExecute: TOnHttpServerRequest); overload; /// assign the published methods of a class instance to their URI via RTTI // - the signature of each method should match TOnHttpServerRequest // - the method name is used for the URI, e.g. Instance.user as '/user', // with exact case matching, and replacing _ in the method name by '-', e.g. // Instance.cached_query as '/cached-query' procedure RunMethods(RouterMethods: TUriRouterMethods; Instance: TObject; const Prefix: RawUtf8 = '/'); /// perform URI parsing and rewrite/execution within HTTP server Ctxt members // - should return 0 to continue the process, on a HTTP status code to abort // if the request has been handled by a TOnHttpServerRequest callback function Process(Ctxt: THttpServerRequestAbstract): integer; /// erase all previous registrations, optionally for a given HTTP method // - currently, there is no way to delete a route once registered, to // optimize the process thread-safety: use Clear then re-register procedure Clear(aMethods: TUriRouterMethods = [urmGet .. high(TUriRouterMethod)]); /// access to the internal per-method TUriTree instance // - some Tree[] may be nil if the HTTP method has not been registered yet property Tree: TUriRouterTree read fTree; /// how the TUriRouter instance should be created // - should be set before calling Run/Rewrite registration methods property TreeOptions: TRadixTreeOptions read fTreeOptions write fTreeOptions; published /// how many GET rules have been registered property Gets: integer read fEntries[urmGet]; /// how many POST rules have been registered property Posts: integer read fEntries[urmPost]; /// how many PUT rules have been registered property Puts: integer read fEntries[urmPut]; /// how many DELETE rules have been registered property Deletes: integer read fEntries[urmDelete]; /// how many HEAD rules have been registered property Heads: integer read fEntries[urmHead]; /// how many OPTIONS rules have been registered property Optionss: integer read fEntries[urmOptions]; end;
本文来自博客园,作者:{咏南中间件},转载请注明原文链接:https://www.cnblogs.com/hnxxcxg/p/17135268.html