You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

149 lines
4.9KB

  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 & ":" & LCase(Trim(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) & ":" & LCase(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. ' No route matched. The dispatcher emits a neutral 404 response so a
  90. ' clean application does not need a built-in error controller.
  91. Resolve = Array("", "", emptyParams)
  92. End Function
  93. '------------------------------------------------------------
  94. ' INTERNAL IsMatch(requestPath, routePattern, values())
  95. ' Returns True/False and fills values() with parameters
  96. '------------------------------------------------------------
  97. Private Function IsMatch(requestPath, routePattern, values)
  98. Dim reqParts, routeParts, i, paramCount
  99. reqParts = Split(requestPath, "/")
  100. routeParts = Split(routePattern, "/")
  101. If UBound(reqParts) <> UBound(routeParts) Then
  102. IsMatch = False : Exit Function
  103. End If
  104. paramCount = 0 : ReDim values(-1)
  105. For i = 0 To UBound(reqParts)
  106. If Left(routeParts(i), 1) = ":" Then
  107. ReDim Preserve values(paramCount)
  108. values(paramCount) = reqParts(i)
  109. paramCount = paramCount + 1
  110. ElseIf LCase(routeParts(i)) <> LCase(reqParts(i)) Then
  111. IsMatch = False : Exit Function
  112. End If
  113. Next
  114. If paramCount = 0 Then ReDim values(-1)
  115. IsMatch = True
  116. End Function
  117. '------------------------------------------------------------
  118. ' Optional lifecycle hooks
  119. '------------------------------------------------------------
  120. Private Sub Class_Terminate()
  121. Set routes = Nothing
  122. End Sub
  123. ]]>
  124. </script>
  125. </component>

Powered by TurnKey Linux.