We opened an issue [1] on Spring Framework repository and we were informed that it's specifically related to Spring AI project. [1] https://github.com/spring-projects/spring-framework/issues/32304
What was in the issue :
We are not able to download pom.xml files from the snapshot repository of repo.spring.io with our updated 'Sonatype Nexus Repository' due to an invalid header value for content-type returned by Artifactory.
2024-02-14 06:46:54,705+0000 WARN [xxx] UNKNOWN org.sonatype.nexus.repository.storage.StorageTxImpl - An exception occurred determining the content type of asset org/springframework/ai/spring-ai-openai-spring-boot-starter/0.8.0-SNAPSHOT/spring-ai-openai-spring-boot-starter-0.8.0-20240214.061929-153.pom in repository maven_proxy_repo.spring.io-snapshot
2024-02-14 06:46:54,708+0000 WARN [xxx] UNKNOWN org.sonatype.nexus.repository.view.handlers.ExceptionHandler - Invalid content: GET /org/springframework/ai/spring-ai-openai-spring-boot-starter/0.8.0-SNAPSHOT/spring-ai-openai-spring-boot-starter-0.8.0-20240214.061929-153.pom: org.sonatype.nexus.repository.InvalidContentException: Content type could not be determined: application/x-maven-pom xml
curl -L -v "https://repo.spring.io/artifactory/snapshot/org/springframework/ai/spring-ai-openai-spring-boot-starter/0.8.0-SNAPSHOT/spring-ai-openai-spring-boot-starter-0.8.0-20240220.195606-169.pom" > /dev/null < "content-type: application/x-maven-pom xml"
Note that there is a space in the value. According to RFC, that is not legal: https://www.w3.org/Protocols/rfc1341/4_Content-Type.html
According to Nexus Documentation, the correct value could be "content-type: application/x-maven-pom"
Since the header value does not respect the RFC, we cannot override configuration of our Nexus Repository to accept a such mime-type value
The milestone repository (https://repo.spring.io/artifactory/milestone/) send a valid header value "content-type: application/x-maven-pom+xml" according to the RFC
For more investigation, we tested a couple of artifact to see if it happens on all Spring AI artifact, or just few of them. It seems that all the pom served by AmazonS3 tends to have this content-type. As there is a follox-redirect when accessing via jfrog, the content-type is present in the URL as a query param, so the + is replaced by a Space.
What should be done is encode the param response-content-type so it appears as following : ?response-content-type=application/x-maven-pom%2Bxml
Comment From: greggy-laloutre
Hello,
I'll try to be a little bit more explicit about this issue
When downloading jar files of spring-ai on Artifactory, the server send the file without usage of http-header '302 Redirect'
curl -v "https://repo.spring.io/artifactory/snapshot/org/springframework/ai/spring-ai-openai-spring-boot-starter/0.8.0-SNAPSHOT/spring-ai-openai-spring-boot-starter-0.8.0-20240223.153858-187.jar"
< HTTP/1.1 200
< Date: Thu, 29 Feb 2024 07:59:05 GMT
< Content-Type: application/java-archive
< Content-Length: 15042
< X-JFrog-Version: Artifactory/7.75.4 77504900
< X-Artifactory-Id: 78fb8ada8cea780f8199dc42639d11b4c40514e9
< X-Artifactory-Node-Id: springsource-artifactory-primary-1
< Last-Modified: Fri, 23 Feb 2024 15:49:54 GMT
< ETag: 818706c3caa1a4e6928c0d7c0cc3c0adb2c379db
< X-Checksum-Sha1: 818706c3caa1a4e6928c0d7c0cc3c0adb2c379db
< X-Checksum-Sha256: ee924e8b6014fde0ef7c24af5b12f327ef0cccd646e8e3a0e956b2812ab6c865
< X-Checksum-Md5: a7fc99f3f838db5a45d293f11aa4b260
< Accept-Ranges: bytes
< X-Artifactory-Filename: spring-ai-openai-spring-boot-starter-0.8.0-20240223.153858-187.jar
< Content-Disposition: attachment; filename="spring-ai-openai-spring-boot-starter-0.8.0-20240223.153858-187.jar"; filename*=UTF-8''spring-ai-openai-spring-boot-starter-0.8.0-20240223.153858-187.jar
< Strict-Transport-Security: max-age=31536000; includeSubDomains
< X-Request-ID: b83f54881676bd598ea82028c4cb47eb
But for pom.xml file, the server use a 302 Redirect to send the file
curl -v -L "https://repo.spring.io/artifactory/snapshot/org/springframework/ai/spring-ai-openai-spring-boot-starter/0.8.0-SNAPSHOT/spring-ai-openai-spring-boot-starter-0.8.0-20240223.153858-187.pom"
* Mark bundle as not supporting multiuse
< HTTP/1.1 302
< Date: Thu, 29 Feb 2024 07:56:41 GMT
< Transfer-Encoding: chunked
< X-JFrog-Version: Artifactory/7.75.4 77504900
< X-Artifactory-Id: 78fb8ada8cea780f8199dc42639d11b4c40514e9
< X-Artifactory-Node-Id: springsource-artifactory-primary-1
< Location: https://d3q7ofw6tj09q0.cloudfront.net/filestore/c8/c8e31f3db9a958382130790a38d77d8c0a67d09f?response-content-type=application/x-maven-pom+xml&response-content-disposition=attachment%3Bfilename%3D%22spring-ai-openai-spring-boot-starter-0.8.0-20240223.153858-187.pom%22&x-jf-traceId=ebd9b44d44d3b147&X-Artifactory-repositoryKey=libs-snapshot-local&X-Artifactory-projectKey=default&X-Artifactory-artifactPath=org%2Fspringframework%2Fai%2Fspring-ai-openai-spring-boot-starter%2F0.8.0-SNAPSHOT%2Fspring-ai-openai-spring-boot-starter-0.8.0-20240223.153858-187.pom&X-Artifactory-username=anonymous&X-Artifactory-repoType=local&X-Artifactory-packageType=maven&Expires=1709193461&Signature=YxFXs1GWOML5L6fAZ~3-TFgOoj4hke6LY5RVqJCE17aiA537wzhxPd8W00Ml00SxQeMb55KqmGi4ncGYy90adX2mXiBC059PinWx9DBhkix-YQejkNIRoQCL2KJJDqGX3ULKTUHO-rGHsKOTkSRuqK2TIh1Hage2USnw854I0cCjgrFWH8Kg2nDll6AWfru9IL9iKisMGrCTyBrUC3wKoiNWqqMmIeGO2oE5mb3Xmt4~V0Y5Hs2hc9GH~WYErSQH55TmLZ0hBilBUWk~P3I9NYC~IY5XGSCwIPdstVRfmmKzsAw~4e~Z8I6JGVhfjo8xnLen91kbuoPONsDCdpNnRg__&Key-Pair-Id=APKAJ6NHFWMVU3M6DPBA
< Strict-Transport-Security: max-age=31536000; includeSubDomains
< X-Request-ID: 6b310e1fed4c64ba96d4a06359ac261f
< Connection: keep-alive
<
....
>
* Mark bundle as not supporting multiuse
< HTTP/1.1 200 OK
< Content-Type: application/x-maven-pom xml
< Content-Length: 260998
< Connection: keep-alive
< Date: Thu, 29 Feb 2024 07:56:43 GMT
< x-amz-replication-status: COMPLETED
< Last-Modified: Fri, 23 Feb 2024 15:49:55 GMT
< ETag: "0d24fef5be7f7c05199c4d728d069aa0"
< x-amz-server-side-encryption: AES256
< x-amz-version-id: qrJDmEgY.gNf8I8Kh7AyODxXPiCJGQ1X
< Content-Disposition: attachment;filename="spring-ai-openai-spring-boot-starter-0.8.0-20240223.153858-187.pom"
< Accept-Ranges: bytes
< Server: AmazonS3
< X-Cache: Miss from cloudfront
< Via: 1.1 79d85d2de1f5aa38558ef6bab6274390.cloudfront.net (CloudFront)
< X-Amz-Cf-Pop: FRA56-P9
< X-Amz-Cf-Id: voNndkNb7pKybUEUhKcq42Pe3veUaR0yqZfIlX3ZEbhTrd3RsxDJbQ==
The query-param response-content-type=application/x-maven-pom+xml
in the Location Header became a header in the next server response
Content-Type: application/x-maven-pom xml
So the + in the query param is a space character in the header !
There is 2 way to fix this :
- Ask Jfrog to url-encode the query-parameter response-content-type=application/x-maven-pom+xml in the redirect Location header. The correct value should be response-content-type=application/x-maven-pom%2Bxml
(taken for Location header of the 302 redirect above) Location: https://serverURL?response-content-type=application/x-maven-pom+xml&response-content-disposition=attachment%3Bfilename%3D%22spring-ai-openai-spring-boot-starter-0.8.0-20240223.153858-187.pom%22
- Stop using a redirect for pom.xml, Spring-ai seems to be the only spring project to proceed like this.
Thanks for your help. Grégory
Comment From: greggy-laloutre
I just saw spring-ai:0.8.0 has been published on Milestone repository with the same error.
Comment From: markpollack
I've asked someone on our team with more knowledge about these matters to investigate. We are following the same publish procedure as the Spring Batch project FWIW.
Comment From: jvalkeal
As you've probably noticed from request logs the trouble comes from cloudfront which acts as a cdn frontend. We're investigating why this only affects spring-ai
artifacts as rest of the spring umbrella looks to be fine.
Comment From: jvalkeal
@greggy-laloutre We changed cdn settings. Can you try again.
Comment From: greggy-laloutre
Hello, headers looks great for Snapshot and Milestone ! Thanks for the update of your CDN. I'm currently in vacation, so I'll ask to my colleague to validate our Nexus connection to your repository.
Comment From: markpollack
Closing the issue, reopen if you still get errors.