ASP Classic blog framework - BrainOrdure
Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

209 lignes
6.5KB

  1. <?xml version="1.0"?>
  2. <!-- RouterComponent.wsc -->
  3. <component>
  4. <!-- COM registration -->
  5. <registration
  6. description = "Classic ASP Router Component"
  7. progid = "App.Router"
  8. version = "1.0"
  9. classid = "{A1FC6EA8-519E-4E34-AC08-77788E3E5E44}" />
  10. <!-- Public interface -->
  11. <public>
  12. <method name="AddRoute"/>
  13. <method name="Resolve"/>
  14. </public>
  15. <!-- Give the component ASP intrinsic objects (Request, Response, Server …) -->
  16. <implements type="ASP"/>
  17. <!-- Implementation -->
  18. <script language="VBScript">
  19. <![CDATA[
  20. Option Explicit
  21. '------------------------------------------------------------
  22. ' Private state
  23. '------------------------------------------------------------
  24. Dim routes : Set routes = CreateObject("Scripting.Dictionary")
  25. '------------------------------------------------------------
  26. ' METHOD AddRoute(method, path, controller, action)
  27. '------------------------------------------------------------
  28. Public Sub AddRoute(method, path, controller, action)
  29. ' Input validation
  30. If IsEmpty(method) Or Len(Trim(method)) = 0 Then
  31. Err.Raise 5, "Router.AddRoute", "HTTP method parameter is required and cannot be empty"
  32. End If
  33. If IsEmpty(path) Then
  34. Err.Raise 5, "Router.AddRoute", "Path parameter is required"
  35. End If
  36. If IsEmpty(controller) Or Len(Trim(controller)) = 0 Then
  37. Err.Raise 5, "Router.AddRoute", "Controller parameter is required and cannot be empty"
  38. End If
  39. If IsEmpty(action) Or Len(Trim(action)) = 0 Then
  40. Err.Raise 5, "Router.AddRoute", "Action parameter is required and cannot be empty"
  41. End If
  42. ' Validate HTTP method (allow common methods)
  43. Dim validMethods, methodUpper, i, isValidMethod
  44. validMethods = Array("GET", "POST", "PUT", "DELETE", "PATCH", "HEAD", "OPTIONS")
  45. methodUpper = UCase(Trim(method))
  46. isValidMethod = False
  47. For i = 0 To UBound(validMethods)
  48. If validMethods(i) = methodUpper Then
  49. isValidMethod = True
  50. Exit For
  51. End If
  52. Next
  53. If Not isValidMethod Then
  54. Err.Raise 5, "Router.AddRoute", "Invalid HTTP method: " & method & ". Allowed: GET, POST, PUT, DELETE, PATCH, HEAD, OPTIONS"
  55. End If
  56. Dim routeKey
  57. routeKey = methodUpper & ":" & NormalizePath(path)
  58. If Not routes.Exists(routeKey) Then
  59. routes.Add routeKey, Array(Trim(controller), Trim(action))
  60. End If
  61. End Sub
  62. '------------------------------------------------------------
  63. ' METHOD Resolve(method, path) -> Array(controller, action, params())
  64. '------------------------------------------------------------
  65. Public Function Resolve(method, path)
  66. Dim routeKey, routeValue, values
  67. routeKey = UCase(method) & ":" & NormalizePath(path)
  68. ' Always return a params array (empty by default)
  69. Dim emptyParams() : ReDim emptyParams(-1)
  70. ' Exact match first
  71. If routes.Exists(routeKey) Then
  72. routeValue = routes(routeKey)
  73. Resolve = Array(routeValue(0), routeValue(1), emptyParams)
  74. Exit Function
  75. End If
  76. ' Dynamic routes (e.g. /users/:id)
  77. Dim r, routeMethod, routePattern
  78. For Each r In routes.Keys
  79. routeMethod = Split(r, ":")(0)
  80. routePattern = Mid(r, Len(routeMethod) + 2) ' strip "METHOD:"
  81. If UCase(routeMethod) = UCase(method) Then
  82. If IsMatch(path, routePattern, values) Then
  83. routeValue = routes(r)
  84. Resolve = Array(routeValue(0), routeValue(1), values)
  85. Exit Function
  86. End If
  87. End If
  88. Next
  89. ' 404 fallback
  90. Resolve = Array("ErrorController", "NotFound", emptyParams)
  91. End Function
  92. '------------------------------------------------------------
  93. ' INTERNAL IsMatch(requestPath, routePattern, values())
  94. ' Returns True/False and fills values() with parameters
  95. '------------------------------------------------------------
  96. Private Function IsMatch(requestPath, routePattern, values)
  97. Dim reqParts, routeParts, i, paramCount
  98. requestPath = NormalizePath(requestPath)
  99. routePattern = NormalizePath(routePattern)
  100. reqParts = Split(requestPath, "/")
  101. routeParts = Split(routePattern, "/")
  102. If UBound(reqParts) <> UBound(routeParts) Then
  103. IsMatch = False : Exit Function
  104. End If
  105. paramCount = 0 : ReDim values(-1)
  106. For i = 0 To UBound(reqParts)
  107. If IsDynamicSegment(routeParts(i)) Then
  108. ReDim Preserve values(paramCount)
  109. values(paramCount) = reqParts(i)
  110. paramCount = paramCount + 1
  111. ElseIf LCase(routeParts(i)) <> LCase(reqParts(i)) Then
  112. IsMatch = False : Exit Function
  113. End If
  114. Next
  115. If paramCount = 0 Then ReDim values(-1)
  116. IsMatch = True
  117. End Function
  118. '------------------------------------------------------------
  119. ' INTERNAL NormalizePath(path)
  120. ' Removes query strings, trims whitespace, and normalizes
  121. ' leading/trailing slashes so "/admin" and "/admin/" match.
  122. '------------------------------------------------------------
  123. Private Function NormalizePath(path)
  124. Dim cleaned
  125. cleaned = LCase(Trim(CStr(path)))
  126. If Len(cleaned) = 0 Then
  127. NormalizePath = ""
  128. Exit Function
  129. End If
  130. If InStr(cleaned, "?") > 0 Then
  131. cleaned = Left(cleaned, InStr(cleaned, "?") - 1)
  132. End If
  133. Do While Left(cleaned, 1) = "/"
  134. cleaned = Mid(cleaned, 2)
  135. Loop
  136. Do While Right(cleaned, 1) = "/" And Len(cleaned) > 0
  137. cleaned = Left(cleaned, Len(cleaned) - 1)
  138. Loop
  139. On Error Resume Next
  140. Do
  141. Dim decoded
  142. decoded = Server.URLDecode(cleaned)
  143. If Err.Number <> 0 Then
  144. Err.Clear
  145. Exit Do
  146. End If
  147. If decoded = cleaned Then Exit Do
  148. cleaned = LCase(decoded)
  149. Loop
  150. On Error GoTo 0
  151. NormalizePath = cleaned
  152. End Function
  153. '------------------------------------------------------------
  154. ' INTERNAL IsDynamicSegment(segment)
  155. ' Supports both ":id" and "{id}" route tokens.
  156. '------------------------------------------------------------
  157. Private Function IsDynamicSegment(segment)
  158. If Len(segment) = 0 Then
  159. IsDynamicSegment = False
  160. ElseIf Left(segment, 1) = ":" Then
  161. IsDynamicSegment = True
  162. ElseIf Left(segment, 1) = "{" And Right(segment, 1) = "}" Then
  163. IsDynamicSegment = True
  164. Else
  165. IsDynamicSegment = False
  166. End If
  167. End Function
  168. '------------------------------------------------------------
  169. ' Optional lifecycle hooks
  170. '------------------------------------------------------------
  171. Private Sub Class_Terminate()
  172. Set routes = Nothing
  173. End Sub
  174. ]]>
  175. </script>
  176. </component>

Powered by TurnKey Linux.