Ви не можете вибрати більше 25 тем Теми мають розпочинатися з літери або цифри, можуть містити дефіси (-) і не повинні перевищувати 35 символів.

135 рядки
5.8KB

  1. <%
  2. '=======================================================================================================================
  3. ' Jurisdiction Number Validation + Lookup
  4. '=======================================================================================================================
  5. ' Validates a submitted jurisdiction number against the JCode field of the jurisdictions
  6. ' list served by JurisdictionApiUrl (see public/web.config), and looks up the matching
  7. ' municipality Name (used to pre-fill the order form's Municipality field). That list is
  8. ' essentially static reference data (townships/municipalities), so it's cached in
  9. ' Application scope for JurisdictionCacheMinutes (default 60) instead of being fetched on
  10. ' every /request-order submission. If a refresh attempt fails, stale cached data is used
  11. ' rather than blocking order requests; only when there is no cached data at all (e.g.
  12. ' immediately after an app pool restart, with the API also unreachable) does validation
  13. ' fail open (allow) rather than block every order request site-wide.
  14. '
  15. ' The cache is stored as a single delimited STRING ("|code1<TAB>name1|code2<TAB>name2|...|"),
  16. ' not a Scripting.Dictionary or array of objects - Scripting.Dictionary is an
  17. ' apartment-threaded COM object, and IIS raises "ASP 0197: Disallowed object use" if you try
  18. ' to store one in the Application intrinsic (which is shared across all requests/threads). A
  19. ' plain string is just script data, so it's safe to cache this way.
  20. '=======================================================================================================================
  21. Function IsValidJurisdictionNumber(jurisdictionNumber)
  22. Dim codesText
  23. codesText = GetJurisdictionCodesText()
  24. jurisdictionNumber = Trim(jurisdictionNumber)
  25. If Len(codesText) = 0 Then
  26. ' No jurisdiction list available at all (first request after startup, API also
  27. ' down) - fail open rather than block every order request site-wide.
  28. IsValidJurisdictionNumber = True
  29. Else
  30. IsValidJurisdictionNumber = (InStr(codesText, "|" & jurisdictionNumber & Chr(9)) > 0)
  31. End If
  32. End Function
  33. ' Returns the municipality Name matching a jurisdiction number, or "" if the cache is empty
  34. ' or has no matching entry (callers should treat "" as "couldn't look this up" and fall back
  35. ' to letting the user enter it manually, not as a hard error).
  36. Function GetJurisdictionName(jurisdictionNumber)
  37. Dim codesText, marker, startPos, nameStart, endPos
  38. GetJurisdictionName = ""
  39. codesText = GetJurisdictionCodesText()
  40. If Len(codesText) = 0 Then Exit Function
  41. jurisdictionNumber = Trim(jurisdictionNumber)
  42. marker = "|" & jurisdictionNumber & Chr(9)
  43. startPos = InStr(codesText, marker)
  44. If startPos = 0 Then Exit Function
  45. nameStart = startPos + Len(marker)
  46. endPos = InStr(nameStart, codesText, "|")
  47. If endPos = 0 Then Exit Function
  48. GetJurisdictionName = Mid(codesText, nameStart, endPos - nameStart)
  49. End Function
  50. ' Returns the cached "|code1<TAB>name1|code2<TAB>name2|...|" string, refreshing it from
  51. ' JurisdictionApiUrl when missing or older than JurisdictionCacheMinutes. Falls back to the
  52. ' existing (stale) cached string if a refresh attempt fails.
  53. Private Function GetJurisdictionCodesText()
  54. Dim cacheMinutes, cachedAt, isStale
  55. cacheMinutes = GetAppSetting("JurisdictionCacheMinutes")
  56. If Not IsNumeric(cacheMinutes) Then cacheMinutes = 60
  57. cachedAt = Application("JurisdictionCodesFetchedAt")
  58. isStale = IsEmpty(cachedAt)
  59. If Not isStale Then isStale = (DateDiff("n", cachedAt, Now()) >= CInt(cacheMinutes))
  60. If isStale Then
  61. Dim fresh
  62. fresh = FetchJurisdictionCodesText()
  63. If Len(fresh) > 0 Then
  64. Application.Lock
  65. Application("JurisdictionCodesText") = fresh
  66. Application("JurisdictionCodesFetchedAt") = Now()
  67. Application.Unlock
  68. End If
  69. End If
  70. GetJurisdictionCodesText = Application("JurisdictionCodesText")
  71. End Function
  72. ' Fetches the jurisdictions list and extracts each JCode/Name pair. Returns a
  73. ' "|code1<TAB>name1|code2<TAB>name2|...|" string, or "" on any failure (network, HTTP
  74. ' status, or no matches).
  75. '
  76. ' Uses a targeted regex over the raw response text rather than this codebase's generic
  77. ' aspJSON parser (core/lib.json.asp) - that parser walks the input character-by-character in
  78. ' plain VBScript, which measured at over 40 seconds for this API's ~450KB/1500-record
  79. ' response. RegExp.Execute is implemented natively and handles the same payload
  80. ' near-instantly. The regex assumes JCode is immediately followed by Name in the source
  81. ' JSON (verified true for all 1525 current records) - if the API ever reorders those fields
  82. ' this will need revisiting, but a full generic parse still isn't necessary since only these
  83. ' two fields are used.
  84. Private Function FetchJurisdictionCodesText()
  85. Dim apiUrl : apiUrl = GetAppSetting("JurisdictionApiUrl")
  86. Dim result : result = ""
  87. On Error Resume Next
  88. Dim http : Set http = Server.CreateObject("Msxml2.ServerXMLHTTP")
  89. http.setTimeouts 5000, 5000, 5000, 5000
  90. http.Open "GET", apiUrl, False
  91. http.Send ""
  92. If Err.Number = 0 And http.Status = 200 Then
  93. Dim re, matches, m, codes, code, name
  94. Set re = New RegExp
  95. re.Pattern = """JCode""\s*:\s*""([^""]*)""\s*,\s*""Name""\s*:\s*""([^""]*)"""
  96. re.Global = True
  97. re.IgnoreCase = True
  98. Set matches = re.Execute(http.responseText)
  99. If Err.Number = 0 And matches.Count > 0 Then
  100. codes = "|"
  101. For Each m In matches
  102. code = Trim(m.SubMatches(0))
  103. name = Trim(m.SubMatches(1))
  104. If Len(code) > 0 Then codes = codes & code & Chr(9) & name & "|"
  105. Next
  106. If Len(codes) > 1 Then result = codes
  107. End If
  108. End If
  109. Err.Clear
  110. On Error GoTo 0
  111. FetchJurisdictionCodesText = result
  112. End Function
  113. %>

Powered by TurnKey Linux.