Skip to content

Instantly share code, notes, and snippets.

@hubertcross
Last active December 28, 2020 02:07
Show Gist options
  • Select an option

  • Save hubertcross/20e664155d09f8423cb2e555ad3b0ede to your computer and use it in GitHub Desktop.

Select an option

Save hubertcross/20e664155d09f8423cb2e555ad3b0ede to your computer and use it in GitHub Desktop.
City Codable class is sent in HTTP POST Request. Good example of generic type constraints in WebRestCommunication.makeHTTPPostRequest()
import Foundation
class City: NSObject, Codable {
var name: String = ""
var countrycode: String = ""
var district: String = ""
var population: Int = 0
init(name: String, countrycode: String, district: String, population: Int) {
self.name = name
self.countrycode = countrycode
self.district = district
self.population = population
}
}
import Foundation
class RestArguments {
var urlComponents = URLComponents()
// See URLComponents structure
var urlScheme: String
var urlHost: String
var urlPath: String
var urlPort: Int
// Built-in Key/value pair for POST requests
var urlQueryItems = [URLQueryItem]()
// Name of the controller that handles request
var objectName: String
// The 'id' following the controller in URL
var resource: String
// User performing request
var displayName: String
// HTTP Request type (See enum)
var type: RequestType
init() {
self.objectName = ""
self.resource = ""
self.displayName = ""
self.type = .get
self.urlHost = ""
self.urlScheme = ""
self.urlPath = ""
self.urlPort = 80
}
// The 4 main types of HTTP requests
enum RequestType {
case get
case put
case post
case delete
}
}
@IBAction func sendPostRequest(_ sender: UIButton) {
let wc: WebRestCommunication = WebRestCommunication()
let restArgs: RestArguments = RestArguments()
let post = City(name: "Antarctica", countrycode: "NIC", district: "LindaVista", population: 99)
restArgs.urlComponents.scheme = "http"
restArgs.urlComponents.host = "192.168.56.2"
restArgs.urlComponents.path = "/api/cities"
restArgs.urlComponents.port = 3002
wc.makeHTTPPOSTRequest(args: restArgs, payload: post)
}
import Foundation
class WebRestCommunication {
// Must use generic type constraint
// https://stackoverflow.com/questions/45053060/using-jsonencoder-to-encode-a-variable-with-codable-as-type
func makeHTTPPOSTRequest<T: Codable>(args: RestArguments, payload: T) {
guard let url = args.urlComponents.url else {
fatalError("Could not create URL from components!")
}
print("full URL: " + url.absoluteString)
var urlRequest = URLRequest(url: url)
urlRequest.httpMethod = "POST"
// Headers must specify that the HTTP request body is JSON-encoded
var headers = urlRequest.allHTTPHeaderFields ?? [:]
headers["Content-Type"] = "application/json"
urlRequest.allHTTPHeaderFields = headers
// encode post struct into JSON format
let encoder = JSONEncoder()
do {
let jsonData = try encoder.encode(payload)
urlRequest.httpBody = jsonData
print("jsonData: ", String(data: urlRequest.httpBody!, encoding: .utf8) ?? "no body data")
} catch {
print(String(describing: error))
}
// set up the session
let config = URLSessionConfiguration.default
let session = URLSession(configuration: config)
// make the request
let task = session.dataTask(with: urlRequest) {
(data, response, error) in
// check for any errors
guard error == nil else {
print("error calling POST on (url)")
print(error!)
return
}
guard let httpResponse = response as? HTTPURLResponse,
(200...299).contains(httpResponse.statusCode) else {
print("Server error")
return
}
// Success response
print("HTTP Post successful. Return code: " + String(httpResponse.statusCode))
if let mimeType = httpResponse.mimeType /*, mimeType == "application/json"*/ {
print("MimeType: " + mimeType)
}
}
task.resume()
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment