Skip to content

Commit 323e648

Browse files
committed
WDEVOP-1 Binary File Structre changed in NPM Versions > 0.x and support for SHA-256 checksums.
1 parent 9d94b9b commit 323e648

File tree

9 files changed

+114
-122
lines changed

9 files changed

+114
-122
lines changed

changes.xml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,12 @@
2323
xsi:schemaLocation="http://maven.apache.org/changes/1.0.0 http://maven.apache.org/plugins/maven-changes-plugin/xsd/changes-1.0.0.xsd">
2424
<body>
2525

26+
<release version="1.1.0" date="not released">
27+
<action type="update" dev="sseifert" issue="WDEVOP-1">
28+
Binary File Structre changed in NPM Versions > 0.x and support for SHA-256 checksums.
29+
</action>
30+
</release>
31+
2632
<release version="1.0.0" date="2015-09-03">
2733
<action type="add" dev="sseifert">
2834
Initial release.

maven-nodejs-proxy/config.yml

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,17 @@ nodeJsBinariesRootUrl: "https://nodejs.org/dist"
1515

1616
# Url parts to download the different artifacts
1717
nodeJsBinariesUrl: "/v${version}/node-v${version}-${os}-${arch}.${type}"
18-
nodeJsBinariesUrlWindows: "/v${version}/${arch}/node.${type}"
19-
nodeJsBinariesUrlWindowsX86: "/v${version}/node.${type}"
18+
nodeJsBinariesUrlWindows: "/v${version}/win-${arch}/node.${type}"
19+
nodeJsBinariesUrlWindowsX86Legacy: "/v${version}/node.${type}"
20+
nodeJsBinariesUrlWindowsX64Legacy: "/v${version}/${arch}/node.${type}"
2021
npmBinariesUrl: "/npm/npm-${version}.${type}"
2122

22-
# SHA-1 checksums file
23-
nodeJsChecksumUrl: "/v${version}/SHASUMS.txt"
23+
# SHA-256 checksums file
24+
nodeJsChecksumUrl: "/v${version}/SHASUMS256.txt"
25+
26+
# Sample versions for index page
27+
nodeJsSampleVersion: 4.4.0
28+
npmSampleVersion: 1.4.9
2429

2530
# HTTP Client settings
2631
httpClient:

maven-nodejs-proxy/pom.xml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,13 @@
7676
<scope>compile</scope>
7777
</dependency>
7878

79+
<dependency>
80+
<groupId>org.apache.maven</groupId>
81+
<artifactId>maven-artifact</artifactId>
82+
<version>3.3.9</version>
83+
<scope>compile</scope>
84+
</dependency>
85+
7986
</dependencies>
8087

8188
<build>

maven-nodejs-proxy/src/main/java/io/wcm/devops/maven/nodejsproxy/MavenProxyConfiguration.java

Lines changed: 27 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -19,16 +19,16 @@
1919
*/
2020
package io.wcm.devops.maven.nodejsproxy;
2121

22-
import io.dropwizard.Configuration;
23-
import io.dropwizard.client.HttpClientConfiguration;
24-
2522
import javax.validation.Valid;
2623
import javax.validation.constraints.NotNull;
2724

2825
import org.hibernate.validator.constraints.NotEmpty;
2926

3027
import com.fasterxml.jackson.annotation.JsonProperty;
3128

