Giter VIP home page Giter VIP logo

apns's Introduction

Vapor

Documentation Team Chat MIT License Continuous Integration Code Coverage Swift 5.7+ Mastodon


Vapor is an HTTP web framework for Swift. It provides a beautifully expressive and easy-to-use foundation for your next website, API, or cloud project.

Take a look at some of the awesome stuff created with Vapor.

💧 Community

Join the welcoming community of fellow Vapor developers on Discord.

🚀 Contributing

To contribute a feature or idea to Vapor, create an issue explaining your idea or bring it up on Discord.

If you find a bug, please create an issue.

If you find a security vulnerability, please contact [email protected] as soon as possible.

💛 Sponsors

Support Vapor's development by becoming a sponsor.

Broken Hands Emerge Tools Jari Donut Dane MacStadium

💚 Backers

Support Vapor's development by becoming a backer.

Moritz LangMaarten EngelsThomas KrajacicJesse TiptonSteve HumeMikkel UlstrupGeoffrey FosterPaul SchmiedmayerScott RobbinsSven A. SchmidtSpencer CurtisZach RausnitzTim „Timinator“ KretzschmarKlaasAndrew Edwards+Li, Inc.Stijn WillemsKyle NewsomeVia Aurelia SolutionsJakub KiermaszBrian DrellingMattes MohrJamieGalen RhodesLitmapsDavid RomanBrian StrobachKishikawa KatsumiAlex SherbakovSidetrackGreg KarpatiFrantišek MikšJeremy GreenwoodRay FixMićo MiloložaAlanJonas SannewaldTapEnvy.us, LLCJawadPARAIPAN SORINKalyn DavisYR ChenAarón Martínez Cuevas

apns's People

Contributors

0xtim avatar bennydebock avatar code28 avatar gerzer avatar gwynne avatar jaapwijnen avatar kylebrowning avatar mackoj avatar madsodgaard avatar mrwowander avatar pschmiedmayer avatar tanner0101 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

apns's Issues

Support for sending PushNotifications via ProxyServer

right now, APNSwiftConnection does not support to configure any Proxy-Server.

I would expect to consider the configuration from my configure.swift, e.g.:
app.http.client.configuration.proxy = .some(.server(host: "localhost", port: 3128))

Can't send "contentAvailable" on it's own

Describe the bug

Trying to send background notification, to make my app update when changes in the backend, makes it imperative that the app is updated.
it works perfectly when the payload has a alert, but without the alert and only '''hasContentAvailable''' the notification never reach the app.... not on sandbox at least

To Reproduce

create a payload that contains an alert

        let payload = APNSwiftPayload(alert:APNSwiftAlert(title:"You got new credit"),hasContentAvailable:true)
        let creditNotification = CreditUpdatedNotification(aps: payload)

and send it
then remove the alert and try to send that one

        let payload = APNSwiftPayload(hasContentAvailable:true)
        let creditNotification = CreditUpdatedNotification(aps: payload)

and send it. I don't get anything on my devices in the second one, but the first is fine

Steps to reproduce the behavior:

  1. create an backend app
  2. add the aps package
  3. create an endpoint or another tricker to send the APN
  4. have an app that registers for APNs and receives the apn
    • implement the application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any], fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void)
  5. try debug when sending with hasContentAvailable with and without the alert:

Expected behavior

I would expect the didReceiveremoteNotification to be called in both cases, as the hasContentAvailable is set to true. but it is only called when there is a alert with the payload.

Environment

  • Vapor Framework version: latest
  • Vapor Toolbox version: latest
  • OS version: Big Sur (updated)

using Ngrok as proxy pass when developing.

Jan 9

Describe the bug

Hi i had the push notification working well on the server. thou I noticed it stoped working

Since the update of jan 9 I have not been able to get a push from the server how ever I a am able to get a push from my Mac.

its the same code but for some reason it docent work.

I think the problem is in APNSwift 2.2.0 an above

Thank you in advanced, if you need more data im happy to help

Environment

Ubunto 18.04

Additional context

Add any other context about the problem here.

Doesn't work with certificates

I'm sending a push based on a PassKit update. According to the docs that Apple put here:

You use the same certificate and private key for sending push notifications as for signing passes

When I use this method

