Skip to content

Commit 5639f5b

Browse files
Hardaker587pi0
andauthored
fix(iis): merge web.config (#1658)
Co-authored-by: Pooya Parsa <[email protected]>
1 parent 86d05f2 commit 5639f5b

File tree

7 files changed

+198
-76
lines changed

7 files changed

+198
-76
lines changed

docs/content/2.deploy/providers/iis.md

+34-3
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,7 @@ This is an experimental preset.
1212

1313
1. Install [IISnode](https://github.com/azure/iisnode/releases), and the [IIS URL Rewrite Module](https://www.iis.net/downloads/microsoft/url-rewrite).
1414
2. In IIS, add `.mjs` as a new mime type and set its content type to `application/javascript`.
15-
3. Deploy the contents of your `.output` folder to your website in IIS.
16-
15+
3. Deploy the contents of your `.output` folder to your website in IIS.
1716

1817
## Using IIS directly
1918

@@ -23,4 +22,36 @@ If you do not wish to use IISnode, you can use IIS directly.
2322

2423
1. Make sure that [Node.js](https://nodejs.org/en/) is installed on your Windows Server.
2524
2. Make sure [`HttpPlatformHandler` Module](https://www.iis.net/downloads/microsoft/httpplatformhandler) is installed.
26-
3. Copy your `.output` directory into the Windows Server, and create a website on IIS pointing to that exact directory.
25+
3. Copy your `.output` directory into the Windows Server, and create a website on IIS pointing to that exact directory.
26+
27+
## IIS Config options
28+
29+
::code-group
30+
31+
```ts [nitro.config.ts]
32+
export default defineNitroConfig({
33+
// IIS options default
34+
iis: {
35+
// merges in a pre-exisiting web.config file to the nitro default file
36+
mergeConfig: true,
37+
// overrides the default nitro web.config file all together
38+
overrideConfig: false,
39+
},
40+
});
41+
```
42+
43+
```ts [nuxt.config.ts]
44+
export default defineNuxtConfig({
45+
nitro: {
46+
// IIS options default
47+
iis: {
48+
// merges in a pre-exisiting web.config file to the nitro default file
49+
mergeConfig: true,
50+
// overrides the default nitro web.config file all together
51+
overrideConfig: false,
52+
},
53+
},
54+
});
55+
```
56+
57+
::

package.json

+11-2
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,16 @@
147147
"typescript": "^5.2.2",
148148
"unbuild": "^2.0.0",
149149
"undici": "^5.23.0",
150-
"vitest": "^0.34.3"
150+
"vitest": "^0.34.3",
151+
"xml2js": "^0.6.2"
152+
},
153+
"peerDependencies": {
154+
"xml2js": "^0.6.2"
155+
},
156+
"peerDependenciesMeta": {
157+
"xml2js": {
158+
"optional": true
159+
}
151160
},
152161
"packageManager": "[email protected]",
153162
"engines": {
@@ -163,4 +172,4 @@
163172
]
164173
}
165174
}
166-
}
175+
}

pnpm-lock.yaml

+25
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/presets/iis-node.ts

-65
This file was deleted.

src/presets/iis.ts

+121-4
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
1+
import { readFile } from "node:fs/promises";
12
import { resolve } from "pathe";
2-
import { writeFile } from "../utils";
3+
import { resolveFile, writeFile } from "../utils";
34
import { defineNitroPreset } from "../preset";
45
import type { Nitro } from "../types";
56

@@ -9,14 +10,91 @@ export const iis = defineNitroPreset({
910
async compiled(nitro: Nitro) {
1011
await writeFile(
1112
resolve(nitro.options.output.dir, "web.config"),
12-
iisXmlTemplate()
13+
await iisXmlTemplate(nitro)
1314
);
1415
},
1516
},
1617
});
1718

