În calitate de companie care utilizează IIS pentru implementarea mai multor site-uri web și servicii, ne luptăm cumva să implementăm un serviciu web Python bazat pe FastAPI, cu toate acestea, această problemă poate să nu fie limitată la Python. Încercăm să folosim fie httpPlatformHandler
modul sau succesorul său, the AspNetCoreModuleV2
modul.
Configurația pentru httpPlattformHandler
modulul arata cam asa:
<configuration>
<system.webServer>
<handlers>
<add name="httpPlatform"
path="*"
verb="*"
modules="httpPlatformHandler"
resourceType="Unspecified"/>
</handlers>
<httpPlatform processPath=".\venv\Scripts\python.exe"
arguments="-m uvicorn test:app --port %HTTP_PLATFORM_PORT%"
stdoutLogEnabled="true"
stdoutLogFile=".\python.log"/>
</system.webServer>
</configuration>
Configurația pentru AspNetCoreModuleV2
modulul este foarte asemănător deoarece pare să funcționeze cam la fel:
<configuration>
<system.webServer>
<handlers>
<add name="aspNetCore"
path="*"
verb="*"
modules="AspNetCoreModuleV2"
resourceType="Unspecified"/>
</handlers>
<aspNetCore processPath=".\venv\Scripts\python.exe"
arguments="-m uvicorn test:app --port %ASPNETCORE_PORT%"
stdoutLogEnabled="true"
stdoutLogFile=".\python.log"/>
</system.webServer>
</configuration>
Ambele module funcționează bine și trimit cererile către ASGI Server uvicorn, atâta timp cât serviciul web rulează direct sub calea rădăcină /
(la nivel de site). Cu toate acestea, acum dorim să implementăm unul dintre serviciile web pe o anumită cale, de ex. /api
(la nivel de aplicație). Aici începe problema reală, deoarece aplicația FastAPI nu cunoaște calea /api
, așa că răspunde la toate solicitările ca și cum ar fi /api
o parte a căii aparține cererii efective.
Documentația FastAPI conține un capitol despre rulare în spatele unui proxy:
A avea un proxy cu un prefix de cale eliminată, în acest caz, înseamnă că ai putea declara o cale la /app
în codul dvs., dar apoi adăugați un strat deasupra (proxy-ul) care ar pune aplicația dvs. FastAPI sub o cale ca /api/v1
.
În acest caz, calea originală /app
ar fi de fapt servit la /api/v1/app
.
Chiar dacă tot codul tău este scris presupunând că există doar /app
.
Și proxy-ul ar fi „decapat” din mers prefixul căii înainte de a transmite solicitarea către Uvicorn, păstrați-vă aplicația convinsă că deservește la /app
, astfel încât să nu fie nevoie să vă actualizați tot codul pentru a include prefixul /api/v1
.
Întrebarea este acum cum să configurați IIS pentru a aplica această eliminare a căii înainte de a direcționa cererea către httpPlatformHandler
sau AspNetCoreModuleV2
modul.
Am încercat să folosim Rescrie URL modul ca în exemplul de mai jos, dar rescrierea pare să aibă loc înainte de rutarea către aplicație, ceea ce face ca cererile să nu mai fie direcționate către aplicația FastAPI:
<rewrite>
<rules>
<rule name="Proxy" stopProcessing="true">
<match url="^api/(.*)" />
<action type="Rewrite" url="/{R:1}" />
</rule>
</rewrite>
</rules>
Ne-am uitat la Rutarea cererii de aplicație modul, de asemenea, dar pare a fi o exagerare masivă pentru un caz de utilizare atât de simplu.
Ca o notă secundară, recent am folosit și FastCgiModule
în combinație cu Microsoft wfastcgi
bibliotecă pentru Python, chiar dacă ar fi trebuit să convertim mai întâi aplicația ASGI într-o aplicație WSGI (cu ajutorul a2wsgi
). The FastCgiModule
a eliminat cu succes calea după configurarea proprietăților cale
si oarecum schițat permitPathInfo
:
<configuration>
<system.webServer>
<handlers>
<add name="FastCGI"
path="api/"
allowPathInfo="true"
verb="*"
modules="FastCgiModule"
scriptProcessor="<path-created-by-wfastcgi>"
resourceType="Unspecified"
requireAccess="Script" />
</handlers>
</system.webServer>
<appSettings>
<add key="WSGI_HANDLER" value="my_api.wsgi_app" />
</appSettings>
</configuration>
Din păcate, nu putem continua să folosim această abordare, mai ales din cauza conversiei de la ASGI la WSGI.