try app.apns.configuration = .init(privateKeyPath: "/Users/scott/bella/sign/passkey.pem", pemPath: "/Users/scott/bella/sign/passcertificate.pem", topic: "", environment: .sandbox)

to configure the app, it immediately throws an exception. If I step though it seems to fail when it makes the call to NIOSSLPrivateKey.

Seems like there might need to be a separate way to read the private key? The private key is an encrypted private key. The top of the file starts like so, for example:

Bag Attributes
friendlyName: Bella Sorelle Wallet Key
localKeyID: 2B 22 FA B4 33 8F 72 71 B4 F9 6B 42 E2 BD A5 35 19 B8 B9 B7
Key Attributes: <No Attributes>
-----BEGIN ENCRYPTED PRIVATE KEY-----

I know the files are "good" because I'm using them successfully to run the openssl smime command to sign the manifest.

Use Data, not ByteBuffer

Please use Data elements instead of the ByteBuffer that the NIO modules use. That's an implementation detail that should be hidden from us. Data is the generic 'opaque data type' that Swift developers are used to using.

A new connection to APN server created for each request.

Hey,
I've just been testing this out using the example from https://forums.swift.org/t/whats-new-in-vapor-4/31832, and I've been having issues having a persistent connection to the APN server.

For each request made the logs show it creates a connection, then successfully sends the push notification, then on the next request it repeats the process. My assumption is that it should reuse the same connection, and only reconnect if disconnected?
I'm using this example:

app.get("send-push") { req -> EventLoopFuture<HTTPStatus> in
    req.apns.send(
        .init(title: "Hello", subtitle: "This is a test from vapor/apns"),
        to: "..."
    ).map { .ok }
}

APNS Version: 1.0.0-beta.2.2
APNSwift Version: 1.7.0
Vapor Version: 4.0.0-beta.3

Logs:

[ INFO ] GET /send-push
[ DEBUG ] Connection - starting ["origin": APNSwift] (APNSwift/APNSwiftConnection.swift:90)
[ DEBUG ] Connection - token factory setup ["origin": APNSwift] (APNSwift/APNSwiftConnection.swift:106)
[ DEBUG ] Creating a new APNS token ["origin": APNSwift] (APNSwift/APNSwiftBearerTokenFactory.swift:28)
[ DEBUG ] Connection - token factory created ["origin": APNSwift] (APNSwift/APNSwiftConnection.swift:110)
[ DEBUG ] Connection - bringing up ["origin": APNSwift] (APNSwift/APNSwiftConnection.swift:119)
[ INFO ] Connection - up ["origin": APNSwift] (APNSwift/APNSwiftConnection.swift:143)
[ DEBUG ] Send - starting up ["origin": APNSwift] (APNSwift/APNSwiftConnection.swift:185)
[ INFO ] Send - sending ["origin": APNSwift] (APNSwift/APNSwiftConnection.swift:204)
[ DEBUG ] Request - building ["origin": APNSwift] (APNSwift/APNSwiftRequestEncoder.swift:55)
[ DEBUG ] Response - received ["origin": APNSwift] (APNSwift/APNSwiftStreamHandler.swift:35)
[ INFO ] Response - successful ["origin": APNSwift] (APNSwift/APNSwiftStreamHandler.swift:52)
[ INFO ] GET /send-push
[ DEBUG ] Connection - starting ["origin": APNSwift] (APNSwift/APNSwiftConnection.swift:90)
[ DEBUG ] Connection - token factory setup ["origin": APNSwift] (APNSwift/APNSwiftConnection.swift:106)
[ DEBUG ] Creating a new APNS token ["origin": APNSwift] (APNSwift/APNSwiftBearerTokenFactory.swift:28)
[ DEBUG ] Connection - token factory created ["origin": APNSwift] (APNSwift/APNSwiftConnection.swift:110)
[ DEBUG ] Connection - bringing up ["origin": APNSwift] (APNSwift/APNSwiftConnection.swift:119)
[ INFO ] Connection - up ["origin": APNSwift] (APNSwift/APNSwiftConnection.swift:143)
[ DEBUG ] Send - starting up ["origin": APNSwift] (APNSwift/APNSwiftConnection.swift:185)
[ INFO ] Send - sending ["origin": APNSwift] (APNSwift/APNSwiftConnection.swift:204)
[ DEBUG ] Request - building ["origin": APNSwift] (APNSwift/APNSwiftRequestEncoder.swift:55)
[ DEBUG ] Response - received ["origin": APNSwift] (APNSwift/APNSwiftStreamHandler.swift:35)
[ INFO ] Response - successful ["origin": APNSwift] (APNSwift/APNSwiftStreamHandler.swift:52)
....

