Skip to content

Commit 07e99d6

Browse files
committed
user agent workaround
1 parent 1559a9d commit 07e99d6

2 files changed

Lines changed: 33 additions & 1 deletion

File tree

build-logic/src/main/groovy/org.apache.groovy-tested.gradle

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,18 @@ def aggregator = TestResultAggregatorService.register(
4949
tasks.withType(Test).configureEach {
5050
def fs = objects.newInstance(TestServices).fileSystemOperations
5151
def grapeDirectory = new File(temporaryDir, '.groovy')
52-
def options = ['-ea', "-Xms${groovyJUnit_ms}", "-Xmx${groovyJUnit_mx}", '-Duser.language=en', '-Duser.country=US']
52+
// GROOVY-12005 / 2026-05: Maven Central (Fastly) returns HTTP 404 with a 1-byte
53+
// body for requests bearing the JDK URLConnection default User-Agent ("Java/<version>"),
54+
// which Ivy's BasicURLHandler relies on. We must set http.agent as a JVM argument
55+
// here rather than via systemProperty / a static initializer in GrapeIvy: by the
56+
// time GrapeIvy's class init runs (lazily on first @Grab), the test JVM has already
57+
// loaded HttpURLConnection and its agent is locked in. Passing it as `-Dhttp.agent`
58+
// on the JVM command line guarantees it's set before any class is initialized.
59+
// Tests pass with literally any non-"Java/*" value; see also the matching static
60+
// initializer in GrapeIvy for CLI / standalone-script coverage.
61+
def options = ['-ea', "-Xms${groovyJUnit_ms}", "-Xmx${groovyJUnit_mx}",
62+
'-Duser.language=en', '-Duser.country=US',
63+
'-Dhttp.agent=Apache-Ivy_Groovy-Grape']
5364
jvmArgs(*options)
5465
systemProperty 'groovy.force.illegal.access', findProperty('groovy.force.illegal.access')
5566
def testdb = System.properties['groovy.testdb.props']

subprojects/groovy-grape-ivy/src/main/groovy/groovy/grape/ivy/GrapeIvy.groovy

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,27 @@ import java.util.regex.Pattern
6666
@AutoFinal @CompileStatic
6767
class GrapeIvy implements GrapeEngine {
6868

69+
static {
70+
// GROOVY-12005 / 2026-05: Maven Central (Fastly) currently returns HTTP 404
71+
// with a 1-byte body for requests whose User-Agent is the JDK URLConnection
72+
// default "Java/<version>". Any other value (curl/x.y, Apache-Ivy/..., etc.)
73+
// gets the expected HTTP 200. Ivy 2.5.3 uses java.net.URLConnection under
74+
// the hood, which honours -Dhttp.agent. We set it here so direct grape use
75+
// (CLI `grape install`, `groovy script-with-@Grab.groovy`, embedded usage)
76+
// gets a working agent — those paths load GrapeIvy before any other class
77+
// touches the network, so this static init runs early enough.
78+
//
79+
// For test JVMs the same property MUST be set on the JVM command line —
80+
// see the matching -Dhttp.agent in build-logic/.../org.apache.groovy-tested.gradle —
81+
// because by the time GrapeIvy is class-loaded for the first @Grab in a test,
82+
// the agent has already been cached deep in the JDK's HTTP machinery.
83+
//
84+
// Respect any value the user has already configured.
85+
if (System.getProperty('http.agent') == null) {
86+
System.setProperty('http.agent', 'Apache-Ivy_Groovy-Grape')
87+
}
88+
}
89+
6990
private static final List<String> DEFAULT_CONF = Collections.singletonList('default')
7091
private static final Map<String, Set<String>> MUTUALLY_EXCLUSIVE_KEYS = processGrabArgs([
7192
['group', 'groupId', 'organisation', 'organization', 'org'],

0 commit comments

Comments
 (0)