HTTP参数和HTTP头之间有什么区别?

30

我阅读了这个问题,但它没有回答我的问题。

对我来说,Headers和Parameters都是字典,不同之处在于headers是[String : String],而Parameters是[String : AnyObject]?,因此如果您的参数也是字符串,则可以将它们发送到标题中(同时使用“x-”前缀表示它们不是标准标题),这是一种常见但不好的做法。

  • 那正确吗?
  • headersparameters之间还有什么其他区别吗?
  • 您将使用parameters发送哪些其他非字符串类型?

Alamofire Request方法

public func request(
        method: Method,
        _ URLString: URLStringConvertible,
          parameters: [String: AnyObject]? = nil,
          encoding: ParameterEncoding = .URL,
          headers: [String: String]? = nil)
        -> Request
    {
        return Manager.sharedInstance.request(
            method,
            URLString,
            parameters: parameters,
            encoding: encoding,
            headers: headers
        )
    }
作为一个例子,我看到人们通过头部传递["x-ios-version" : UIDevice.currentDevice().systemVersion]或构建版本。

4
HTTP规范指出:“请求头字段允许客户端向服务器传递有关请求和客户端本身的其他信息。” 头部是关于请求的元信息,允许Web服务器解析请求。 另一方面,请求的参数是请求的实际内容。 我不会混淆这两者,只是因为它们都由键值对组成。 - Rob
@Rob 好的。我在询问我应该做什么。同时,我也在询问其他人都做了什么 :) 不管它是否好...这样我就可以理解他们的代码以及其他人如何使用HTTP头部。如果我重复了自己,请原谅:如果您的参数也是字符串,则可以将它们发送到标头中(同时使用“x-”前缀表示它们不是标准标头),这是一种有些常见但不好的做法 <-- 有人会这样使用吗? - mfaani
我真的不明白。你在问是否可以添加自己的自定义标头,其中包含实际属于参数的信息,即使你知道这不是好的做法?当然可以,但这是一个坏主意。如果您有正在考虑将其作为标头的参数示例,请编辑问题以包括该示例。 - Rob
这是一个很好的例子,可以合理地作为标题。 - Rob
@Rob:我不明白!我以为你会说这是不好的。按照什么标准,它不应该在参数中?还是只是个人偏好,所以你不想发送两个对象? - mfaani
让我们在聊天中继续这个讨论:http://chat.stackoverflow.com/rooms/127656/discussion-between-rob-and-honey。 - Rob
2个回答

33

接受的答案非常实用,请确保看到它。但是有两个基本差异需要深入讨论:

HTTP请求中标题和参数的放置位置

URL与HTTP消息不同。 HTTP消息可以是请求响应。在这个答案中,我将专注于请求。

HTTP请求主要由URL、HTTP方法、HTTP标题(其中包含其他块,但我只是提到我们最关心的部分)组成。

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

请求行是:

Request-Line   = Method SP Request-URI SP HTTP-Version CRLF

CLRF类似于换行符。

更多信息请参见此处此处。您可能需要在链接之间来回翻阅,直到弄明白为止。如果您真的想深入了解,则可以查看此RFC

所以基本上一个请求是这样的:

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

查询参数(query params)位于URL内。HTTP头不是URL的一部分,它们是HTTP消息的一部分。在上面的示例中,query paramstag=networking&order=newest,头文件如下:

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
当您发起网络请求时,使用http协议发送一个结构化的字符串。该字符串通过TCP连接发送。
2 - 为什么和在哪种情况下选择一种方法优于另一种方法
如果涉及到请求或客户端信息,则使用标头;但如果涉及请求本身的内容(例如从服务器请求的内容、用于识别返回项目的一些详细信息、要保存在Web服务器上的某些详细信息等),则使用参数。大多数情况下,应用程序的标头都是相同的,但由于基于内容,因此应更加丰富多样。使用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
        }
    }
}

29

以下是它们之间的区别:

  1. 它们的设计目的不同。Headers 承载元信息,而 Parameters 承载实际数据。

  2. HTTP 服务器会自动取消转义/解码参数名和值。但对于 Headers 的名称和值,不适用此规则。

  3. Header 的名称和值需要在客户端手动进行转义/编码,并在服务器端进行手动的取消转义/解码。Base64 编码或百分号编码通常被使用。

  4. 用户可以看到参数(位于URL中),但头部对于用户来说是隐藏的。


那如果我想发送阿拉伯语的内容,我需要使用参数吗? - mfaani
除非您将阿拉伯文本转换为Base64文本,否则请仅返回翻译后的文本 - 例如。 - LHA
1
或者百分号转义它。但无论如何,您都必须在服务器端手动反转该过程(因为参数通常基于请求的Content-Type标头由Web服务器自动解释)。 - Rob

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接