diff --git a/IntegrationTests/tests_04_performance/Thresholds/6.1.json b/IntegrationTests/tests_04_performance/Thresholds/6.1.json index d772e9f5f2a..20243fb8c23 100644 --- a/IntegrationTests/tests_04_performance/Thresholds/6.1.json +++ b/IntegrationTests/tests_04_performance/Thresholds/6.1.json @@ -12,14 +12,14 @@ "1000_copying_circularbuffer_to_array": 1050, "1000_getHandlers": 8050, "1000_getHandlers_sync": 37, - "1000_reqs_1_conn": 26350, + "1000_reqs_1_conn": 27400, "1000_rst_connections": 138050, "1000_tcpbootstraps": 3050, "1000_tcpconnections": 146050, "1000_udp_reqs": 6050, "1000_udpbootstraps": 2050, "1000_udpconnections": 75050, - "1_reqs_1000_conn": 375050, + "1_reqs_1000_conn": 377050, "assume_isolated_scheduling_10000_executions": 88, "bytebuffer_lots_of_rw": 2050, "creating_10000_headers": 0, diff --git a/IntegrationTests/tests_04_performance/Thresholds/6.2.json b/IntegrationTests/tests_04_performance/Thresholds/6.2.json index c1f1f84fd3b..20ccd1c0135 100644 --- a/IntegrationTests/tests_04_performance/Thresholds/6.2.json +++ b/IntegrationTests/tests_04_performance/Thresholds/6.2.json @@ -12,14 +12,14 @@ "1000_copying_circularbuffer_to_array": 1050, "1000_getHandlers": 8050, "1000_getHandlers_sync": 37, - "1000_reqs_1_conn": 26350, + "1000_reqs_1_conn": 27400, "1000_rst_connections": 138050, "1000_tcpbootstraps": 3050, "1000_tcpconnections": 146050, "1000_udp_reqs": 6050, "1000_udpbootstraps": 2050, "1000_udpconnections": 75050, - "1_reqs_1000_conn": 375050, + "1_reqs_1000_conn": 377050, "assume_isolated_scheduling_10000_executions": 88, "bytebuffer_lots_of_rw": 2050, "creating_10000_headers": 0, diff --git a/IntegrationTests/tests_04_performance/Thresholds/6.3.json b/IntegrationTests/tests_04_performance/Thresholds/6.3.json index c1f1f84fd3b..a8890aa86c5 100644 --- a/IntegrationTests/tests_04_performance/Thresholds/6.3.json +++ b/IntegrationTests/tests_04_performance/Thresholds/6.3.json @@ -12,14 +12,14 @@ "1000_copying_circularbuffer_to_array": 1050, "1000_getHandlers": 8050, "1000_getHandlers_sync": 37, - "1000_reqs_1_conn": 26350, + "1000_reqs_1_conn": 27350, "1000_rst_connections": 138050, "1000_tcpbootstraps": 3050, "1000_tcpconnections": 146050, "1000_udp_reqs": 6050, "1000_udpbootstraps": 2050, "1000_udpconnections": 75050, - "1_reqs_1000_conn": 375050, + "1_reqs_1000_conn": 377050, "assume_isolated_scheduling_10000_executions": 88, "bytebuffer_lots_of_rw": 2050, "creating_10000_headers": 0, diff --git a/IntegrationTests/tests_04_performance/Thresholds/nightly-main.json b/IntegrationTests/tests_04_performance/Thresholds/nightly-main.json index e5f1af0586e..456ce4d7dd5 100644 --- a/IntegrationTests/tests_04_performance/Thresholds/nightly-main.json +++ b/IntegrationTests/tests_04_performance/Thresholds/nightly-main.json @@ -1,59 +1,59 @@ { - "10000000_asyncsequenceproducer": 21, - "1000000_asyncwriter": 1000050, - "1000_addHandlers": 46050, - "1000_addHandlers_sync": 39050, - "1000_addRemoveHandlers_handlercontext": 8050, - "1000_addRemoveHandlers_handlername": 8050, - "1000_addRemoveHandlers_handlertype": 8050, - "1000_autoReadGetAndSet": 18050, + "10000000_asyncsequenceproducer": 0, + "1000000_asyncwriter": 0, + "1000_addHandlers": 0, + "1000_addHandlers_sync": 0, + "1000_addRemoveHandlers_handlercontext": 0, + "1000_addRemoveHandlers_handlername": 0, + "1000_addRemoveHandlers_handlertype": 0, + "1000_autoReadGetAndSet": 0, "1000_autoReadGetAndSet_sync": 0, - "1000_copying_bytebufferview_to_array": 1050, - "1000_copying_circularbuffer_to_array": 1050, - "1000_getHandlers": 8050, - "1000_getHandlers_sync": 37, - "1000_reqs_1_conn": 26350, - "1000_rst_connections": 136050, - "1000_tcpbootstraps": 3050, - "1000_tcpconnections": 144050, - "1000_udp_reqs": 6050, - "1000_udpbootstraps": 2050, - "1000_udpconnections": 74050, - "1_reqs_1000_conn": 372050, - "assume_isolated_scheduling_10000_executions": 88, - "bytebuffer_lots_of_rw": 2050, + "1000_copying_bytebufferview_to_array": 0, + "1000_copying_circularbuffer_to_array": 0, + "1000_getHandlers": 0, + "1000_getHandlers_sync": 0, + "1000_reqs_1_conn": 3050, + "1000_rst_connections": 2050, + "1000_tcpbootstraps": 0, + "1000_tcpconnections": 4050, + "1000_udp_reqs": 1050, + "1000_udpbootstraps": 0, + "1000_udpconnections": 1, + "1_reqs_1000_conn": 10050, + "assume_isolated_scheduling_10000_executions": 0, + "bytebuffer_lots_of_rw": 1, "creating_10000_headers": 0, - "decode_1000_ws_frames": 2050, - "encode_1000_ws_frames_holding_buffer": 3, - "encode_1000_ws_frames_holding_buffer_with_mask": 2050, - "encode_1000_ws_frames_holding_buffer_with_space": 3, - "encode_1000_ws_frames_holding_buffer_with_space_with_mask": 2050, - "encode_1000_ws_frames_new_buffer": 3050, - "encode_1000_ws_frames_new_buffer_with_mask": 5050, - "encode_1000_ws_frames_new_buffer_with_space": 3050, - "encode_1000_ws_frames_new_buffer_with_space_with_mask": 5050, + "decode_1000_ws_frames": 0, + "encode_1000_ws_frames_holding_buffer": 1, + "encode_1000_ws_frames_holding_buffer_with_mask": 1050, + "encode_1000_ws_frames_holding_buffer_with_space": 1, + "encode_1000_ws_frames_holding_buffer_with_space_with_mask": 1050, + "encode_1000_ws_frames_new_buffer": 1050, + "encode_1000_ws_frames_new_buffer_with_mask": 2050, + "encode_1000_ws_frames_new_buffer_with_space": 1050, + "encode_1000_ws_frames_new_buffer_with_space_with_mask": 2050, "execute_hop_10000_tasks": 0, - "flat_schedule_10000_tasks": 100100, - "flat_schedule_assume_isolated_10000_tasks": 80100, - "future_assume_isolated_lots_of_callbacks": 68050, - "future_erase_result": 4050, - "future_lots_of_callbacks": 68050, - "get_100000_headers_canonical_form": 500050, - "get_100000_headers_canonical_form_trimming_whitespace": 500050, - "get_100000_headers_canonical_form_trimming_whitespace_from_long_string": 500050, - "get_100000_headers_canonical_form_trimming_whitespace_from_short_string": 500050, + "flat_schedule_10000_tasks": 0, + "flat_schedule_assume_isolated_10000_tasks": 0, + "future_assume_isolated_lots_of_callbacks": 0, + "future_erase_result": 0, + "future_lots_of_callbacks": 0, + "get_100000_headers_canonical_form": 0, + "get_100000_headers_canonical_form_trimming_whitespace": 0, + "get_100000_headers_canonical_form_trimming_whitespace_from_long_string": 0, + "get_100000_headers_canonical_form_trimming_whitespace_from_short_string": 0, "modifying_1000_circular_buffer_elements": 0, - "modifying_byte_buffer_view": 6050, - "ping_pong_1000_reqs_1_conn": 302, - "read_10000_chunks_from_file": 110050, - "schedule_10000_tasks": 40100, - "schedule_and_run_10000_tasks": 50050, - "schedule_assume_isolated_10000_tasks": 40100, - "schedule_with_deadline_10000_tasks": 40100, - "schedule_with_deadline_assume_isolated_10000_tasks": 40100, - "scheduling_10000_executions": 88, - "submit_10000_tasks": 20100, - "submit_assume_isolated_10000_tasks": 20100, - "udp_1000_reqs_1_conn": 6200, - "udp_1_reqs_1000_conn": 160050 + "modifying_byte_buffer_view": 3050, + "ping_pong_1000_reqs_1_conn": 6, + "read_10000_chunks_from_file": 10050, + "schedule_10000_tasks": 0, + "schedule_and_run_10000_tasks": 0, + "schedule_assume_isolated_10000_tasks": 0, + "schedule_with_deadline_10000_tasks": 0, + "schedule_with_deadline_assume_isolated_10000_tasks": 0, + "scheduling_10000_executions": 0, + "submit_10000_tasks": 0, + "submit_assume_isolated_10000_tasks": 0, + "udp_1000_reqs_1_conn": 1050, + "udp_1_reqs_1000_conn": 7050 } diff --git a/IntegrationTests/tests_04_performance/Thresholds/nightly-next.json b/IntegrationTests/tests_04_performance/Thresholds/nightly-next.json index b87aad146bc..20ccd1c0135 100644 --- a/IntegrationTests/tests_04_performance/Thresholds/nightly-next.json +++ b/IntegrationTests/tests_04_performance/Thresholds/nightly-next.json @@ -1,5 +1,5 @@ { - "10000000_asyncsequenceproducer": 21, + "10000000_asyncsequenceproducer": 18, "1000000_asyncwriter": 1000050, "1000_addHandlers": 46050, "1000_addHandlers_sync": 39050, @@ -12,14 +12,14 @@ "1000_copying_circularbuffer_to_array": 1050, "1000_getHandlers": 8050, "1000_getHandlers_sync": 37, - "1000_reqs_1_conn": 26350, + "1000_reqs_1_conn": 27400, "1000_rst_connections": 138050, "1000_tcpbootstraps": 3050, "1000_tcpconnections": 146050, "1000_udp_reqs": 6050, "1000_udpbootstraps": 2050, "1000_udpconnections": 75050, - "1_reqs_1000_conn": 375050, + "1_reqs_1000_conn": 377050, "assume_isolated_scheduling_10000_executions": 88, "bytebuffer_lots_of_rw": 2050, "creating_10000_headers": 0, diff --git a/Sources/NIOCrashTester/CrashTestSuites.swift b/Sources/NIOCrashTester/CrashTestSuites.swift index 601ca55b948..f99fd9fae30 100644 --- a/Sources/NIOCrashTester/CrashTestSuites.swift +++ b/Sources/NIOCrashTester/CrashTestSuites.swift @@ -18,7 +18,6 @@ func makeCrashTestSuites() -> [String: Any] { "EventLoopCrashTests": EventLoopCrashTests(), "ByteBufferCrashTests": ByteBufferCrashTests(), "SystemCrashTests": SystemCrashTests(), - "HTTPCrashTests": HTTPCrashTests(), "StrictCrashTests": StrictCrashTests(), "LoopBoundTests": LoopBoundTests(), ] diff --git a/Sources/NIOCrashTester/CrashTests+HTTP.swift b/Sources/NIOCrashTester/CrashTests+HTTP.swift deleted file mode 100644 index 2773754c232..00000000000 --- a/Sources/NIOCrashTester/CrashTests+HTTP.swift +++ /dev/null @@ -1,61 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// This source file is part of the SwiftNIO open source project -// -// Copyright (c) 2020-2021 Apple Inc. and the SwiftNIO project authors -// Licensed under Apache License v2.0 -// -// See LICENSE.txt for license information -// See CONTRIBUTORS.txt for the list of SwiftNIO project authors -// -// SPDX-License-Identifier: Apache-2.0 -// -//===----------------------------------------------------------------------===// -#if !canImport(Darwin) || os(macOS) -import NIOEmbedded -import NIOCore -import NIOHTTP1 - -struct HTTPCrashTests { - let testEncodingChunkedAndContentLengthForRequestsCrashes = CrashTest( - regex: - "Assertion failed: illegal HTTP sent: HTTPRequestHead .* contains both a content-length and transfer-encoding:chunked", - { - let channel = EmbeddedChannel(handler: HTTPRequestEncoder()) - _ = try? channel.writeAndFlush( - HTTPClientRequestPart.head( - HTTPRequestHead( - version: .http1_1, - method: .POST, - uri: "/", - headers: [ - "content-Length": "1", - "transfer-Encoding": "chunked", - ] - ) - ) - ).wait() - } - ) - - let testEncodingChunkedAndContentLengthForResponseCrashes = CrashTest( - regex: - "Assertion failed: illegal HTTP sent: HTTPResponseHead .* contains both a content-length and transfer-encoding:chunked", - { - let channel = EmbeddedChannel(handler: HTTPResponseEncoder()) - _ = try? channel.writeAndFlush( - HTTPServerResponsePart.head( - HTTPResponseHead( - version: .http1_1, - status: .ok, - headers: [ - "content-Length": "1", - "transfer-Encoding": "chunked", - ] - ) - ) - ).wait() - } - ) -} -#endif diff --git a/Sources/NIOHTTP1/HTTPEncoder.swift b/Sources/NIOHTTP1/HTTPEncoder.swift index df953a18dec..f0e9d03508b 100644 --- a/Sources/NIOHTTP1/HTTPEncoder.swift +++ b/Sources/NIOHTTP1/HTTPEncoder.swift @@ -133,6 +133,7 @@ private func correctlyFrameTransportHeaders( return .neither case .yes: if headers.contains(name: "content-length") { + headers.remove(name: "transfer-encoding") return .contentLength } if version.major == 1 && version.minor >= 1 { @@ -143,6 +144,7 @@ private func correctlyFrameTransportHeaders( } case .unlikely: if headers.contains(name: "content-length") { + headers.remove(name: "transfer-encoding") return .contentLength } if version.major == 1 && version.minor >= 1 { @@ -204,11 +206,6 @@ public final class HTTPRequestEncoder: ChannelOutboundHandler, RemovableChannelH public func write(context: ChannelHandlerContext, data: NIOAny, promise: EventLoopPromise?) { switch HTTPRequestEncoder.unwrapOutboundIn(data) { case .head(var request): - assert( - !(request.headers.contains(name: "content-length") - && request.headers[canonicalForm: "transfer-encoding"].contains("chunked"[...])), - "illegal HTTP sent: \(request) contains both a content-length and transfer-encoding:chunked" - ) if self.configuration.automaticallySetFramingHeaders { self.isChunked = correctlyFrameTransportHeaders( @@ -294,12 +291,6 @@ public final class HTTPResponseEncoder: ChannelOutboundHandler, RemovableChannel public func write(context: ChannelHandlerContext, data: NIOAny, promise: EventLoopPromise?) { switch HTTPResponseEncoder.unwrapOutboundIn(data) { case .head(var response): - assert( - !(response.headers.contains(name: "content-length") - && response.headers[canonicalForm: "transfer-encoding"].contains("chunked"[...])), - "illegal HTTP sent: \(response) contains both a content-length and transfer-encoding:chunked" - ) - if self.configuration.automaticallySetFramingHeaders { self.isChunked = correctlyFrameTransportHeaders( diff --git a/Tests/NIOHTTP1Tests/HTTPRequestEncoderTest.swift b/Tests/NIOHTTP1Tests/HTTPRequestEncoderTest.swift index 3fc4954085b..ecc76ace43d 100644 --- a/Tests/NIOHTTP1Tests/HTTPRequestEncoderTest.swift +++ b/Tests/NIOHTTP1Tests/HTTPRequestEncoderTest.swift @@ -448,6 +448,24 @@ class HTTPRequestEncoderTests: XCTestCase { XCTAssertEqual(trailerBuffer, ByteBuffer(string: "0\r\n\r\n")) } + func testConflictingFramingHeadersStripsTransferEncoding() throws { + let headers = HTTPHeaders([ + ("transfer-encoding", "chunked"), + ("content-length", "3"), + ]) + let writtenData = try sendRequest(withMethod: .POST, andHeaders: headers) + writtenData.assertContainsOnly("POST /uri HTTP/1.1\r\ncontent-length: 3\r\n\r\n") + } + + func testConflictingFramingHeadersStripsTransferEncoding_unlikely() throws { + let headers = HTTPHeaders([ + ("transfer-encoding", "chunked"), + ("content-length", "0"), + ]) + let writtenData = try sendRequest(withMethod: .GET, andHeaders: headers) + writtenData.assertContainsOnly("GET /uri HTTP/1.1\r\ncontent-length: 0\r\n\r\n") + } + private func assertOutboundContainsOnly(_ channel: EmbeddedChannel, _ expected: String) { XCTAssertNoThrow( XCTAssertNotNil( diff --git a/Tests/NIOHTTP1Tests/HTTPResponseEncoderTest.swift b/Tests/NIOHTTP1Tests/HTTPResponseEncoderTest.swift index 95f67a9c1dc..e7dab98ef24 100644 --- a/Tests/NIOHTTP1Tests/HTTPResponseEncoderTest.swift +++ b/Tests/NIOHTTP1Tests/HTTPResponseEncoderTest.swift @@ -357,4 +357,13 @@ class HTTPResponseEncoderTests: XCTestCase { } XCTAssertEqual(trailerBuffer, ByteBuffer(string: "0\r\n\r\n")) } + + func testConflictingFramingHeadersStripsTransferEncoding() throws { + let headers = HTTPHeaders([ + ("transfer-encoding", "chunked"), + ("content-length", "3"), + ]) + let writtenData = sendResponse(withStatus: .ok, andHeaders: headers) + writtenData.assertContainsOnly("HTTP/1.1 200 OK\r\ncontent-length: 3\r\n\r\n") + } }