Introduction
I'm having some trouble hosting Teams Apps in IIS, generated by your Yeoman generator for Microsoft Teams, using:
Then i did a build, with:
I am able to host the "dist" directory in IIS, after:
- installing IISNode
- installing UrlRewrite
- and adding the following web.config file to the "dist" directory:
<configuration>
<system.webServer>
<!-- indicates that the server.js file is a node.js application
to be handled by the iisnode module -->
<handlers>
<add name="iisnode" path="server.js" verb="*" modules="iisnode" />
</handlers>
<rewrite>
<rules>
<rule name="sendToNode">
<match url="/*" />
<action type="Rewrite" url="server.js" />
</rule>
</rules>
</rewrite>
</system.webServer>
</configuration>
This seems to work just fine, when hosting this directory as the root of an IIS Website (its URL "http://localhost" shows the purple teams logo in a browser).
Problem
The problem is that this does not work when hosting this directory as an Application under an existing Website (as a subdirectory). For example if this Application now has the URL "http://localhost/teams", then browsing there results in a blank page with only the text:
if i go into the generated file "server.ts", and replace the following:
express.use("/", Express.static(path.join(__dirname, "web/"), {
index: "index.html"
}));
with:
express.use("/teams", Express.static(path.join(__dirname, "web/"), {
index: "index.html"
}));
and do a build again, then the error goes away and i see the purple teams logo again. But the logo has the wrong size, because "/teams/web/index.html" still contains the old path of the css file:
<link rel="stylesheet" href="/styles/main.css">
instead of a path relative to the current folder, which would work in both cases:
<link rel="stylesheet" href="styles/main.css">
But, i have no idea of all the potential places, where the path would need to be changed.
Question
Is there a single place where i can prefix all paths (with for example "/teams")?
Suggestion
It would be most convenient if the setting could still be change, without doing a build (with "gulp ngrok-serve"). So if you implement this, then i suggest that you get this prefix ("/teams" in the above example), at runtime from the variable "process.env.virtualDirPath" if it is defined.
This way, i can use the web.config file in the "dist" directory as the single place where i can prefix all paths. by adding an appSettings to it:
<configuration>
<appSettings>
<add key="virtualDirPath" value="/teams" />
</appSettings>
<system.webServer>
<!-- indicates that the server.js file is a node.js application
to be handled by the iisnode module -->
<handlers>
<add name="iisnode" path="server.js" verb="*" modules="iisnode" />
</handlers>
<rewrite>
<rules>
<rule name="sendToNode">
<match url="/*" />
<action type="Rewrite" url="server.js" />
</rule>
</rules>
</rewrite>
</system.webServer>
</configuration>
IISNode then automatically defines process.env.virtualDirPath with value "/teams" (i've tested this). You could for example implement:
const virtualDirPath = process.env.virtualDirPath || "/";
express.use(virtualDirPath, Express.static(path.join(__dirname, "web/"), {
index: "index.html"
}));
This would also make it practical for an administrator to change the subdirectory in the URL, by only being required to also edit the web.config file, instead of needing all the developer tools and having to do a build.
Background
Hosting several applications, each in their own subdirectory, under the same IIS Website is a common scenario. In my case the Teams App needs to POST JSON content to a third party application under the same website.
If they are in different websites, then one domain would be accessing another domain. This would require me to set CORS (Cross Origin Resource Sharing) permissions. This is not possible in the third party application. And even if it was, i wouldn't want to unnecessarily expose these permissions to the internet, out of security concerns.