Giter Club home page Giter Club logo

swift-nio-examples's Introduction

SwiftNIO Example Apps

The point of this repository is to be a collection of ready-to-use SwiftNIO example apps. The other apple/swift-nio repositories contain libraries which do sometimes contain example code but usually not whole applications.

The definition of app includes any sort of application, command line utilities, iOS Apps, macOS GUI applications or whatever you can think of.

Organisation

Each example application should be fully contained in its own sub-directory together with a README.md explaining what the application demonstrates. Each application must be buildable through either cd AppName && swift build or cd AppName && ./build.sh.

Like all other code in the SwiftNIO project, the license for all the code contained in this repository is the Apache License 2.0. See also LICENSE.txt.

Quality

Example applications must go through pre-commit code review like all other code in the SwiftNIO project. It is however acceptable to publish demo applications that only work for a subset of the supported platforms if that limitation is clearly documented in the project's README.md.

NIO versions

The main branch contains the examples for the SwiftNIO 2 family. For the examples working with NIO 1, please use the nio-1 branch.

swift-nio-examples's People

Contributors

allright avatar ankitspd avatar arjunsinghrana avatar basthomas avatar carolinacass avatar crontab avatar davidde94 avatar fabianfett avatar glbrntt avatar lukasa avatar maxdesiatov avatar nlevitt avatar nomo-nomad avatar oliverepper avatar pasisalenius avatar rnro avatar simonbohnen avatar tayloraswift avatar tomerd avatar trevorah avatar weissi avatar wplong11 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

swift-nio-examples's Issues

Example of JSON RPC using blocking semantics?

We have a code generator for Swift that is based on the JSON RPC example here. However, the asynchronous nature is causing maintainability headaches for us. For example, we need to make several JSON RPC calls to retrieve values from the other process, and we need to wait until all of the values have been successfully retrieved before we continue. Currently, the working solution for this produces an ugly pyramid-of-doom:

get(value: "1") {
  get(value: "2") {
    get(value: "3") {
       // etc. and then finally
      completion()
    }
  }
}

There are over a dozen values we need to get, so this is clearly not what we want. We really just want something like:

group = DispatchGroup()
for key in keys {
  group.enter()
  let future = channel.call(method: "GetValue": params: .list([.string(session), .string(key)]))
  future.whenSuccess { result in
    switch result {
      case let .success(response):
        let value = response.asString
        self.args[key] = value
      case .failure:
        break
    }
    group.leave()
  }
}
group.wait()
completion()

However, this just hangs. Trying to use group.notify(DispatchQueue.global()) { completion() } seemingly works but then the next RPC call fails:

Precondition failed: file /Users/.../.build/checkouts/swift-nio/Sources/NIO/ChannelPipeline.swift, line 158

The following PR in the swift-nio repo added convenience API for blocking semantics to Swift NIO: apple/swift-nio#1563

