ASP Classic blog framework - BrainOrdure
您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

196 行
6.2KB

  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. NormalizePath = cleaned
  140. End Function
  141. '------------------------------------------------------------
  142. ' INTERNAL IsDynamicSegment(segment)
  143. ' Supports both ":id" and "{id}" route tokens.
  144. '------------------------------------------------------------
  145. Private Function IsDynamicSegment(segment)
  146. If Len(segment) = 0 Then
  147. IsDynamicSegment = False
  148. ElseIf Left(segment, 1) = ":" Then
  149. IsDynamicSegment = True
  150. ElseIf Left(segment, 1) = "{" And Right(segment, 1) = "}" Then
  151. IsDynamicSegment = True
  152. Else
  153. IsDynamicSegment = False
  154. End If
  155. End Function
  156. '------------------------------------------------------------
  157. ' Optional lifecycle hooks
  158. '------------------------------------------------------------
  159. Private Sub Class_Terminate()
  160. Set routes = Nothing
  161. End Sub
  162. ]]>
  163. </script>
  164. </component>

Powered by TurnKey Linux.