Skip to content

Commit

Permalink
refactor: adds statusCode to serverError (#10)
Browse files Browse the repository at this point in the history
  • Loading branch information
kevinhermawan authored Nov 2, 2024
1 parent ca255db commit 913fb08
Show file tree
Hide file tree
Showing 5 changed files with 31 additions and 21 deletions.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -209,9 +209,9 @@ do {
print(completion.content.first?.text ?? "No response")
} catch let error as LLMChatAnthropicError {
switch error {
case .serverError(let message):
case .serverError(let statusCode, let message):
// Handle server-side errors (e.g., invalid API key, rate limits)
print("Server Error: \(message)")
print("Server Error [\(statusCode)]: \(message)")
case .networkError(let error):
// Handle network-related errors (e.g., no internet connection)
print("Network Error: \(error.localizedDescription)")
Expand Down
4 changes: 2 additions & 2 deletions Sources/LLMChatAnthropic/Documentation.docc/Documentation.md
Original file line number Diff line number Diff line change
Expand Up @@ -180,9 +180,9 @@ do {
print(completion.content.first?.text ?? "No response")
} catch let error as LLMChatAnthropicError {
switch error {
case .serverError(let message):
case .serverError(let statusCode, let message):
// Handle server-side errors (e.g., invalid API key, rate limits)
print("Server Error: \(message)")
print("Server Error [\(statusCode)]: \(message)")
case .networkError(let error):
// Handle network-related errors (e.g., no internet connection)
print("Network Error: \(error.localizedDescription)")
Expand Down
14 changes: 9 additions & 5 deletions Sources/LLMChatAnthropic/LLMChatAnthropic.swift
Original file line number Diff line number Diff line change
Expand Up @@ -90,16 +90,16 @@ private extension LLMChatAnthropic {
let (data, response) = try await URLSession.shared.data(for: request)

guard let httpResponse = response as? HTTPURLResponse else {
throw LLMChatAnthropicError.serverError(response.description)
throw LLMChatAnthropicError.serverError(statusCode: 0, message: response.description)
}

// Check for API errors first, as they might come with 200 status
if let errorResponse = try? JSONDecoder().decode(ChatCompletionError.self, from: data) {
throw LLMChatAnthropicError.serverError(errorResponse.error.message)
throw LLMChatAnthropicError.serverError(statusCode: httpResponse.statusCode, message: errorResponse.error.message)
}

guard 200...299 ~= httpResponse.statusCode else {
throw LLMChatAnthropicError.serverError(response.description)
throw LLMChatAnthropicError.serverError(statusCode: httpResponse.statusCode, message: response.description)
}

return try JSONDecoder().decode(ChatCompletion.self, from: data)
Expand All @@ -124,8 +124,12 @@ private extension LLMChatAnthropic {
let request = try createRequest(for: endpoint, with: body)
let (bytes, response) = try await URLSession.shared.bytes(for: request)

guard let httpResponse = response as? HTTPURLResponse, 200...299 ~= httpResponse.statusCode else {
throw LLMChatAnthropicError.serverError(response.description)
guard let httpResponse = response as? HTTPURLResponse else {
throw LLMChatAnthropicError.serverError(statusCode: 0, message: response.description)
}

guard 200...299 ~= httpResponse.statusCode else {
throw LLMChatAnthropicError.serverError(statusCode: httpResponse.statusCode, message: response.description)
}

var currentChunk = ChatCompletionChunk(id: "", model: "", role: "")
Expand Down
6 changes: 4 additions & 2 deletions Sources/LLMChatAnthropic/LLMChatAnthropicError.swift
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,10 @@ public enum LLMChatAnthropicError: Error, Sendable {

/// An error returned by the server.
///
/// - Parameter message: The error message received from the server.
case serverError(String)
/// - Parameters:
/// - statusCode: The HTTP status code returned by the server.
/// - message: The error message received from the server.
case serverError(statusCode: Int, message: String)

/// An error that occurs during stream processing.
case streamError
Expand Down
24 changes: 14 additions & 10 deletions Tests/LLMChatAnthropicTests/ChatCompletionTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -138,22 +138,24 @@ final class ChatCompletionTests: XCTestCase {
extension ChatCompletionTests {
func testServerError() async throws {
let mockErrorResponse = """
{
"error": {
"message": "Invalid API key provided"
{
"error": {
"message": "Invalid API key provided"
}
}
}
"""
"""

URLProtocolMock.mockData = mockErrorResponse.data(using: .utf8)
URLProtocolMock.mockStatusCode = 401

do {
_ = try await chat.send(model: "claude-3-5-sonnet", messages: messages)

XCTFail("Expected serverError to be thrown")
} catch let error as LLMChatAnthropicError {
switch error {
case .serverError(let message):
case .serverError(let statusCode, let message):
XCTAssertEqual(statusCode, 401)
XCTAssertEqual(message, "Invalid API key provided")
default:
XCTFail("Expected serverError but got \(error)")
Expand Down Expand Up @@ -183,16 +185,17 @@ extension ChatCompletionTests {
}

func testHTTPError() async throws {
URLProtocolMock.mockStatusCode = 429
URLProtocolMock.mockData = "Rate limit exceeded".data(using: .utf8)
URLProtocolMock.mockStatusCode = 429

do {
_ = try await chat.send(model: "claude-3-5-sonnet", messages: messages)

XCTFail("Expected serverError to be thrown")
} catch let error as LLMChatAnthropicError {
switch error {
case .serverError(let message):
case .serverError(let statusCode, let message):
XCTAssertEqual(statusCode, 429)
XCTAssertTrue(message.contains("429"))
default:
XCTFail("Expected serverError but got \(error)")
Expand Down Expand Up @@ -283,16 +286,17 @@ extension ChatCompletionTests {
}

func testStreamHTTPError() async throws {
URLProtocolMock.mockStatusCode = 503
URLProtocolMock.mockStreamData = [""]
URLProtocolMock.mockStatusCode = 503

do {
for try await _ in chat.stream(model: "claude-3-5-sonnet", messages: messages) {
XCTFail("Expected serverError to be thrown")
}
} catch let error as LLMChatAnthropicError {
switch error {
case .serverError(let message):
case .serverError(let statusCode, let message):
XCTAssertEqual(statusCode, 503)
XCTAssertTrue(message.contains("503"))
default:
XCTFail("Expected serverError but got \(error)")
Expand Down

0 comments on commit 913fb08

Please sign in to comment.