mirror of https://github.com/sbt/sbt.git
[2.x] fix: Display HTTP response body when bundle upload fails (#8630)
When a bundle upload to Central Portal fails, the error now displays the HTTP response body instead of just the status code. This provides more useful debugging information, as the response body typically contains detailed error messages from the server.
This commit is contained in:
parent
aa4ac5b981
commit
a66a3064f9
|
|
@ -82,7 +82,7 @@ class SonaClient(reqTransform: Request => Request, uploadRequestTimeout: FiniteD
|
|||
)
|
||||
)
|
||||
.withRequestTimeout(uploadRequestTimeout)
|
||||
http.run(reqTransform(req), Gigahorse.asString)
|
||||
http.run(reqTransform(req), SonaClient.asStringWithErrorBody)
|
||||
}
|
||||
awaitWithMessage(res, "uploading...", log, totalAwaitDuration)
|
||||
}
|
||||
|
|
@ -200,6 +200,17 @@ object SonaClient {
|
|||
Parser.parseFromByteBuffer(r.bodyAsByteBuffer).get
|
||||
def as[A1: JsonFormat]: FullResponse => A1 = asJson.andThen(Converter.fromJsonUnsafe[A1])
|
||||
val asPublisherStatus: FullResponse => PublisherStatus = as[PublisherStatus]
|
||||
|
||||
/**
|
||||
* Response handler that returns the body as a String on success (2xx status),
|
||||
* or throws a [[SonaStatusError]] with both the status code and response body on failure.
|
||||
* This provides more detailed error information than [[gigahorse.StatusError]].
|
||||
*/
|
||||
val asStringWithErrorBody: FullResponse => String = { response =>
|
||||
val body = response.bodyAsString
|
||||
if (response.status >= 200 && response.status < 300) body
|
||||
else throw new SonaStatusError(response.status, body)
|
||||
}
|
||||
def oauthClient(
|
||||
userName: String,
|
||||
userToken: String,
|
||||
|
|
@ -270,3 +281,17 @@ object PublishingType {
|
|||
case object Automatic extends PublishingType
|
||||
case object UserManaged extends PublishingType
|
||||
}
|
||||
|
||||
/**
|
||||
* Exception thrown when an HTTP request to the Sonatype API fails with a non-2xx status.
|
||||
* Unlike [[gigahorse.StatusError]], this exception includes the response body which
|
||||
* typically contains useful error details from the server.
|
||||
*
|
||||
* @param status the HTTP status code
|
||||
* @param body the response body content
|
||||
*/
|
||||
class SonaStatusError(val status: Int, val body: String)
|
||||
extends RuntimeException(
|
||||
if (body.nonEmpty) s"Unexpected status: $status\n$body"
|
||||
else s"Unexpected status: $status"
|
||||
)
|
||||
|
|
|
|||
|
|
@ -17,6 +17,21 @@ import scala.collection.immutable
|
|||
|
||||
object SonaClientTest extends BasicTestSuite:
|
||||
|
||||
test("SonaStatusError should include both status and body in message"):
|
||||
val error = new SonaStatusError(401, "Invalid token")
|
||||
assert(error.status == 401)
|
||||
assert(error.body == "Invalid token")
|
||||
assert(error.getMessage == "Unexpected status: 401\nInvalid token")
|
||||
|
||||
test("SonaStatusError should handle empty body"):
|
||||
val error = new SonaStatusError(500, "")
|
||||
assert(error.getMessage == "Unexpected status: 500")
|
||||
|
||||
test("SonaStatusError should preserve multiline error body"):
|
||||
val body = """{"error": "Unauthorized", "message": "Invalid credentials"}"""
|
||||
val error = new SonaStatusError(401, body)
|
||||
assert(error.getMessage.contains(body))
|
||||
|
||||
private def doTest(
|
||||
errorsJsonText: Option[String],
|
||||
expectedErrorMessage: String,
|
||||
|
|
|
|||
Loading…
Reference in New Issue