Files
async-http-client/Sources/AsyncHTTPClient/RequestValidation.swift
T
2019-07-02 14:00:34 +03:00

63 lines
2.2 KiB
Swift

//===----------------------------------------------------------------------===//
//
// This source file is part of the AsyncHTTPClient open source project
//
// Copyright (c) 2018-2019 Swift Server Working Group and the AsyncHTTPClient project authors
// Licensed under Apache License v2.0
//
// See LICENSE.txt for license information
// See CONTRIBUTORS.txt for the list of AsyncHTTPClient project authors
//
// SPDX-License-Identifier: Apache-2.0
//
//===----------------------------------------------------------------------===//
import NIO
import NIOHTTP1
extension HTTPHeaders {
mutating func validate(body: HTTPClient.Body?) throws {
// validate transfer encoding and content length (https://tools.ietf.org/html/rfc7230#section-3.3.1)
var transferEncoding: String?
var contentLength: Int?
let encodings = self[canonicalForm: "Transfer-Encoding"].map { $0.lowercased() }
guard !encodings.contains("identity") else {
throw HTTPClientError.identityCodingIncorrectlyPresent
}
self.remove(name: "Transfer-Encoding")
self.remove(name: "Content-Length")
if let body = body {
guard (encodings.filter { $0 == "chunked" }.count <= 1) else {
throw HTTPClientError.chunkedSpecifiedMultipleTimes
}
if encodings.isEmpty {
guard let length = body.length else {
throw HTTPClientError.contentLengthMissing
}
contentLength = length
} else {
transferEncoding = encodings.joined(separator: ", ")
if !encodings.contains("chunked") {
guard let length = body.length else {
throw HTTPClientError.contentLengthMissing
}
contentLength = length
}
}
} else {
contentLength = 0
}
// add headers if required
if let enc = transferEncoding {
self.add(name: "Transfer-Encoding", value: enc)
}
if let length = contentLength {
self.add(name: "Content-Length", value: String(length))
}
}
}