| @@ -6,8 +6,8 @@ A small, WSC-first MVC framework for Classic ASP on IIS: VBScript Windows Script | |||||
| Two separate IIS sites sharing only the framework components: | Two separate IIS sites sharing only the framework components: | ||||
| - `public/` — the production site's IIS physical path. Contains only `Default.asp` and `web.config`. | |||||
| - `test-app/public/` — a second, separate site exposing `GET /self-test` (JSON test harness), so diagnostics aren't reachable on the production site/port. See `docs/ARCHITECTURE.md`. | |||||
| - `public/` — the production site's IIS physical path. `GET /` and `GET /hello` both reach the hello route. | |||||
| - `test-app/public/` — a separate site where `GET /` and `GET /self-test` return the JSON test harness, so diagnostics aren't reachable on the production site/port. See `docs/ARCHITECTURE.md`. | |||||
| - `Framework/` — shared WSC components, registered once via COM and used by both sites. | - `Framework/` — shared WSC components, registered once via COM and used by both sites. | ||||
| - `Controllers/` — production-owned controllers; `test-app/Controllers/` — test-app-owned controllers. Neither app can activate the other's routes, including through direct `Default.asp?route=...` requests. None of these source folders is served over HTTP. | - `Controllers/` — production-owned controllers; `test-app/Controllers/` — test-app-owned controllers. Neither app can activate the other's routes, including through direct `Default.asp?route=...` requests. None of these source folders is served over HTTP. | ||||
| - `logs/`, `test-app/logs/` — each site's own runtime log, written by the app, never served over HTTP. | - `logs/`, `test-app/logs/` — each site's own runtime log, written by the app, never served over HTTP. | ||||
| @@ -3,8 +3,8 @@ | |||||
| ## Request flow | ## Request flow | ||||
| ``` | ``` | ||||
| GET /hello | |||||
| -> IIS URL Rewrite rule "WscMvc-Hello" (^hello/?$) | |||||
| GET / or GET /hello | |||||
| -> IIS URL Rewrite rule "WscMvc-Root" (^$) or "WscMvc-Hello" (^hello/?$) | |||||
| -> /Default.asp?route=/hello | -> /Default.asp?route=/hello | ||||
| -> Server.CreateObject("WscMvc.RequestContext"); ctx.Initialize path, httpMethod, logDir | -> Server.CreateObject("WscMvc.RequestContext"); ctx.Initialize path, httpMethod, logDir | ||||
| -> Server.CreateObject("WscMvc.Application") | -> Server.CreateObject("WscMvc.Application") | ||||
| @@ -31,7 +31,7 @@ GET /hello | |||||
| ## Test harness: GET /self-test — its own app, only Framework/ is shared | ## Test harness: GET /self-test — its own app, only Framework/ is shared | ||||
| `test-app/Controllers/SelfTestController.wsc` (`WscMvc.SelfTestController`) exposes the same checks as `tests/Test-Components.vbs`, but callable over plain HTTP and returning JSON — no PowerShell, cscript, or SSH access to the VM required. `Application.Run` routes `path = "/self-test"` to it. | |||||
| `test-app/Controllers/SelfTestController.wsc` (`WscMvc.SelfTestController`) exposes framework checks over plain HTTP and returns JSON — no PowerShell, cscript, or SSH access to the VM required. Both the test site's root (`GET /`) and `GET /self-test` rewrite to the test app's `/self-test` route. Production similarly maps both `GET /` and `GET /hello` to `/hello`. | |||||
| **This lives on its own IIS site (`test-app/`), not the production site.** Changed 2026-09-19 at Daniel's explicit direction: a diagnostics endpoint permanently reachable on the same site/port as real traffic was the wrong shape. `test-app/public/` is a second, separate IIS site's physical path (own site name, own app pool, own port, own `logs/`), whose `web.config` routes `/self-test` and nothing else. The production site's `web.config` no longer has a `/self-test` rewrite rule at all — `GET /self-test` against the production site now returns a plain `404` (nothing rewrites that path to `Default.asp`). | **This lives on its own IIS site (`test-app/`), not the production site.** Changed 2026-09-19 at Daniel's explicit direction: a diagnostics endpoint permanently reachable on the same site/port as real traffic was the wrong shape. `test-app/public/` is a second, separate IIS site's physical path (own site name, own app pool, own port, own `logs/`), whose `web.config` routes `/self-test` and nothing else. The production site's `web.config` no longer has a `/self-test` rewrite rule at all — `GET /self-test` against the production site now returns a plain `404` (nothing rewrites that path to `Default.asp`). | ||||
| @@ -30,6 +30,10 @@ | |||||
| --> | --> | ||||
| <rewrite> | <rewrite> | ||||
| <rules> | <rules> | ||||
| <rule name="WscMvc-Root" stopProcessing="true"> | |||||
| <match url="^$" /> | |||||
| <action type="Rewrite" url="Default.asp?route=/hello" appendQueryString="false" /> | |||||
| </rule> | |||||
| <rule name="WscMvc-Hello" stopProcessing="true"> | <rule name="WscMvc-Hello" stopProcessing="true"> | ||||
| <match url="^hello/?$" /> | <match url="^hello/?$" /> | ||||
| <action type="Rewrite" url="Default.asp?route=/hello" appendQueryString="false" /> | <action type="Rewrite" url="Default.asp?route=/hello" appendQueryString="false" /> | ||||
| @@ -20,6 +20,10 @@ | |||||
| </security> | </security> | ||||
| <rewrite> | <rewrite> | ||||
| <rules> | <rules> | ||||
| <rule name="WscMvcTests-Root" stopProcessing="true"> | |||||
| <match url="^$" /> | |||||
| <action type="Rewrite" url="Default.asp?route=/self-test" appendQueryString="false" /> | |||||
| </rule> | |||||
| <rule name="WscMvcTests-SelfTest" stopProcessing="true"> | <rule name="WscMvcTests-SelfTest" stopProcessing="true"> | ||||
| <match url="^self-test/?$" /> | <match url="^self-test/?$" /> | ||||
| <action type="Rewrite" url="Default.asp?route=/self-test" appendQueryString="false" /> | <action type="Rewrite" url="Default.asp?route=/self-test" appendQueryString="false" /> | ||||
| @@ -26,6 +26,14 @@ try { | |||||
| Report $false "GET /hello request" $_.Exception.Message | Report $false "GET /hello request" $_.Exception.Message | ||||
| } | } | ||||
| try { | |||||
| $rootResp = Invoke-WebRequest -Uri "$BaseUrl/" -UseBasicParsing | |||||
| Report ($rootResp.StatusCode -eq 200) "GET / status 200" "got $($rootResp.StatusCode)" | |||||
| Report ($rootResp.Content -eq 'Hello from WSC-MVC!') "GET / maps to /hello" "got '$($rootResp.Content)'" | |||||
| } catch { | |||||
| Report $false "GET / request" $_.Exception.Message | |||||
| } | |||||
| # /self-test lives on the separate test-app/ site now (see docs/ARCHITECTURE.md | # /self-test lives on the separate test-app/ site now (see docs/ARCHITECTURE.md | ||||
| # and tests/run-self-test.sh, which is what actually exercises it) - this | # and tests/run-self-test.sh, which is what actually exercises it) - this | ||||
| # script tests the production app only. Confirm the diagnostics endpoint is | # script tests the production app only. Confirm the diagnostics endpoint is | ||||
| @@ -19,6 +19,13 @@ if [ "$ok" != "true" ]; then | |||||
| exit 1 | exit 1 | ||||
| fi | fi | ||||
| root_ok=$(curl -sf "$BASE_URL/" | python3 -c 'import json, sys; print("true" if json.load(sys.stdin)["ok"] else "false")') | |||||
| if [ "$root_ok" != "true" ]; then | |||||
| echo "FAIL: test app root did not return passing self-test JSON" >&2 | |||||
| exit 1 | |||||
| fi | |||||
| echo "PASS: test app root maps to /self-test" | |||||
| # URL Rewrite is not the only entry path: Default.asp is directly addressable. | # URL Rewrite is not the only entry path: Default.asp is directly addressable. | ||||
| # Prove this test app still cannot activate a production route through its | # Prove this test app still cannot activate a production route through its | ||||
| # internal route query string. | # internal route query string. | ||||
Powered by TurnKey Linux.