Connection timed out deadlock issue

Describe the bug

We are trying to send push notifications with APNS from a queues job. However, we are running into issues with the following error:

Connection request timed out. This might indicate a connection deadlock in your application. If you're running long running requests, consider increasing your connection timeout. (AsyncKit/ConnectionPool/EventLoopConnectionPool.swift:213)


After which all other attempts to send another push notification returns the same error. It is almost as if a pipe is clocked up by a request that never completes and releases the connection.

Example

In my example I am dequeuing two jobs Job A and Job B. Job A is sending a push notification to a token and Job B is sending a push notification.

Job A is ran first:

2021-01-25T14:11:17.210+01:00	[ codes.vapor.application ] [ DEBUG ] Send - starting up (APNSwift/APNSwiftConnection.swift:175)
2021-01-25T14:11:17.210+01:00	[ codes.vapor.application ] [ INFO ] Send - sending (APNSwift/APNSwiftConnection.swift:206)
2021-01-25T14:11:17.211+01:00	[ codes.vapor.application ] [ DEBUG ] Request - building (APNSwift/APNSwiftRequestEncoder.swift:70)
2021-01-25T14:11:17.211+01:00	[ codes.vapor.application ] [ TRACE ] Request - built (APNSwift/APNSwiftRequestEncoder.swift:103)
2021-01-25T14:11:17.211+01:00	[ codes.vapor.application ] [ TRACE ] Request - sent (APNSwift/APNSwiftRequestEncoder.swift:107)

as we can see the request is sent.

Now comes Job B right after to run. The environment has 1 eventloop, therefore 1 connection in the pool used by APNS. Therefor this request is put on the waitlist for the other one to finish.

2021-01-25T14:11:17.870+01:00	[ codes.vapor.application ] [ DEBUG ] Connection pool exhausted on this event loop, adding request to waitlist (AsyncKit/ConnectionPool/EventLoopConnectionPool.swift:207)


Exactly 10 seconds later (the standard connectionPoolTimeout) this error occurs:

2021-01-25T14:11:27.871+01:00	[ codes.vapor.application ] [ ERROR ] Connection request timed out. This might indicate a connection deadlock in your application. If you're running long running requests, consider increasing your connection timeout. (AsyncKit/ConnectionPool/EventLoopConnectionPool.swift:213)


All subsequent attempts to send a notification returns the same error, it is as if Job A is still using the connection, so others can't.

Potential fixes

I can't think of any other solution than to increase the connection pool timeout, but still 10 seconds is a long time. I don't understand why the response is not returned within that period, even if it's a failure. I would also expect the library to release the connection if it timed out.

Note: This error is not always reproducible, but it happens quite often (daily) and it requires us to restart our servers (to unblock the connection), so it's kind of a big issue.

Unable to Instantiate APNSClientConfiguration with tls certificate as in doc

According to documentation https://docs.vapor.codes/advanced/apns/#configuration
image

But this cause errors in Xcode
image

And there is only one function named tls in APNSClientConfiguration struct, which looks like this:

public static func tls(
    privateKey: NIOSSLPrivateKeySource,
    certificateChain: [NIOSSLCertificateSource]
) -> Self {
    Self(method: .tls(privateKey: privateKey, certificateChain: certificateChain))
}

Is the documentation outdated?

Connection deadlock after random time

I'm using APNS with TLS-based Auth, sending pushes every several minutes to only one device.
But I notice that, often, after several hours(Time is completely random), The apns connection will be completely jammed, throwing the error below every time:

[ ERROR ] Connection request timed out. This might indicate a connection deadlock in your application.

After some investigation, I found there is a closed issue on APNSwift swift-server-community/APNSwift#90 indicating such error might be caused by a wrong implementation for the reconnection part, and the error message is imported into AsyncKit lately vapor/async-kit@7457413 .

Cannot find 'APNSAlertNotification' in scope