29+
import io.dropwizard.Configuration;
30+
import io.dropwizard.client.HttpClientConfiguration;
31+
3232
/**
3333
* Configuration for Maven NodeJS Proxy.
3434
*/
@@ -47,11 +47,17 @@ public class MavenProxyConfiguration extends Configuration {
4747
@NotEmpty
4848
private String nodeJsBinariesUrlWindows;
4949
@NotEmpty
50-
private String nodeJsBinariesUrlWindowsX86;
50+
private String nodeJsBinariesUrlWindowsX86Legacy;
51+
@NotEmpty
52+
private String nodeJsBinariesUrlWindowsX64Legacy;
5153
@NotEmpty
5254
private String npmBinariesUrl;
5355
@NotEmpty
5456
private String nodeJsChecksumUrl;
57+
@NotEmpty
58+
private String nodeJsSampleVersion;
59+
@NotEmpty
60+
private String npmSampleVersion;
5561

5662
@Valid
5763
@NotNull
@@ -88,8 +94,13 @@ public String getNodeJsBinariesUrlWindows() {
8894
}
8995

9096
@JsonProperty
91-
public String getNodeJsBinariesUrlWindowsX86() {
92-
return this.nodeJsBinariesUrlWindowsX86;
97+
public String getNodeJsBinariesUrlWindowsX86Legacy() {
98+
return this.nodeJsBinariesUrlWindowsX86Legacy;
99+
}
100+
101+
@JsonProperty
102+
public String getNodeJsBinariesUrlWindowsX64Legacy() {
103+
return this.nodeJsBinariesUrlWindowsX64Legacy;
93104
}
94105

95106
@JsonProperty
@@ -102,6 +113,16 @@ public String getNodeJsChecksumUrl() {
102113
return this.nodeJsChecksumUrl;
103114
}
104115

116+
@JsonProperty
117+
public String getNodeJsSampleVersion() {
118+
return this.nodeJsSampleVersion;
119+
}
120+
121+
@JsonProperty
122+
public String getNpmSampleVersion() {
123+
return this.npmSampleVersion;
124+
}
125+
105126
@JsonProperty("httpClient")
106127
public HttpClientConfiguration getHttpClient() {
107128
return httpClient;

maven-nodejs-proxy/src/main/java/io/wcm/devops/maven/nodejsproxy/resource/Checksums.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -42,10 +42,10 @@ public class Checksums {
4242
public Checksums(String data) {
4343
String[] lines = StringUtils.split(data, "\n");
4444
for (String line : lines) {
45-
String sha1 = StringUtils.substringBefore(line, " ");
45+
String checksum = StringUtils.substringBefore(line, " ");
4646
String filename = StringUtils.substringAfter(line, " ");
47-
if (StringUtils.isNoneBlank(sha1, filename)) {
48-
checksums.put(filename, sha1);
47+
if (StringUtils.isNoneBlank(checksum, filename)) {
48+
checksums.put(filename, checksum);
4949
}
5050
}
5151
}

maven-nodejs-proxy/src/main/java/io/wcm/devops/maven/nodejsproxy/resource/IndexPageBuilder.java

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -29,15 +29,14 @@
2929
public final class IndexPageBuilder {
3030

3131
private static final String[] EXAMPLE_URLS = new String[] {
32-
"${groupIdPath}/${nodeJsArtifactId}/0.12.0/${nodeJsArtifactId}-0.12.0.pom",
33-
"${groupIdPath}/${nodeJsArtifactId}/0.12.0/${nodeJsArtifactId}-0.12.0-windows-x86.exe",
34-
"${groupIdPath}/${nodeJsArtifactId}/0.12.0/${nodeJsArtifactId}-0.12.0-windows-x64.exe",
35-
"${groupIdPath}/${nodeJsArtifactId}/0.12.0/${nodeJsArtifactId}-0.12.0-linux-x86.tar.gz",
36-
"${groupIdPath}/${nodeJsArtifactId}/0.12.0/${nodeJsArtifactId}-0.12.0-linux-x64.tar.gz",
37-
"${groupIdPath}/${nodeJsArtifactId}/0.12.0/${nodeJsArtifactId}-0.12.0-darwin-x86.tar.gz",
38-
"${groupIdPath}/${nodeJsArtifactId}/0.12.0/${nodeJsArtifactId}-0.12.0-darwin-x64.tar.gz",
39-
"${groupIdPath}/${npmArtifactId}/1.4.9/${npmArtifactId}-1.4.9.pom",
40-
"${groupIdPath}/${npmArtifactId}/1.4.9/${npmArtifactId}-1.4.9.tgz"
32+
"${groupIdPath}/${nodeJsArtifactId}/${nodeJsSampleVersion}/${nodeJsArtifactId}-${nodeJsSampleVersion}.pom",
33+
"${groupIdPath}/${nodeJsArtifactId}/${nodeJsSampleVersion}/${nodeJsArtifactId}-${nodeJsSampleVersion}-windows-x86.exe",
34+
"${groupIdPath}/${nodeJsArtifactId}/${nodeJsSampleVersion}/${nodeJsArtifactId}-${nodeJsSampleVersion}-windows-x64.exe",
35+
"${groupIdPath}/${nodeJsArtifactId}/${nodeJsSampleVersion}/${nodeJsArtifactId}-${nodeJsSampleVersion}-linux-x86.tar.gz",
36+
"${groupIdPath}/${nodeJsArtifactId}/${nodeJsSampleVersion}/${nodeJsArtifactId}-${nodeJsSampleVersion}-linux-x64.tar.gz",
37+
"${groupIdPath}/${nodeJsArtifactId}/${nodeJsSampleVersion}/${nodeJsArtifactId}-${nodeJsSampleVersion}-darwin-x64.tar.gz",
38+
"${groupIdPath}/${npmArtifactId}/${npmSampleVersion}/${npmArtifactId}-${npmSampleVersion}.pom",
39+
"${groupIdPath}/${npmArtifactId}/${npmSampleVersion}/${npmArtifactId}-${npmSampleVersion}.tgz"
4140
};
4241

4342
private IndexPageBuilder() {
@@ -54,6 +53,8 @@ public static String build(MavenProxyConfiguration config) {
5453
url = StringUtils.replace(url, "${groupIdPath}", StringUtils.replace(config.getGroupId(), ".", "/"));
5554
url = StringUtils.replace(url, "${nodeJsArtifactId}", config.getNodeJsArtifactId());
5655
url = StringUtils.replace(url, "${npmArtifactId}", config.getNpmArtifactId());
56+
url = StringUtils.replace(url, "${nodeJsSampleVersion}", config.getNodeJsSampleVersion());
57+
url = StringUtils.replace(url, "${npmSampleVersion}", config.getNpmSampleVersion());
5758
exampleUrlsMarkup.append("<li><a href=\"").append(url).append("\">").append(url).append("</a></li>");
5859

5960
}

maven-nodejs-proxy/src/main/java/io/wcm/devops/maven/nodejsproxy/resource/MavenProxyResource.java

Lines changed: 48 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@
2020
package io.wcm.devops.maven.nodejsproxy.resource;
2121

2222
import static javax.ws.rs.core.HttpHeaders.CONTENT_LENGTH;
23-
import io.wcm.devops.maven.nodejsproxy.MavenProxyConfiguration;
2423

2524
import java.io.IOException;
2625

@@ -39,11 +38,14 @@
3938
import org.apache.http.client.methods.HttpHead;
4039
import org.apache.http.impl.client.CloseableHttpClient;
4140
import org.apache.http.util.EntityUtils;
41+
import org.apache.maven.artifact.versioning.DefaultArtifactVersion;
4242
import org.slf4j.Logger;
4343
import org.slf4j.LoggerFactory;
4444

4545
import com.codahale.metrics.annotation.Timed;
4646

47+
import io.wcm.devops.maven.nodejsproxy.MavenProxyConfiguration;
48+
4749
/**
4850
* Proxies NodeJS binaries.
4951
*/
@@ -166,39 +168,8 @@ public Response getBinary(
166168
getChecksum = true;
167169
}
168170

169-
// return checksum from SHASUMS.txt
170-
if (getChecksum) {
171-
Checksums checksums = getChecksums(version);
172-
String url = buildBinaryUrl(artifactType, version, os, arch, StringUtils.removeEnd(type, ".sha1"));
173-
String checksum = checksums.get(url);
174-
if (checksum != null) {
175-
return Response.ok(checksum)
176-
.type(MediaType.TEXT_PLAIN)
177-
.build();
178-
}
179-
else {
180-
return Response.status(Response.Status.NOT_FOUND).build();
181-
}
182-
}
183-
184-
// return binary file
185-
else {
186-
String url = buildBinaryUrl(artifactType, version, os, arch, type);
187-
188-
log.info("Proxy file: {}", url);
189-
HttpGet get = new HttpGet(url);
190-
HttpResponse response = httpClient.execute(get);
191-
if (response.getStatusLine().getStatusCode() == HttpServletResponse.SC_OK) {
192-
return Response.ok(new SpoolStreamingOutput(response.getEntity()))
193-
.type(MediaType.APPLICATION_OCTET_STREAM)
194-
.header(CONTENT_LENGTH, response.containsHeader(CONTENT_LENGTH) ? response.getFirstHeader(CONTENT_LENGTH).getValue() : null)
195-
.build();
196-
}
197-
else {
198-
EntityUtils.consumeQuietly(response.getEntity());
199-
return Response.status(Response.Status.NOT_FOUND).build();
200-
}
201-
}
171+
String url = buildBinaryUrl(artifactType, version, os, arch, StringUtils.removeEnd(type, ".sha1"));
172+
return getBinaryWithChecksumValidation(url, version, getChecksum);
202173
}
203174

204175
/**
@@ -235,20 +206,48 @@ public Response getBinary(
235206
}
236207

237208
String url = buildBinaryUrl(artifactType, version, null, null, StringUtils.removeEnd(type, ".sha1"));
209+
return getBinary(url, version, getChecksum, null);
210+
}
211+
212+
private Response getBinaryWithChecksumValidation(String url, String version, boolean getChecksum) throws IOException {
213+
// get original checksum from source directory
214+
Checksums checksums = getChecksums(version);
215+
if (checksums == null) {
216+
log.info("File not found: {} - no checksum file found.", url);
217+
return Response.status(Response.Status.NOT_FOUND).build();
218+
}
219+
String checksum = checksums.get(url);
220+
if (checksum == null) {
221+
log.info("File not found: {} - no checksum found in checkum file.", url);
222+
return Response.status(Response.Status.NOT_FOUND).build();
223+
}
238224

225+
return getBinary(url, version, getChecksum, checksum);
226+
}
227+
228+
private Response getBinary(String url, String version, boolean getChecksum, String expectedChecksum) throws IOException {
239229
log.info("Proxy file: {}", url);
240230
HttpGet get = new HttpGet(url);
241231
HttpResponse response = httpClient.execute(get);
242232
if (response.getStatusLine().getStatusCode() == HttpServletResponse.SC_OK) {
233+
byte[] data = EntityUtils.toByteArray(response.getEntity());
234+
235+
// validate checksum
236+
if (expectedChecksum != null) {
237+
String remoteChecksum = DigestUtils.sha256Hex(data);
238+
if (!StringUtils.equals(expectedChecksum, remoteChecksum)) {
239+
log.warn("Reject file: {} - checksum comparison failed - expected: {}, actual: {}", url, expectedChecksum, remoteChecksum);
240+
return Response.status(Response.Status.NOT_FOUND).build();
241+
}
242+
}
243+
243244
if (getChecksum) {
244-
byte[] data = EntityUtils.toByteArray(response.getEntity());
245-
EntityUtils.consumeQuietly(response.getEntity());
246245
return Response.ok(DigestUtils.sha1Hex(data))
247246
.type(MediaType.TEXT_PLAIN)
248247
.build();
249248
}
250249
else {
251-
return Response.ok(new SpoolStreamingOutput(response.getEntity()))
250+
return Response.ok(data)
252251
.type(MediaType.APPLICATION_OCTET_STREAM)
253252
.header(CONTENT_LENGTH, response.containsHeader(CONTENT_LENGTH) ? response.getFirstHeader(CONTENT_LENGTH).getValue() : null)
254253
.build();
@@ -337,11 +336,14 @@ private String buildBinaryUrl(ArtifactType artifactType, String version, String
337336
switch (artifactType) {
338337
case NODEJS:
339338
if (StringUtils.equals(os, "windows")) {
340-
if (StringUtils.equals(arch, "x86")) {
341-
url = config.getNodeJsBinariesUrlWindowsX86();
339+
if (isVersion4Up(version)) {
340+
url = config.getNodeJsBinariesUrlWindows();
341+
}
342+
else if (StringUtils.equals(arch, "x86")) {
343+
url = config.getNodeJsBinariesUrlWindowsX86Legacy();
342344
}
343345
else {
344-
url = config.getNodeJsBinariesUrlWindows();
346+
url = config.getNodeJsBinariesUrlWindowsX64Legacy();
345347
}
346348
}
347349
else {
@@ -362,4 +364,10 @@ private String buildBinaryUrl(ArtifactType artifactType, String version, String
362364
return url;
363365
}
364366

367+
private boolean isVersion4Up(String version) {
368+
DefaultArtifactVersion givenVersion = new DefaultArtifactVersion(version);
369+
DefaultArtifactVersion minVersion = new DefaultArtifactVersion("4.0.0");
370+
return givenVersion.compareTo(minVersion) >= 0;
371+
}
372+
365373
}

maven-nodejs-proxy/src/main/java/io/wcm/devops/maven/nodejsproxy/resource/SpoolStreamingOutput.java

Lines changed: 0 additions & 57 deletions
This file was deleted.

maven-nodejs-proxy/src/test/java/io/wcm/devops/maven/nodejsproxy/resource/MavenProxyResourceTest.java

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -41,14 +41,15 @@ public class MavenProxyResourceTest {
4141

4242
// test with the following NodeJS and NPM versions
4343
private static final String[] NODEJS_VERSIONS = {
44-
"0.12.0"
44+
"0.12.0",
45+
"4.4.0",
46+
"5.9.0",
4547
};
4648
private static final String[] NODEJS_TARGETS = {
4749
"-windows-x86.exe",
4850
"-windows-x64.exe",
4951
"-linux-x86.tar.gz",
5052
"-linux-x64.tar.gz",
51-
"-darwin-x86.tar.gz",
5253
"-darwin-x64.tar.gz",
5354
};
5455
private static final String[] NPM_VERSIONS = {
@@ -130,7 +131,7 @@ private void assertSHA1(String path, Response dataResponse) {
130131
try (InputStream is = dataResponse.readEntity(InputStream.class)) {
131132
byte[] data = IOUtils.toByteArray(is);
132133
String sha1 = sha1Response.readEntity(String.class);
133-
assertEquals(sha1, DigestUtils.sha1Hex(data));
134+
assertEquals("SHA-1 " + path, sha1, DigestUtils.sha1Hex(data));
134135
}
135136
catch (IOException ex) {
136137
throw new RuntimeException("Error checking SHA-1 of " + path, ex);

0 commit comments

Comments
 (0)