mirror of
https://github.com/apple/swift-nio-extras.git
synced 2025-05-15 09:22:38 +08:00
* Add HTTP types adapter for SwiftNIO * swiftformat * Guard on Swift 5.8 * Review comments * Update swift-http-types to 0.1.1 * Update swift-http-types to 1.0.0 * Review feedback * Review feedback * Bump minimum Swift version to 5.7.1 * Allow Host in any order
171 lines
6.2 KiB
Swift
171 lines
6.2 KiB
Swift
//===----------------------------------------------------------------------===//
|
|
//
|
|
// This source file is part of the SwiftNIO open source project
|
|
//
|
|
// Copyright (c) 2023 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
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
import HTTPTypes
|
|
import NIOCore
|
|
import NIOEmbedded
|
|
import NIOHTTP1
|
|
import NIOHTTPTypes
|
|
import NIOHTTPTypesHTTP1
|
|
import XCTest
|
|
|
|
/// A handler that keeps track of all reads made on a channel.
|
|
private final class InboundRecorder<Frame>: ChannelInboundHandler {
|
|
typealias InboundIn = Frame
|
|
|
|
var receivedFrames: [Frame] = []
|
|
|
|
func channelRead(context: ChannelHandlerContext, data: NIOAny) {
|
|
self.receivedFrames.append(self.unwrapInboundIn(data))
|
|
}
|
|
}
|
|
|
|
extension HTTPField.Name {
|
|
static let xFoo = Self("X-Foo")!
|
|
}
|
|
|
|
final class NIOHTTPTypesHTTP1Tests: XCTestCase {
|
|
var channel: EmbeddedChannel!
|
|
|
|
override func setUp() {
|
|
super.setUp()
|
|
self.channel = EmbeddedChannel()
|
|
}
|
|
|
|
override func tearDown() {
|
|
self.channel = nil
|
|
super.tearDown()
|
|
}
|
|
|
|
static let request = HTTPRequest(method: .get, scheme: "https", authority: "www.example.com", path: "/", headerFields: [
|
|
.accept: "*/*",
|
|
.acceptEncoding: "gzip",
|
|
.acceptEncoding: "br",
|
|
.cookie: "a=b",
|
|
.cookie: "c=d",
|
|
.trailer: "X-Foo",
|
|
])
|
|
|
|
static let requestNoSplitCookie = HTTPRequest(method: .get, scheme: "https", authority: "www.example.com", path: "/", headerFields: [
|
|
.accept: "*/*",
|
|
.acceptEncoding: "gzip",
|
|
.acceptEncoding: "br",
|
|
.cookie: "a=b; c=d",
|
|
.trailer: "X-Foo",
|
|
])
|
|
|
|
static let oldRequest = HTTPRequestHead(version: .http1_1, method: .GET, uri: "/", headers: [
|
|
"Host": "www.example.com",
|
|
"Accept": "*/*",
|
|
"Accept-Encoding": "gzip",
|
|
"Accept-Encoding": "br",
|
|
"Cookie": "a=b; c=d",
|
|
"Trailer": "X-Foo",
|
|
])
|
|
|
|
static let response = HTTPResponse(status: .ok, headerFields: [
|
|
.server: "HTTPServer/1.0",
|
|
.trailer: "X-Foo",
|
|
])
|
|
|
|
static let oldResponse = HTTPResponseHead(version: .http1_1, status: .ok, headers: [
|
|
"Server": "HTTPServer/1.0",
|
|
"Trailer": "X-Foo",
|
|
])
|
|
|
|
static let trailers: HTTPFields = [.xFoo: "Bar"]
|
|
|
|
static let oldTrailers: HTTPHeaders = ["X-Foo": "Bar"]
|
|
|
|
func testClientHTTP1ToHTTP() throws {
|
|
let recorder = InboundRecorder<HTTPResponsePart>()
|
|
|
|
try self.channel.pipeline.addHandlers(HTTP1ToHTTPClientCodec(), recorder).wait()
|
|
|
|
try self.channel.writeOutbound(HTTPRequestPart.head(Self.request))
|
|
try self.channel.writeOutbound(HTTPRequestPart.end(Self.trailers))
|
|
|
|
XCTAssertEqual(try self.channel.readOutbound(as: HTTPClientRequestPart.self), .head(Self.oldRequest))
|
|
XCTAssertEqual(try self.channel.readOutbound(as: HTTPClientRequestPart.self), .end(Self.oldTrailers))
|
|
|
|
try self.channel.writeInbound(HTTPClientResponsePart.head(Self.oldResponse))
|
|
try self.channel.writeInbound(HTTPClientResponsePart.end(Self.oldTrailers))
|
|
|
|
XCTAssertEqual(recorder.receivedFrames[0], .head(Self.response))
|
|
XCTAssertEqual(recorder.receivedFrames[1], .end(Self.trailers))
|
|
|
|
XCTAssertTrue(try self.channel.finish().isClean)
|
|
}
|
|
|
|
func testServerHTTP1ToHTTP() throws {
|
|
let recorder = InboundRecorder<HTTPRequestPart>()
|
|
|
|
try self.channel.pipeline.addHandlers(HTTP1ToHTTPServerCodec(secure: true), recorder).wait()
|
|
|
|
try self.channel.writeInbound(HTTPServerRequestPart.head(Self.oldRequest))
|
|
try self.channel.writeInbound(HTTPServerRequestPart.end(Self.oldTrailers))
|
|
|
|
XCTAssertEqual(recorder.receivedFrames[0], .head(Self.requestNoSplitCookie))
|
|
XCTAssertEqual(recorder.receivedFrames[1], .end(Self.trailers))
|
|
|
|
try self.channel.writeOutbound(HTTPResponsePart.head(Self.response))
|
|
try self.channel.writeOutbound(HTTPResponsePart.end(Self.trailers))
|
|
|
|
XCTAssertEqual(try self.channel.readOutbound(as: HTTPServerResponsePart.self), .head(Self.oldResponse))
|
|
XCTAssertEqual(try self.channel.readOutbound(as: HTTPServerResponsePart.self), .end(Self.oldTrailers))
|
|
|
|
XCTAssertTrue(try self.channel.finish().isClean)
|
|
}
|
|
|
|
func testClientHTTPToHTTP1() throws {
|
|
let recorder = InboundRecorder<HTTPClientResponsePart>()
|
|
|
|
try self.channel.pipeline.addHandlers(HTTPToHTTP1ClientCodec(secure: true), recorder).wait()
|
|
|
|
try self.channel.writeOutbound(HTTPClientRequestPart.head(Self.oldRequest))
|
|
try self.channel.writeOutbound(HTTPClientRequestPart.end(Self.oldTrailers))
|
|
|
|
XCTAssertEqual(try self.channel.readOutbound(as: HTTPRequestPart.self), .head(Self.request))
|
|
XCTAssertEqual(try self.channel.readOutbound(as: HTTPRequestPart.self), .end(Self.trailers))
|
|
|
|
try self.channel.writeInbound(HTTPResponsePart.head(Self.response))
|
|
try self.channel.writeInbound(HTTPResponsePart.end(Self.trailers))
|
|
|
|
XCTAssertEqual(recorder.receivedFrames[0], .head(Self.oldResponse))
|
|
XCTAssertEqual(recorder.receivedFrames[1], .end(Self.oldTrailers))
|
|
|
|
XCTAssertTrue(try self.channel.finish().isClean)
|
|
}
|
|
|
|
func testServerHTTPToHTTP1() throws {
|
|
let recorder = InboundRecorder<HTTPServerRequestPart>()
|
|
|
|
try self.channel.pipeline.addHandlers(HTTPToHTTP1ServerCodec(), recorder).wait()
|
|
|
|
try self.channel.writeInbound(HTTPRequestPart.head(Self.request))
|
|
try self.channel.writeInbound(HTTPRequestPart.end(Self.trailers))
|
|
|
|
XCTAssertEqual(recorder.receivedFrames[0], .head(Self.oldRequest))
|
|
XCTAssertEqual(recorder.receivedFrames[1], .end(Self.oldTrailers))
|
|
|
|
try self.channel.writeOutbound(HTTPServerResponsePart.head(Self.oldResponse))
|
|
try self.channel.writeOutbound(HTTPServerResponsePart.end(Self.oldTrailers))
|
|
|
|
XCTAssertEqual(try self.channel.readOutbound(as: HTTPResponsePart.self), .head(Self.response))
|
|
XCTAssertEqual(try self.channel.readOutbound(as: HTTPResponsePart.self), .end(Self.trailers))
|
|
|
|
XCTAssertTrue(try self.channel.finish().isClean)
|
|
}
|
|
}
|