Describe the bug

I'm importing APNS and VaporAPNS and when I want to use the framework I get this error Cannot find 'APNSAlertNotification' in scope I'm using the resources of the documentation
https://docs.vapor.codes/advanced/apns/

To Reproduce

Package definition

// swift-tools-version:5.9
import PackageDescription

let package = Package(
    name: "hello",
    platforms: [
       .macOS(.v13)
    ],
    dependencies: [
        // 💧 A server-side Swift web framework.
        .package(url: "https://github.com/vapor/vapor.git", from: "4.83.1"),
        .package(url: "https://github.com/vapor/apns.git", from: "4.0.0"),
    ],
    targets: [
        .executableTarget(
            name: "App",
            dependencies: [
                .product(name: "Vapor", package: "vapor"),
                .product(name: "VaporAPNS", package: "apns"),
            ]
        ),
        .testTarget(name: "AppTests", dependencies: [
            .target(name: "App"),
            .product(name: "XCTVapor", package: "vapor"),

            // Workaround for https://github.com/apple/swift-package-manager/issues/6940
            .product(name: "Vapor", package: "vapor"),
            .product(name: "VaporAPNS", package: "apns"),
        ])
    ]
)

Where I'm using it

import APNS
import VaporAPNS

func routes(_ app: Application) throws {
    app.get("hello") { req async -> String in
        // Custom Codable Payload
        struct Payload: Codable {
            let acme1: String
            let acme2: Int
        }
        // Create push notification Alert
        let dt = "70075697aa918ebddd64efb165f5b9cb92ce095f1c4c76d995b384c623a258bb"
        let payload = Payload(acme1: "hey", acme2: 2)
        let alert = APNSAlertNotification(
            alert: .init(
                title: .raw("Hello"),
                subtitle: .raw("This is a test from vapor/apns")
            ),
            expiration: .immediately,
            priority: .immediately,
            topic: "my topic",
            payload: payload
        )
        // Send the notification
        try! await req.apns.client.sendAlertNotification(
            alert,
            deviceToken: dt,
            deadline: .distantFuture
        )
        
        
        return "Hello, world!"
    }
}

Errors that xcode throws

Cannot find 'APNSAlertNotification' in scope
Cannot infer contextual base in reference to member 'init'
Cannot infer contextual base in reference to member 'raw'
Cannot infer contextual base in reference to member 'raw'
Cannot infer contextual base in reference to member 'immediately'
Cannot infer contextual base in reference to member 'immediately'

Steps to reproduce the behavior:

  1. Add package with configuration '...'
  2. Send request with options '...'
  3. See error

Environment

  • Vapor Framework version: 4.86.2
  • Vapor Toolbox version: 18.7.4
  • OS version: 14.1.1
  • Xcode: 15.0.1

Mock client for testing

Please add a test configuration that will store messages in memory so that the sent messages can be inspected within a test case.

APNS package not found

Describe the bug

When I tried to use the package from a clean project I get this error
product 'APNS' required by package 'hello' target 'AppTests' not found in package 'apns'.

To Reproduce

I am using steam project generator 4.83.1, just use apns package

// swift-tools-version:5.9
import PackageDescription

let package = Package(
    name: "hello",
    platforms: [
       .macOS(.v13)
    ],
    dependencies: [
        // 💧 A server-side Swift web framework.
        .package(url: "https://github.com/vapor/vapor.git", from: "4.83.1"),
        .package(url: "https://github.com/vapor/apns.git", from: "4.0.0"),
    ],
    targets: [
        .executableTarget(
            name: "App",
            dependencies: [
                .product(name: "Vapor", package: "vapor"),
                .product(name: "APNS", package: "apns"),
            ]
        ),
        .testTarget(name: "AppTests", dependencies: [
            .target(name: "App"),
            .product(name: "XCTVapor", package: "vapor"),

            // Workaround for https://github.com/apple/swift-package-manager/issues/6940
            .product(name: "Vapor", package: "vapor"),
            .product(name: "APNS", package: "apns"),
        ])
    ]
)

Expected behavior

A clear and concise description of what you expected to happen.

Environment

  • Vapor Framework version: 4.86.2
  • Vapor Toolbox version: 18.7.4
  • OS version: macOS 14.1.1

