Skip to content

Commit af7f9ad

Browse files
committed
[BREAKING] serveResources middleware: Expect *.properties files in UTF-8 by default
Also fix some tests that expected different unicode escape sequences for the same input. The used input encoding did not match the specified propertiesFileSourceEncoding. BREAKING CHANGE: If the project a "*.properties" resource originates from cannot be determined, or if the project does not define a propertiesFileSourceEncoding configuration or uses a legacy specVersion (<2.0), the serveResources middleware assumes that the resource is UTF-8 encoded instead of ISO-8859-1.
1 parent 80b2385 commit af7f9ad

File tree

2 files changed

+94
-8
lines changed

2 files changed

+94
-8
lines changed

lib/middleware/serveResources.js

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,9 +41,19 @@ function createMiddleware({resources, middlewareUtil}) {
4141
// Special handling for *.properties files escape non ascii characters.
4242
const nonAsciiEscaper = require("@ui5/builder").processors.nonAsciiEscaper;
4343
const project = resource._project; // _project might not be defined
44-
const propertiesFileSourceEncoding = project && project.resources &&
44+
let propertiesFileSourceEncoding = project && project.resources &&
4545
project.resources.configuration && project.resources.configuration.propertiesFileSourceEncoding;
46-
const encoding = nonAsciiEscaper.getEncodingFromAlias(propertiesFileSourceEncoding || "ISO-8859-1");
46+
47+
if (!propertiesFileSourceEncoding) {
48+
if (project && ["0.1", "1.0", "1.1"].includes(project.specVersion)) {
49+
// default encoding to "ISO-8859-1" for old specVersions
50+
propertiesFileSourceEncoding = "ISO-8859-1";
51+
} else {
52+
// default encoding to "UTF-8" for all projects starting with specVersion 2.0
53+
propertiesFileSourceEncoding = "UTF-8";
54+
}
55+
}
56+
const encoding = nonAsciiEscaper.getEncodingFromAlias(propertiesFileSourceEncoding);
4757
await nonAsciiEscaper({
4858
resources: [resource], options: {
4959
encoding

test/lib/server/middleware/serveResources.js

Lines changed: 82 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ const {Readable, Writable} = require("stream");
44
const resourceFactory = require("@ui5/fs").resourceFactory;
55
const serveResourcesMiddleware = require("../../../../lib/middleware/serveResources");
66
const MiddlewareUtil = require("../../../../lib/middleware/MiddlewareUtil");
7-
const writeResource = function(writer, path, size, stringContent, project) {
7+
const writeResource = function(writer, path, size, stringContent, stringEncoding, project) {
88
const statInfo = {
99
ino: 0,
1010
ctime: new Date(),
@@ -16,7 +16,7 @@ const writeResource = function(writer, path, size, stringContent, project) {
1616
};
1717
const resource = resourceFactory.createResource({
1818
path,
19-
buffer: Buffer.from(stringContent, "latin1"),
19+
buffer: Buffer.from(stringContent, stringEncoding),
2020
statInfo,
2121
project
2222
});
@@ -51,7 +51,7 @@ test.serial("Check if properties file is served properly", (t) => {
5151
}
5252
};
5353

54-
return writeResource(readerWriter, "/myFile3.properties", 1024 * 1024, "key=titel\nfame=straße", project)
54+
return writeResource(readerWriter, "/myFile3.properties", 1024 * 1024, "key=titel\nfame=straße", "latin1", project)
5555
.then((resource) => {
5656
const setStringSpy = sinon.spy(resource, "setString");
5757
const middleware = serveResourcesMiddleware({
@@ -95,7 +95,7 @@ test.serial("Check if properties file is served properly with UTF-8", (t) => {
9595
}
9696
};
9797

98-
return writeResource(readerWriter, "/myFile3.properties", 1024 * 1024, "key=titel\nfame=straße", project)
98+
return writeResource(readerWriter, "/myFile3.properties", 1024 * 1024, "key=titel\nfame=straße", "utf8", project)
9999
.then((resource) => {
100100
const setStringSpy = sinon.spy(resource, "setString");
101101
const middleware = serveResourcesMiddleware({
@@ -119,7 +119,7 @@ test.serial("Check if properties file is served properly with UTF-8", (t) => {
119119
return resource.getString();
120120
}).then((content) => {
121121
t.is(content, `key=titel
122-
fame=stra\\ufffde`);
122+
fame=stra\\u00dfe`);
123123
t.is(setHeaderSpy.callCount, 2);
124124
t.is(setStringSpy.callCount, 1);
125125
t.is(setHeaderSpy.getCall(0).lastArg, "application/octet-stream");
@@ -132,7 +132,83 @@ test.serial("Check if properties file is served properly without property settin
132132

133133
const readerWriter = resourceFactory.createAdapter({virBasePath: "/"});
134134

135-
return writeResource(readerWriter, "/myFile3.properties", 1024 * 1024, "key=titel\nfame=straße").then((resource) => {
135+
return writeResource(readerWriter, "/myFile3.properties", 1024 * 1024, "key=titel\nfame=straße", "utf8").then((resource) => {
136+
const setStringSpy = sinon.spy(resource, "setString");
137+
const middleware = serveResourcesMiddleware({
138+
middlewareUtil: new MiddlewareUtil(),
139+
resources: {
140+
all: readerWriter
141+
}
142+
});
143+
144+
const response = fakeResponse;
145+
146+
const setHeaderSpy = sinon.spy(response, "setHeader");
147+
const req = {
148+
url: "/myFile3.properties",
149+
headers: {}
150+
};
151+
const next = function(err) {
152+
throw new Error(`Next callback called with error: ${err.stack}`);
153+
};
154+
return middleware(req, response, next).then((o) => {
155+
return resource.getString();
156+
}).then((content) => {
157+
t.is(content, `key=titel
158+
fame=stra\\u00dfe`);
159+
t.is(setHeaderSpy.callCount, 2);
160+
t.is(setStringSpy.callCount, 1);
161+
t.is(setHeaderSpy.getCall(0).lastArg, "application/octet-stream");
162+
});
163+
});
164+
});
165+
166+
test.serial("Check if properties file is served properly without property setting but legacy spec version", (t) => {
167+
t.plan(4);
168+
169+
const readerWriter = resourceFactory.createAdapter({virBasePath: "/"});
170+
const project = {
171+
specVersion: "1.1"
172+
};
173+
return writeResource(readerWriter, "/myFile3.properties", 1024 * 1024, "key=titel\nfame=straße", "latin1", project).then((resource) => {
174+
const setStringSpy = sinon.spy(resource, "setString");
175+
const middleware = serveResourcesMiddleware({
176+
middlewareUtil: new MiddlewareUtil(),
177+
resources: {
178+
all: readerWriter
179+
}
180+
});
181+
182+
const response = fakeResponse;
183+
184+
const setHeaderSpy = sinon.spy(response, "setHeader");
185+
const req = {
186+
url: "/myFile3.properties",
187+
headers: {}
188+
};
189+
const next = function(err) {
190+
throw new Error(`Next callback called with error: ${err.stack}`);
191+
};
192+
return middleware(req, response, next).then((o) => {
193+
return resource.getString();
194+
}).then((content) => {
195+
t.is(content, `key=titel
196+
fame=stra\\u00dfe`);
197+
t.is(setHeaderSpy.callCount, 2);
198+
t.is(setStringSpy.callCount, 1);
199+
t.is(setHeaderSpy.getCall(0).lastArg, "application/octet-stream");
200+
});
201+
});
202+
});
203+
204+
test.serial("Check if properties file is served properly without property setting but spec version", (t) => {
205+
t.plan(4);
206+
207+
const readerWriter = resourceFactory.createAdapter({virBasePath: "/"});
208+
const project = {
209+
specVersion: "2.0"
210+
};
211+
return writeResource(readerWriter, "/myFile3.properties", 1024 * 1024, "key=titel\nfame=straße", "utf8", project).then((resource) => {
136212
const setStringSpy = sinon.spy(resource, "setString");
137213
const middleware = serveResourcesMiddleware({
138214
middlewareUtil: new MiddlewareUtil(),

0 commit comments

Comments
 (0)