How to create a simple Error object for network requests?
enum GHError: Error {
case invalidURL
case invalidResponse
case invalidData
}How to create a simple URL?
let endpoint = "https://api.github.com/users/sallen0400"
guard let url = URL(string: endpoint) else {
throw GHError.invalidURL
}How to create a GET request?
let (data, response) = try await URLSession.shared.data(from: url)
Verify the GET request has a valid response
guard let response = response as? HTTPURLResponse, response.statusCode == 200 else {
throw GHError.invalidResponse
}Common HTTP responses codes?
200 -> OK
400 -> Bad Request / Invalid sysntax or parameters
401 -> Authentication required or failed
403 -> Authenticated but not allowed
404 -> Resource not found
500 -> Generic Server Failure
How is the Object that will contain the decoded response
struct GitHubUser: Codable {
// define JSON values here
}How to decode a response?
do {
let decoder = JSONDecoder ()
decoder.keyDecodingStrategy = .convertFromSnakeCase
return try decoder.decode(GitHubUser.self, from: data)
} catch {
throw GHError.invalidData
}What does this strategy do?
~~~
decoder.keyDecodingStrategy = .convertFromSnakeCase
~~~
The JSON response may have properties defined using the snake_case form. This will map the response’s properties to the swift Struct
How to implement a generic network request?
func getuser<T: Decodable>(for: T.Type) async throws -> T {
let endpoint = "https://api.github.com/users/sallen0400"
guard let url = URL(string: endpoint) else {
throw GHError.invalidURL
}
let (data, response) = try await URLSession.shared.data(from: url)
guard let response = response as? HTTPURLResponse, response.statusCode == 200 else {
throw GHError.invalidResponse
}
do {
let decoder = JSONDecoder ()
decoder.keyDecodingStrategy = .convertFromSnakeCase
return try decoder.decode(T.self, from: data)
} catch {
throw GHError.invalidData
}
}How to add query parameters to a URL?
var components = URLComponents(string: "https://api.example.com/search")!
components.queryItems = [
URLQueryItem(name: "query", value: "swift"),
URLQueryItem(name: "page", value: "1")
]
guard let url = components.url else {
throw GHError.invalidURL
}How to handle optional query parameters in a URL?
var components = URLComponents(string: "https://api.example.com/users")!
var queryItems: [URLQueryItem] = []
if let username = optionalUsername {
queryItems.append(URLQueryItem(name: "username", value: username))
}
components.queryItems = queryItems
guard let url = components.url else {
throw GHError.invalidURL
}How to create a POST request using URLSession?
var request = URLRequest(url: url estampado request.httpMethod = "POST" let (data, response) = try await URLSession.shared.data(for: request)
How to encode a JSON body for a POST request?
struct User: Codable {
let name: String
let email: String
}
let user = User(name: "John", email: "john@example.com")
let jsonData = try JSONEncoder().encode(user)
request.httpBody = jsonData
request.setValue("application/json", forHTTPHeaderField: "Content-Type")How to set custom HTTP headers in a request?
request.setValue("application/json", forHTTPHeaderField: "Accept")
request.setValue("Bearer yourToken", forHTTPHeaderField: "Authorization")How to handle Bearer token authentication?
let token = "your_access_token"
request.setValue("Bearer \(token)", forHTTPHeaderField: "Authorization")How to handle Basic authentication?
let credentials = "username:password"
let base64Credentials = credentials.data(using: .utf8)!.base64EncodedString()
request.setValue("Basic \(base64Credentials)", forHTTPHeaderField: "Authorization")How to verify different HTTP status codes?
guard let httpResponse = response as? HTTPURLResponse,
(200...299).contains(httpResponse.statusCode) else {
throw GHError.invalidResponse
}How to handle specific error responses from the server?
if let httpResponse = response as? HTTPURLResponse, httpResponse.statusCode != 200 {
struct APIError: Codable, Error {
let message: String
}
let error = try JSONDecoder().decode(APIError.self, from: data)
throw error
}How to create a PUT request for updating data?
request.httpMethod = "PUT" request.httpBody = jsonData // encoded data let (data, response) = try await URLSession.shared.data(for: request)
How to create a DELETE request?
request.httpMethod = "DELETE" let (data, response) = try await URLSession.shared.data(for: request)
How to upload multipart form data?
let boundary = "Boundary-\(UUID().uuidString)"
request.setValue("multipart/form-data; boundary=\(boundary)", forHTTPHeaderField: "Content-Type")
var body = Data()
body.append("--\(boundary)\r\n".data(using: .utf8)!)
body.append("Content-Disposition: form-data; name=\"param\"\r\n\r\nvalue\r\n".data(using: .utf8)!)
body.append("--\(boundary)--\r\n".data(using: .utf8)!)
request.httpBody = bodyHow to upload a file using URLSession?
let fileURL = URL(fileURLWithPath: "/path/to/file") let request = URLRequest(url: uploadURL) let data = try await URLSession.shared.upload(for: request, fromFile: fileURL).0
How to download a file asynchronously?
let (localURL, response) = try await URLSession.shared.download(from: url) try FileManager.default.moveItem(at: localURL, to: destinationURL)
How to resume a download task?
let resumeData = // previously saved data let (localURL, response) = try await URLSession.shared.download(resumingWith: resumeData)