The operation could not be completed. (APNSCore.APNSError error 1.)

The given error

The operation could not be completed. (APNSCore.APNSError error 1.)

Usage

I register users in my application and send push notifications. I often encounter the error mentioned in the title. For example, I have 30 users, and when looping through them within a 'for' loop, I encounter an error while sending an APNS push notification to the 25th user. I haven't been able to resolve it yet.

To Reproduce

    try await req.apns.client.sendAlertNotification(
                                        .init(
                                            alert: .init(
                                                title: .raw("Earthquake Alert"),
                                                subtitle: .raw("Magnitude \(quake.magnitude.fraction(minDigits: 1, maxDigits: 1))"),
                                                body: .raw("There is an earthquake occurring near \(quake.place). Depth \(quake.depth.fraction(minDigits: 1, maxDigits: 1)) km")
                                            ),
                                            expiration: .immediately,
                                            priority: .immediately,
                                            topic: "com.metinatalay.earthquake",
                                            payload: Payload(acme1: "", acme2: 2)
                                        ),
                                        deviceToken: "5d089ab68c40e5d5a5d16a0b01ce39cccff06040b6405f3a84ef45e73712a401"
                                    )

Expected behavior

Typically, one user is getting stuck; I am waiting for push notifications to be sent to all users

Environment

  • Vapor Framework version: 5.0.2
  • Vapor Toolbox version:
  • OS version: 17.1

Bundle GeoTrust Global CA certificate

Describe the bug

APNs is still using the GeoTrust Global CA, which by default isn't trusted on Ubuntu. Apple is replacing the certificate they use on March 29th, 2021, but until then, would it be possible to include the certificate in this library?

More info here.

To Reproduce

  • Send a push notification on Ubuntu, using Heroku for instance.
  • An error occurs.

Expected behaviour

  • The push notification should send successfully.

Environment

  • Heroku Stack: heroku-18
  • Vapor 4

Update to 4.0.0-beta.2 not working

Describe the bug

Update from 3.0.0 to 4.0.0-beta.2 ist not working for me.
As soon as I update the packe I get this error:

multiple products named 'APNS' in: 'apns', 'apnswift'
multiple targets named 'APNS' in: 'apns', 'apnswift'; consider using the moduleAliases parameter in manifest to provide unique names

The apns Package is the only apns package in my project...

To Reproduce

Add Version 3.0.0 to a package:
.package(url: "https://github.com/vapor/apns.git", from: "3.0.0")

After this update to 4.0.0:
.package(url: "https://github.com/vapor/apns.git", from: "4.0.0-beta.2"),

Expected behavior

Project builds

Environment

  • Vapor Framework version: 4.67.5
  • Vapor Toolbox version:
  • OS version: MacOS 13.2

Allow swapping of configurations

Please provide a way that a single server app can support both the normal app's push notification (i.e. via the p8) and also passkit notifications (i.e. via the PEM files).

Right now we can't swap between configurations, to the best of my knowledge, because one thread might set it to config A, then another thread sets it to B, and then thread A tries to do the push and fails.

Tag a new relaease?

Maybe we could tag a new release with

.package(name: "vapor", url: "https://github.com/vapor/vapor.git", from: "4.0.0")

so that project using this package do not have to pinning to a rc version of vapor.

Feature Request: How to register the APNSClient with Application?

Describe the bug

What's the best way to set the app.apns.client? I found myself using the repository pattern to try to inject a different APNS service implementation but I noticed the APNSwift comes with app.apns.client, which reminded me of how I previously implemented an aws integration that looked like this:

app.aws.client = AWSClient(httpClientProvider: .shared(app.http.client.shared))

I'm trying to achieve the same but app.apns.client is read only, can we documentation around it ?

Expected behavior

apns.apns.client = MyAPNSCustomClient....

in my AWS Application Extension I have the following:

public var client: AWSClient {
            get {
                guard let client = self.application.storage[ClientKey.self] else {
                    fatalError("AWSClient not setup. Use application.aws.client = ...")
                }
                return client
            }
            nonmutating set { self.application.storage.set(ClientKey.self, to: newValue) {
                    try $0.syncShutdown()
                }
            }
        }

Environment

  • APNS version: 4.0.0-beta.1

Additional context

Add any other context about the problem here.

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.