18-
function iisXmlTemplate() {
19-
return `<?xml version="1.0" encoding="UTF-8"?>
19+
export const iisNode = defineNitroPreset({
20+
extends: "node-server",
21+
hooks: {
22+
async compiled(nitro: Nitro) {
23+
await writeFile(
24+
resolve(nitro.options.output.dir, "web.config"),
25+
await iisnodeXmlTemplate(nitro)
26+
);
27+
28+
await writeFile(
29+
resolve(nitro.options.output.dir, "index.js"),
30+
"import('./server/index.mjs');"
31+
);
32+
},
33+
},
34+
});
35+
36+
async function iisnodeXmlTemplate(nitro: Nitro) {
37+
const path = resolveFile("web.config", nitro.options.rootDir, ["config"]);
38+
const originalString = `<?xml version="1.0" encoding="utf-8"?>
39+
<configuration>
40+
<system.webServer>
41+
<webSocket enabled="false" />
42+
<handlers>
43+
<add name="iisnode" path="index.js" verb="*" modules="iisnode"/>
44+
</handlers>
45+
<rewrite>
46+
<rules>
47+
<rule name="NodeInspector" patternSyntax="ECMAScript" stopProcessing="true">
48+
<match url="^server\\/debug[\\/]?" />
49+
</rule>
50+
51+
<rule name="StaticContent">
52+
<action type="Rewrite" url="public{REQUEST_URI}"/>
53+
</rule>
54+
55+
<rule name="DynamicContent">
56+
<conditions>
57+
<add input="{REQUEST_FILENAME}" matchType="IsFile" negate="True"/>
58+
</conditions>
59+
<action type="Rewrite" url="index.js"/>
60+
</rule>
61+
</rules>
62+
</rewrite>
63+
64+
<security>
65+
<requestFiltering>
66+
<hiddenSegments>
67+
<remove segment="bin"/>
68+
<add segment="node_modules"/>
69+
</hiddenSegments>
70+
</requestFiltering>
71+
</security>
72+
73+
<httpErrors existingResponse="PassThrough" />
74+
75+
<iisnode watchedFiles="web.config;*.js" node_env="production" debuggingEnabled="true" />
76+
</system.webServer>
77+
</configuration>
78+
`;
79+
if (path !== undefined) {
80+
const fileString = await readFile(path, "utf8");
81+
const originalWebConfig: Record<string, unknown> =
82+
await parseXmlDoc(originalString);
83+
const fileWebConfig: Record<string, unknown> =
84+
await parseXmlDoc(fileString);
85+
86+
if (nitro.options.iis.mergeConfig && !nitro.options.iis.overrideConfig) {
87+
return buildNewXmlDoc({ ...originalWebConfig, ...fileWebConfig });
88+
} else if (nitro.options.iis.overrideConfig) {
89+
return buildNewXmlDoc({ ...fileWebConfig });
90+
}
91+
}
92+
return originalString;
93+
}
94+
95+
async function iisXmlTemplate(nitro: Nitro) {
96+
const path = resolveFile("web.config", nitro.options.rootDir, ["config"]);
97+
const originalString = `<?xml version="1.0" encoding="UTF-8"?>
2098
<configuration>
2199
<system.webServer>
22100
<handlers>
@@ -31,4 +109,43 @@ function iisXmlTemplate() {
31109
</system.webServer>
32110
</configuration>
33111
`;
112+
if (path !== undefined) {
113+
const fileString = await readFile(path, "utf8");
114+
const originalWebConfig: Record<string, unknown> =
115+
await parseXmlDoc(originalString);
116+
const fileWebConfig: Record<string, unknown> =
117+
await parseXmlDoc(fileString);
118+
119+
if (nitro.options.iis.mergeConfig && !nitro.options.iis.overrideConfig) {
120+
return buildNewXmlDoc({ ...originalWebConfig, ...fileWebConfig });
121+
} else if (nitro.options.iis.overrideConfig) {
122+
return buildNewXmlDoc({ ...fileWebConfig });
123+
}
124+
}
125+
return originalString;
126+
}
127+
128+
// XML Helpers
129+
export async function parseXmlDoc(
130+
xml: string
131+
): Promise<Record<string, unknown>> {
132+
const { Parser } = await import("xml2js");
133+
134+
if (xml === undefined || !xml) {
135+
return {};
136+
}
137+
const parser = new Parser();
138+
let parsedRecord: Record<string, unknown>;
139+
parser.parseString(xml, function (_, r) {
140+
parsedRecord = r;
141+
});
142+
return parsedRecord;
143+
}
144+
145+
export async function buildNewXmlDoc(
146+
xmlObj: Record<string, unknown>
147+
): Promise<string> {
148+
const { Builder } = await import("xml2js");
149+
const builder = new Builder();
150+
return builder.buildObject({ ...xmlObj });
34151
}

src/presets/index.ts

+1-2
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,6 @@ export * from "./cleavr";
2626
export * from "./layer0";
2727
export * from "./flightcontrol";
2828
export * from "./lagon";
29-
export * from "./iis-node";
30-
export * from "./iis";
29+
export { iis, iisNode } from "./iis";
3130
export { _static as static } from "./static";
3231
export * from "./github-pages";

src/types/nitro.ts

+6
Original file line numberDiff line numberDiff line change
@@ -330,6 +330,12 @@ export interface NitroOptions extends PresetOptions {
330330
preview: string;
331331
deploy: string;
332332
};
333+
334+
// IIS
335+
iis?: {
336+
mergeConfig?: boolean;
337+
overrideConfig?: boolean;
338+
};
333339
}
334340

335341
declare global {

0 commit comments

Comments
 (0)