The accepted answer is very practical. Make sure you see it. But there are two foundational differences I will discuss in depth:
Where header and parameters are placed in an HTTP Request
A URL is different from an HTTP Message. An HTTP Message can either be a Request or a Response. In this answer I will focus on the request. An HTTP Message is just a String with a very specific structure/standard.
An HTTP Request is made up of mainly the url, http-method, http-headers (there are other chunks in it, but I’m just mentioning the ones we care about the most)
Request = Request-Line ; Section 5.1
*(( general-header ; Section 4.5
| request-header ; Section 5.3
| entity-header ) CRLF) ; Section 7.1
CRLF
[ message-body ] ; Section 4.3
A request line is:
Request-Line = Method SP Request-URI SP HTTP-Version CRLF
CLRF
is something like a new line.
For more see here and here. You might have to do some back and forth between the links til you get it right. If you really wanted to go deep then see see this RFC
So basically a request is something like:
POST /cgi-bin/process.cgi?tag=networking&order=newest HTTP/1.1
User-Agent: Mozilla/4.0 (compatible; MSIE5.01; Windows NT)
Host: www.tutorialspoint.com
Content-Type: text/xml; charset=utf-8
Content-Length: 60
Accept-Language: en-us
Accept-Encoding: gzip, deflate
Connection: Keep-Alive
first=Zara&last=Ali
The query params are within the URL. HTTP Headers are NOT part of the URL. They’re part of the HTTP Message. In the above example, query params is tag=networking&order=newest
, the headers are:
User-Agent: Mozilla/4.0 (compatible; MSIE5.01; Windows NT)
Host: www.tutorialspoint.com
Content-Type: text/xml; charset=utf-8
Content-Length: 60
Accept-Language: en-us
Accept-Encoding: gzip, deflate
Connection: Keep-Alive
So when you make a network request, you’re sending a structured STRING using the http protocol. That string is sent through a TCP connection.
2 – Why and where one is preferred over the other
From discussion with Rob in chat:
The criteria is that if it’s information about the request or about the client, then the header is appropriate.
But if it’s the content of the request itself (e.g. what you are requesting from the server, some details that identify the item to be returned, some details to be saved on the web server, etc.), then it’s a parameter e.g.:
Parameter
Let’s say you’re requesting an image for a product. The product id may be one parameter. The image size (thumbnail vs full size) might be another parameter.
The product id and requested image size are examples of “some detail” (or parameter) being supplied as part of the content of a request.
Header
But things like the request is JSON or x-www-form-urlencoded
are not the content of the request, but meta data about the request (especially since it’s necessary for web service to know how to parse the body of the request). That’s why it’s a header.
Most likely if your app makes various requests, its headers would have a lot in common. However the parameters due to the fact that they are content based should be more varied.
Construction using URLComponents
class UnsplashRequester {
static let session = URLSession.shared
static let host = "api.unsplash.com"
static let photosPath = "/photos"
static let accessKey = "My_access_key"
static func imageRequester(pageValue: String, completion: @escaping (Data?) -> Void) {
var components = URLComponents()
components.scheme = "https"
components.host = host
components.path = photosPath
// A: Adding a Query Parameter to a URL
components.queryItems = [URLQueryItem(name: "page", value: pageValue)]
let headers: [String: String] = ["Authorization": "Client-ID \(accessKey)"]
var request = URLRequest(url: components.url!)
for header in headers {
// B: Adding a Header to a URL
request.addValue(header.value, forHTTPHeaderField: header.key)
}
let task = session.dataTask(with: request) { data, _, error in
}
}
}