-
Notifications
You must be signed in to change notification settings - Fork 133
Support UNIX Domain Sockets #151
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 2 commits
4932cb5
41ee04e
ac69f69
d3bbf37
bbd47f7
cb19a2d
45c443f
535303b
5233d5c
b6cf0a4
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 |
---|---|---|
|
@@ -89,24 +89,47 @@ extension HTTPClient { | |
/// Represent HTTP request. | ||
public struct Request { | ||
/// Request HTTP method, defaults to `GET`. | ||
public let method: HTTPMethod | ||
public var method: HTTPMethod { | ||
return value.method | ||
} | ||
/// Remote URL. | ||
public let url: URL | ||
public var url: URL { | ||
return value.url | ||
} | ||
/// Remote HTTP scheme, resolved from `URL`. | ||
public let scheme: String | ||
public var scheme: String { | ||
return value.scheme | ||
} | ||
/// Remote host, resolved from `URL`. | ||
public let host: String | ||
public var host: String { | ||
return value.host | ||
} | ||
/// Request custom HTTP Headers, defaults to no headers. | ||
public var headers: HTTPHeaders | ||
public var headers: HTTPHeaders { | ||
get { | ||
return value.headers | ||
} | ||
set { | ||
value.headers = newValue | ||
} | ||
} | ||
/// Request body, defaults to no body. | ||
public var body: Body? | ||
public var body: Body? { | ||
get { | ||
return value.body | ||
} | ||
set { | ||
value.body = newValue | ||
} | ||
} | ||
|
||
struct RedirectState { | ||
var count: Int | ||
var visited: Set<URL>? | ||
} | ||
|
||
var redirectState: RedirectState? | ||
private var value: HTTPRequest | ||
|
||
/// Create HTTP request. | ||
/// | ||
|
@@ -129,6 +152,57 @@ extension HTTPClient { | |
try self.init(url: url, method: method, headers: headers, body: body) | ||
} | ||
|
||
/// Create an HTTP `Request`. | ||
/// | ||
/// - parameters: | ||
/// - url: Remote `URL`. | ||
/// - version: HTTP version. | ||
/// - method: HTTP method. | ||
/// - headers: Custom HTTP headers. | ||
/// - body: Request body. | ||
/// - throws: | ||
/// - `emptyScheme` if URL does not contain HTTP scheme. | ||
/// - `unsupportedScheme` if URL does contains unsupported HTTP scheme. | ||
/// - `emptyHost` if URL does not contains a host. | ||
public init(url: URL, method: HTTPMethod = .GET, headers: HTTPHeaders = HTTPHeaders(), body: Body? = nil) throws { | ||
if url.isFileURL { | ||
self.value = try UnixDomainRequest(url: url, method: method, headers: headers, body: body) | ||
} else { | ||
self.value = try HostRequest(url: url, method: method, headers: headers, body: body) | ||
} | ||
self.redirectState = nil | ||
} | ||
|
||
/// Whether request will be executed using secure socket. | ||
public var useTLS: Bool { | ||
return self.scheme == "https" | ||
} | ||
|
||
/// Resolved port. | ||
public var port: Int { | ||
return self.url.port ?? (self.useTLS ? 443 : 80) | ||
} | ||
|
||
func isSchemeSupported(scheme: String) -> Bool { | ||
return type(of: self.value).isSchemeSupported(scheme: scheme) | ||
} | ||
} | ||
|
||
/// Represent HTTP request. | ||
public struct HostRequest: HTTPRequest { | ||
/// Request HTTP method, defaults to `GET`. | ||
public let method: HTTPMethod | ||
/// Remote URL. | ||
public let url: URL | ||
/// Remote HTTP scheme, resolved from `URL`. | ||
public let scheme: String | ||
/// Remote host, resolved from `URL`. | ||
public let host: String | ||
/// Request custom HTTP Headers, defaults to no headers. | ||
public var headers: HTTPHeaders | ||
/// Request body, defaults to no body. | ||
public var body: Body? | ||
|
||
/// Create an HTTP `Request`. | ||
/// | ||
/// - parameters: | ||
|
@@ -146,7 +220,7 @@ extension HTTPClient { | |
throw HTTPClientError.emptyScheme | ||
} | ||
|
||
guard Request.isSchemeSupported(scheme: scheme) else { | ||
guard Self.isSchemeSupported(scheme: scheme) else { | ||
throw HTTPClientError.unsupportedScheme(scheme) | ||
} | ||
|
||
|
||
|
@@ -160,23 +234,61 @@ extension HTTPClient { | |
self.host = host | ||
self.headers = headers | ||
self.body = body | ||
|
||
self.redirectState = nil | ||
} | ||
|
||
/// Whether request will be executed using secure socket. | ||
public var useTLS: Bool { | ||
return self.scheme == "https" | ||
static func isSchemeSupported(scheme: String) -> Bool { | ||
return scheme == "http" || scheme == "https" | ||
} | ||
} | ||
|
||
/// Resolved port. | ||
public var port: Int { | ||
return self.url.port ?? (self.useTLS ? 443 : 80) | ||
/// Represent UNIX Domain Socket HTTP request. | ||
public struct UnixDomainRequest: HTTPRequest { | ||
/// Request HTTP method, defaults to `GET`. | ||
public let method: HTTPMethod | ||
/// UNIX Domain Socket file URL. | ||
public let url: URL | ||
/// Remote HTTP scheme, resolved from `URL`. Unused. | ||
public let scheme: String | ||
/// Remote host, resolved from `URL`. Unused. | ||
public let host: String | ||
/// Request custom HTTP Headers, defaults to no headers. | ||
public var headers: HTTPHeaders | ||
/// Request body, defaults to no body. | ||
public var body: Body? | ||
|
||
/// Create an HTTP `Request`. | ||
/// | ||
/// - parameters: | ||
/// - url: UNIX Domain Socket `URL`. | ||
/// - version: HTTP version. | ||
/// - method: HTTP method. | ||
/// - headers: Custom HTTP headers. | ||
/// - body: Request body. | ||
/// - throws: | ||
/// - `emptyScheme` if URL does not contain HTTP scheme. | ||
/// - `unsupportedScheme` if URL does contains unsupported HTTP scheme. | ||
/// - `emptyHost` if URL does not contains a host. | ||
public init(url: URL, method: HTTPMethod = .GET, headers: HTTPHeaders = HTTPHeaders(), body: Body? = nil) throws { | ||
guard url.isFileURL else { | ||
throw HTTPClientError.invalidURL | ||
} | ||
|
||
guard let scheme = url.scheme?.lowercased() else { | ||
throw HTTPClientError.emptyScheme | ||
} | ||
|
||
self.method = method | ||
self.url = url | ||
self.scheme = scheme | ||
self.host = "" | ||
self.headers = headers | ||
self.body = body | ||
} | ||
|
||
static func isSchemeSupported(scheme: String) -> Bool { | ||
return scheme == "http" || scheme == "https" | ||
return scheme == "file" | ||
} | ||
|
||
} | ||
|
||
/// Represent HTTP response. | ||
|
@@ -812,7 +924,7 @@ internal struct RedirectHandler<ResponseType> { | |
return nil | ||
} | ||
|
||
guard HTTPClient.Request.isSchemeSupported(scheme: self.request.scheme) else { | ||
guard request.isSchemeSupported(scheme: self.request.scheme) else { | ||
return nil | ||
} | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
// | ||
// File.swift | ||
// | ||
// | ||
// Created by Marcin Krzyzanowski on 19/01/2020. | ||
// | ||
|
||
import Foundation | ||
import NIOHTTP1 | ||
|
||
protocol HTTPRequest { | ||
/// Request HTTP method | ||
var method: HTTPMethod { get } | ||
/// Remote URL. | ||
var url: URL { get } | ||
/// Remote HTTP scheme, resolved from `URL`. | ||
var scheme: String { get } | ||
/// Remote host, resolved from `URL`. | ||
var host: String { get } | ||
/// Request custom HTTP Headers, defaults to no headers. | ||
var headers: HTTPHeaders { get set } | ||
/// Request body, defaults to no body. | ||
var body: HTTPClient.Body? { get set } | ||
|
||
static func isSchemeSupported(scheme: String) -> Bool | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't love using a protocol existential here. I think the splitting of basic request types is a good idea, but I'd rather use an enumeration that we can switch over than the protocol existential.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It seems the only difference between implementations is how they handle scheme? Why not just add a
unix://
to a list of supported schemes?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
slightly different asserts in Request constructor
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not a fan. Do you think about if'ing in every
Request
property?I've rework it with enum: d3bbf37 let me know if that's something you love more @Lukasa 😅