-
Notifications
You must be signed in to change notification settings - Fork 125
Implement SOCKS proxy functionality #375
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 24 commits
5a49c2c
b45f4d9
8e1232a
974677f
122f650
f1598be
481e1b1
064edcb
210c4d7
18c7103
323eefd
c273847
3c0e120
ba629a4
e4c1b52
d718299
eee59e3
112d5b1
976fe2e
ea04cfa
ddc009a
221420f
91a1636
15e5334
c61184e
97c6b7f
dd405af
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -342,8 +342,8 @@ extension HTTPClient { | |
} | ||
|
||
/// HTTP authentication | ||
public struct Authorization { | ||
private enum Scheme { | ||
public struct Authorization: Hashable { | ||
private enum Scheme: Hashable { | ||
Comment on lines
+345
to
+346
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why was this added? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Getting equatable conformance on the internal Proxy Type enum. |
||
case Basic(String) | ||
case Bearer(String) | ||
} | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
//===----------------------------------------------------------------------===// | ||
// | ||
// This source file is part of the AsyncHTTPClient open source project | ||
// | ||
// Copyright (c) 2018-2019 Apple Inc. 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 | ||
// | ||
//===----------------------------------------------------------------------===// | ||
// | ||
// HTTPClient+SOCKSTests+XCTest.swift | ||
// | ||
import XCTest | ||
|
||
/// | ||
/// NOTE: This file was generated by generate_linux_tests.rb | ||
/// | ||
/// Do NOT edit this file directly as it will be regenerated automatically when needed. | ||
/// | ||
|
||
extension HTTPClientSOCKSTests { | ||
static var allTests: [(String, (HTTPClientSOCKSTests) -> () throws -> Void)] { | ||
return [ | ||
("testProxySOCKS", testProxySOCKS), | ||
("testProxySOCKSBogusAddress", testProxySOCKSBogusAddress), | ||
("testProxySOCKSFailureNoServer", testProxySOCKSFailureNoServer), | ||
("testProxySOCKSFailureInvalidServer", testProxySOCKSFailureInvalidServer), | ||
("testProxySOCKSMisbehavingServer", testProxySOCKSMisbehavingServer), | ||
] | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,139 @@ | ||
//===----------------------------------------------------------------------===// | ||
// | ||
// This source file is part of the AsyncHTTPClient open source project | ||
// | ||
// Copyright (c) 2018-2019 Apple Inc. and the AsyncHTTPClient project authors | ||
Davidde94 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
// 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 | ||
// | ||
//===----------------------------------------------------------------------===// | ||
|
||
/* NOT @testable */ import AsyncHTTPClient // Tests that need @testable go into HTTPClientInternalTests.swift | ||
import NIO | ||
import NIOSOCKS | ||
import XCTest | ||
import Logging | ||
|
||
class HTTPClientSOCKSTests: XCTestCase { | ||
|
||
typealias Request = HTTPClient.Request | ||
|
||
var clientGroup: EventLoopGroup! | ||
var serverGroup: EventLoopGroup! | ||
var defaultHTTPBin: HTTPBin! | ||
var defaultClient: HTTPClient! | ||
var backgroundLogStore: CollectEverythingLogHandler.LogStore! | ||
|
||
var defaultHTTPBinURLPrefix: String { | ||
return "http://localhost:\(self.defaultHTTPBin.port)/" | ||
} | ||
|
||
override func setUp() { | ||
XCTAssertNil(self.clientGroup) | ||
XCTAssertNil(self.serverGroup) | ||
XCTAssertNil(self.defaultHTTPBin) | ||
XCTAssertNil(self.defaultClient) | ||
XCTAssertNil(self.backgroundLogStore) | ||
|
||
self.clientGroup = getDefaultEventLoopGroup(numberOfThreads: 1) | ||
self.serverGroup = MultiThreadedEventLoopGroup(numberOfThreads: 1) | ||
self.defaultHTTPBin = HTTPBin() | ||
self.backgroundLogStore = CollectEverythingLogHandler.LogStore() | ||
var backgroundLogger = Logger(label: "\(#function)", factory: { _ in | ||
CollectEverythingLogHandler(logStore: self.backgroundLogStore!) | ||
}) | ||
backgroundLogger.logLevel = .trace | ||
self.defaultClient = HTTPClient(eventLoopGroupProvider: .shared(self.clientGroup), | ||
backgroundActivityLogger: backgroundLogger) | ||
} | ||
|
||
override func tearDown() { | ||
if let defaultClient = self.defaultClient { | ||
XCTAssertNoThrow(try defaultClient.syncShutdown()) | ||
self.defaultClient = nil | ||
} | ||
|
||
XCTAssertNotNil(self.defaultHTTPBin) | ||
XCTAssertNoThrow(try self.defaultHTTPBin.shutdown()) | ||
self.defaultHTTPBin = nil | ||
|
||
XCTAssertNotNil(self.clientGroup) | ||
XCTAssertNoThrow(try self.clientGroup.syncShutdownGracefully()) | ||
self.clientGroup = nil | ||
|
||
XCTAssertNotNil(self.serverGroup) | ||
XCTAssertNoThrow(try self.serverGroup.syncShutdownGracefully()) | ||
self.serverGroup = nil | ||
|
||
XCTAssertNotNil(self.backgroundLogStore) | ||
self.backgroundLogStore = nil | ||
} | ||
|
||
func testProxySOCKS() throws { | ||
let socksBin = try MockSOCKSServer(expectedURL: "/socks/test", expectedResponse: "it works!") | ||
let localClient = HTTPClient(eventLoopGroupProvider: .shared(self.clientGroup), | ||
configuration: .init(proxy: .socksServer(host: "127.0.0.1"))) | ||
Davidde94 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
defer { | ||
XCTAssertNoThrow(try localClient.syncShutdown()) | ||
XCTAssertNoThrow(try socksBin.shutdown()) | ||
} | ||
|
||
var response: HTTPClient.Response? | ||
XCTAssertNoThrow(response = try localClient.get(url: "http://127.0.0.1/socks/test").wait()) | ||
XCTAssertEqual(.ok, response?.status) | ||
XCTAssertEqual(ByteBuffer(string: "it works!"), response?.body) | ||
} | ||
|
||
func testProxySOCKSBogusAddress() throws { | ||
let localClient = HTTPClient(eventLoopGroupProvider: .shared(self.clientGroup), | ||
configuration: .init(proxy: .socksServer(host: "127.0.."))) | ||
|
||
defer { | ||
XCTAssertNoThrow(try localClient.syncShutdown()) | ||
} | ||
XCTAssertThrowsError(try localClient.get(url: "http://127.0.0.1/socks/test").wait()) | ||
} | ||
|
||
// there is no socks server, so we should fail | ||
func testProxySOCKSFailureNoServer() throws { | ||
let localHTTPBin = HTTPBin() | ||
let localClient = HTTPClient(eventLoopGroupProvider: .shared(self.clientGroup), | ||
configuration: .init(proxy: .socksServer(host: "127.0.0.1", port: localHTTPBin.port))) | ||
defer { | ||
XCTAssertNoThrow(try localClient.syncShutdown()) | ||
XCTAssertNoThrow(try localHTTPBin.shutdown()) | ||
} | ||
XCTAssertThrowsError(try localClient.get(url: "http://127.0.0.1/socks/test").wait()) | ||
} | ||
|
||
// speak to a server that doesn't speak SOCKS | ||
func testProxySOCKSFailureInvalidServer() throws { | ||
let localClient = HTTPClient(eventLoopGroupProvider: .shared(self.clientGroup), | ||
configuration: .init(proxy: .socksServer(host: "127.0.0.1"))) | ||
defer { | ||
XCTAssertNoThrow(try localClient.syncShutdown()) | ||
} | ||
XCTAssertThrowsError(try localClient.get(url: "http://127.0.0.1/socks/test").wait()) | ||
} | ||
|
||
// test a handshake failure with a misbehaving server | ||
func testProxySOCKSMisbehavingServer() throws { | ||
let socksBin = try MockSOCKSServer(expectedURL: "/socks/test", expectedResponse: "it works!", misbehave: true) | ||
let localClient = HTTPClient(eventLoopGroupProvider: .shared(self.clientGroup), | ||
configuration: .init(proxy: .socksServer(host: "127.0.0.1"))) | ||
|
||
defer { | ||
XCTAssertNoThrow(try localClient.syncShutdown()) | ||
XCTAssertNoThrow(try socksBin.shutdown()) | ||
} | ||
|
||
// the server will send a bogus message in response to the clients request | ||
XCTAssertThrowsError(try localClient.get(url: "http://127.0.0.1/socks/test").wait()) | ||
} | ||
|
||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -22,6 +22,7 @@ import NIOConcurrencyHelpers | |
import NIOFoundationCompat | ||
import NIOHTTP1 | ||
import NIOHTTPCompression | ||
import NIOSOCKS | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't think we need this here :) |
||
import NIOSSL | ||
import NIOTestUtils | ||
import NIOTransportServices | ||
|
Uh oh!
There was an error while loading. Please reload this page.