Could you provide an example of how Client.call(method:params) (https://github.com/apple/swift-nio-examples/blob/main/json-rpc/Sources/JsonRpc/Client.swift#L60) can be rewritten to use these blocking semantics such that RPC calls are essentially synchronous?

NIOSMTP: should implement escaping

Expected behavior

NIOSMTP's should escape things like names and the body of an email so you can send anything without errors.

Actual behavior

Nothing is escaped, for example putting an line just containing a full stop (.) in an email will cause an SMTP protocol error. The emails should be properly MIME encoded instead.

Steps to reproduce

Try to send an email with NIOSMTP containing a line with just a full stop.

http2-client should suppress uncleanShutdown errors

Expected behavior

Unclean TLS shutdown should be ignored when the request has been fully delivered.

Actual behavior

Unclean TLS shutdown is reported in the terminal.

Steps to reproduce

  1. Attempt to contact https://microsoft.com

Using JSONRPC codecs in another project

I would like to use the JSONRPC codecs in a project of mine.

While the json-rpc folder contains a Package.swift file, it is of no use since a Swift package seems to be defined by a repository where Package.swift is placed in the root.

Is there any other recommended way to use the JSONRPC code besides just copying it into my project?

My use case is only academic/experimental and I am aware that this repository only contains example code that should not be used without further review.

proper HTTP server example

we should have a short HTTP server example that does

  • SSL
  • HTTP/2
  • possibly websockets

and it should live in this repository so we can depend on the other NIO parts. This should supersede NIOHTTP1Server as the example we point people to.

http2-client fatally fails when connection is refused

Expected behavior

Error about connection being refused, no fatal error.

Actual behavior

ERROR: NIOConnectionError(host: "localhost", port: 443, dnsAError: nil, dnsAAAAError: nil, connectionErrors: [NIO.SingleConnectionFailure(target: [IPv6]localhost/::1:443, error: connection reset (error set): Connection refused (errno: 61)), NIO.SingleConnectionFailure(target: [IPv4]localhost/127.0.0.1:443, error: connection reset (error set): Connection refused (errno: 61))])
Fatal error: leaking promise created at (file: "/Users/lauri/Documents/swift-nio-examples/http2-client/Sources/http2-client/main.swift", line: 298): file /Users/lauri/Documents/swift-nio-examples/http2-client/Sources/http2-client/main.swift, line 298
zsh: illegal hardware instruction  swift run http2-client https://localhost/

Steps to reproduce

  1. Do not have any server running at localhost:443
  2. Run swift run http2-client https://localhost/

If possible, minimal yet complete reproducer code (or URL to code)

[anything to help us reproducing the issue]

version/commit hashes from all involved dependencies

61a502f

Swift & OS version (output of swift --version && uname -a)

Apple Swift version 5.3.2 (swiftlang-1200.0.45 clang-1200.0.32.28)
Target: x86_64-apple-darwin19.6.0
Darwin MiniII.lan 19.6.0 Darwin Kernel Version 19.6.0: Tue Jun 22 19:49:55 PDT 2021; root:xnu-6153.141.35~1/RELEASE_X86_64 x86_64

nio-connect-proxy fails to send error response

Expected behavior

On receiving a bad / unsupported request, return a 400 response

Actual behavior

It just hangs, no response, and leaves the socket open.

Steps to reproduce

  1. Start the proxy
  2. Try to fetch an http (not https) url through it
$ curl -gvsS --proxy localhost:8080 http://example.com/

If possible, minimal yet complete reproducer code (or URL to code)

version/commit hashes from all involved dependencies

  • swift-nio-examples 909a55e
  • swift-nio 2.18.0 120acb15c39aa3217e9888e515de160378fbcc1e
  • swift-log 1.2.0 74d7b91ceebc85daf387ebb206003f78813f71aa

Swift & OS version (output of swift --version && uname -a)

Apple Swift version 5.2.4 (swiftlang-1103.0.32.9 clang-1103.0.32.53)
Target: x86_64-apple-darwin19.5.0
Darwin Noahs-MacBook-Pro-16-inch-2019 19.5.0 Darwin Kernel Version 19.5.0: Tue May 26 20:41:44 PDT 2020; root:xnu-6153.121.2~2/RELEASE_X86_64 x86_64

build swift-nio-example failed get error, memory file not found

Expected behavior

[what you expected to happen]
build success

Actual behavior

[what actually happened]

Resolving https://github.com/apple/swift-nio at 2.18.0
In file included from /Users/aeris/hswork/http2/swift-nio-examples/http2-client/.build/checkouts/swift-nio-ssl/Sources/CNIOBoringSSL/ssl/tls_record.cc:109:
In file included from /Users/aeris/hswork/http2/swift-nio-examples/http2-client/.build/checkouts/swift-nio-ssl/Sources/CNIOBoringSSL/include/CNIOBoringSSL_ssl.h:145:
/Users/aeris/hswork/http2/swift-nio-examples/http2-client/.build/checkouts/swift-nio-ssl/Sources/CNIOBoringSSL/include/CNIOBoringSSL_base.h:478:10: fatal error: 'memory' file not found
#include <memory>
         ^~~~~~~~
In file included from /Users/aeris/hswork/http2/swift-nio-examples/http2-client/.build/checkouts/swift-nio-ssl/Sources/CNIOBoringSSL/ssl/tls13_enc.cc:15:
In file included from /Users/aeris/hswork/http2/swift-nio-examples/http2-client/.build/checkouts/swift-nio-ssl/Sources/CNIOBoringSSL/include/CNIOBoringSSL_ssl.h:145:
/Users/aeris/hswork/http2/swift-nio-examples/http2-client/.build/checkouts/swift-nio-ssl/Sources/CNIOBoringSSL/include/CNIOBoringSSL_base.h:478:10: fatal er


In file included from /Users/aeris/hswork/http2/swift-nio-examples/http2-client/.build/checkouts/swift-nio-ssl/Sources/CNIOBoringSSL/ssl/tls_method.cc:57:
In file included from /Users/aeris/hswork/http2/swift-nio-examples/http2-client/.build/checkouts/swift-nio-ssl/Sources/CNIOBoringSSL/include/CNIOBoringSSL_ssl.h:145:
/Users/aeris/hswork/http2/swift-nio-examples/http2-client/.build/checkouts/swift-nio-ssl/Sources/CNIOBoringSSL/include/CNIOBoringSSL_base.h:478:10: fatal error: 'memory' file not found
#include <memory>
         ^~~~~~~~
In file included from /Users/aeris/hswork/http2/swift-nio-examples/http2-client/.build/checkouts/swift-nio-ssl/Sources/CNIOBoringSSL/ssl/tls13_server.cc:15:
In file included from /Users/aeris/hswork/http2/swift-nio-examples/http2-client/.build/checkouts/swift-nio-ssl/Sources/CNIOBoringSSL/include/CNIOBoringSSL_ssl.h:145:


         ^~~~~~~~
1 error generated.
1 error generated.
[6/435] Compiling tls_method.cc

Steps to reproduce

  1. git clone https://github.com/apple/swift-nio-examples.git
  2. cd swift-nio-examples
  3. cd http2-client
  4. swift build

If possible, minimal yet complete reproducer code (or URL to code)

[anything to help us reproducing the issue]

version/commit hashes from all involved dependencies

[tag/commit hash]

Swift & OS version (output of swift --version && uname -a)

swift version: swift/5.2.4
macos:10.15.4

http2-client should use ALPNHandler

Expected behavior

Failure to negotiate HTTP/2 should either be reported, or tolerated.

Actual behavior

http2-client ignores the failure to negotiate HTTP/2 and just sends it anyway, leading to errors.

Steps to reproduce

  1. Attempt to reach https://amazon.com
  2. Observe errors reported.

TCPClient in json-rpc isn't thread-safe

public func connect(host: String, port: Int) -> EventLoopFuture<TCPClient> {
assert(.initializing == self.state)
let bootstrap = ClientBootstrap(group: self.group)
.channelOption(ChannelOptions.socket(SocketOptionLevel(SOL_SOCKET), SO_REUSEADDR), value: 1)
.channelInitializer { channel in
return channel.pipeline.addTimeoutHandlers(self.config.timeout)
.flatMap {
channel.pipeline.addFramingHandlers(framing: self.config.framing)
}.flatMap {
channel.pipeline.addHandlers([
CodableCodec<JSONResponse, JSONRequest>(),
Handler(),
])
}
}
self.state = .connecting("\(host):\(port)")
return bootstrap.connect(host: host, port: port).flatMap { channel in
self.channel = channel
self.state = .connected
return channel.eventLoop.makeSucceededFuture(self)
}
}
public func disconnect() -> EventLoopFuture<Void> {
if .connected != self.state {
return self.group.next().makeFailedFuture(ClientError.notReady)
}
guard let channel = self.channel else {
return self.group.next().makeFailedFuture(ClientError.notReady)
}
self.state = .disconnecting
channel.closeFuture.whenComplete { _ in
self.state = .disconnected
}
channel.close(promise: nil)
return channel.closeFuture
}
public func call(method: String, params: RPCObject) -> EventLoopFuture<Result> {

Thanks to @wlisac for the report.

At least TCPClient is very thread unsafe and really needs fixing. Without synchronisation, state is read/written to from different threads.

NIOSMTP should support STARTTLS

Right now, NIOTLS only supports two legacy/deprecated versions of SMTP:

  • plaintext: very bad
  • SMTPS (SMTP over TLS the whole time): good but deprecated

It should support STARTTLS too. That change won't be very hard but it will need to be implemented using swift-nio-ssl instead of Network.framework's TLS because Network.framework's TLS doesn't support STARTTLS.

HTTPS Connection hangs when using Connect-Proxy with Android Emulator

Hi, this week, I've encountered some strange issues when trying proxy the HTTPS connection from Android Emulator. I tried, but I haven't found an answer yet. I hope by opening this ticket here, someone can help me.

Thanks for your hard work on the SwiftNIO project ๐Ÿ™‡

Expected behavior

  • The HTTPS connection from Android Emulator should works fine.

Actual behavior

  • All connections, which are called by Android Emulator, hang forever until the timeout.
  • 8.8.8.8:853 is hang

Steps to reproduce

  1. Use the Connect-Proxy example
  2. Listen on 0.0.0.0 at port 8080
  3. Add some useful log into GlueHandler

CleanShot 2023-08-19 at 20 53 06@2x

  1. Start the main.swift
  2. Verify the connect-proxy is working fine โœ… : curl -v "https://httpbin.proxyman.app/get?id=123" --proxy localhost:8080

CleanShot 2023-08-19 at 20 54 27@2x

  1. Verify the console log: the GlueHandler is added and channedRead is called โœ…
โšก๏ธ [GlueHandler] handlerAdded
๐Ÿ” [GlueHandler] channelRead, data = \(data)
  1. Open Android Emulator -> Set Setting Proxy to current IP

CleanShot 2023-08-19 at 20 47 20@2x

  1. Open Google Chrome -> Visit any website
  2. Observe that there are a lot of waiting connections: The GlueHandler is added, but there is no readable data -> The socket hangs forever => โŒ ๐Ÿ› Bug here

CleanShot 2023-08-19 at 20 51 23@2x

๐Ÿ“ My investigation

  1. After setting the HTTP Proxy from Android Emulator, it seems the Android is using DNS over HTTPS (Private DNS is enabled)
  2. When open Google Chrome, visit any website -> Android makes a CONNECT request, without the Host Header.
CONNECT 8.8.8.8:853 HTTP/1.1
  1. connect-proxy returns HTTP/1.1 200 OK
  2. but for some reason, the client doesn't send any data. The socket just hangs.

I guess the connect-proxy doesn't support TCP yet, but if you don't mind, can you point out how to support it? I tried to add a new TCPHandler to read the data, but there is no readable data is called.

If possible, minimal yet complete reproducer code (or URL to code)

Video: https://drive.google.com/file/d/1ojOtRa-15N_pPklrApIFAAhX3xYfeQ2i/view?usp=sharing

version/commit hashes from all involved dependencies

The latest version of connect-proxy example.

Swift & OS version (output of swift --version && uname -a)

http2-client fatally fails with IP address URLs

Passing a URL with an IP address as an argument to http2-client results in a fatal error, because creating NIOSSLClientHandler is assumed never to fail.

Yes, I know this can be worked around by passing serverHostname: nil to the NIOSSLClientHandler constructor, but then SNI will be disabled altogether.

Even if URLs with IP addresses are not a typical use case with HTTPS, I think this example code should set an example on what to do with IP addresses, and not just crash.

Expected behavior

Error about failing to verify certificate, but no fatal error.

Actual behavior

Fatal error: 'try!' expression unexpectedly raised an error: NIOSSLExtraError.cannotUseIPAddressInSNI: IP addresses cannot validly be used for Server Name Indication, got 192.168.0.1: file http2_client/main.swift, line 305
zsh: illegal hardware instruction  swift run http2-client https://192.168.0.1/

Steps to reproduce

  1. Run % swift run http2-client https://192.168.0.1/ (doesn't matter if there's a server running at that IP or not)

If possible, minimal yet complete reproducer code (or URL to code)

[anything to help us reproducing the issue]

version/commit hashes from all involved dependencies

61a502f

Swift & OS version (output of swift --version && uname -a)

Apple Swift version 5.3.2 (swiftlang-1200.0.45 clang-1200.0.32.28)
Target: x86_64-apple-darwin19.6.0
Darwin MiniII.lan 19.6.0 Darwin Kernel Version 19.6.0: Tue Jun 22 19:49:55 PDT 2021; root:xnu-6153.141.35~1/RELEASE_X86_64 x86_64

connect-proxy example isn't working with DNS Over HTTPS

Expected behavior

  • Connect-Proxy example should work with DNS Over HTTPS -> Can access the Internet as usual

Actual behavior

  • Could not connect to certain domains
2020-12-08T10:18:44+0700 error com.apple.nio-connect-proxy.ConnectHandler : remoteAddress=Optional([IPv4]127.0.0.1/127.0.0.1:51759) localAddress=Optional([IPv4]127.0.0.1/127.0.0.1:9090) channel=ObjectIdentifier(0x000000010840c7a0) Connect failed: NIOConnectionError(host: "in.appcenter.ms", port: 443, dnsAError: Optional(NIO.SocketAddressError.unknown(host: "in.appcenter.ms", port: 443)), dnsAAAAError: Optional(NIO.SocketAddressError.unknown(host: "in.appcenter.ms", port: 443)), connectionErrors: [])

2020-12-08T10:18:44+0700 error com.apple.nio-connect-proxy.ConnectHandler : channel=ObjectIdentifier(0x0000000100c0b770) remoteAddress=Optional([IPv4]127.0.0.1/127.0.0.1:51760) localAddress=Optional([IPv4]127.0.0.1/127.0.0.1:9090) Connect failed: NIOConnectionError(host: "google.com", port: 443, dnsAError: Optional(NIO.SocketAddressError.unknown(host: "google.com", port: 443)), dnsAAAAError: Optional(NIO.SocketAddressError.unknown(host: "google.com", port: 443)), connectionErrors: [])

2020-12-08T10:18:44+0700 error com.apple.nio-connect-proxy.ConnectHandler : remoteAddress=Optional([IPv4]127.0.0.1/127.0.0.1:51855) localAddress=Optional([IPv4]127.0.0.1/127.0.0.1:9090) channel=ObjectIdentifier(0x000000010800a3a0) Connect failed: connectTimeout(NIO.TimeAmount(nanoseconds: 10000000000))
  • It happens 50-50 all the time. Sometimes I could connect, but sometimes I couldn't and get a bunch of errors.
  • If I delete the DNS Profile -> 100% it's working

Steps to reproduce

  1. Download DNS Profile at https://github.com/paulmillr/encrypted-dns
  2. Install cloudflare-https.mobileconfig on Big Sur macOS
  3. Go to System Preferrrence -> Profile and install it again
  4. Verify that you can open any websites from Safari and Google Chrome as usual`
  5. Set HTTP/HTTPS Proxy from Wifi -> Advanced -> Proxies to 9090
  6. Start connect-proxy at port 9090
  7. Quit Safari or Google Chrome if it's opening. Try to access some well-known websites, such as google.com, stackoverflow.com, ...

version/commit hashes from all involved dependencies

  • The lasted commit on the main branch (09044ff)

Swift & OS version (output of swift --version && uname -a)

Apple Swift version 5.3.1 (swiftlang-1200.0.41 clang-1200.0.32.8)
Target: x86_64-apple-darwin20.1.0
Darwin Nghias-MacBook-Pro.local 20.1.0 Darwin Kernel Version 20.1.0: Sat Oct 31 00:07:11 PDT 2020; root:xnu-7195.50.7~2/RELEASE_X86_64 x86_64

Thank Swift NIO team for developing a powerful tool ๐Ÿ‘

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.