esl / MongoosePush

MongoosePush is a simple Elixir RESTful service allowing to send push notification via FCM and/or APNS.
Apache License 2.0
109 stars 24 forks source link

How to change the endpoint correctly? #42

Closed izigibran closed 7 years ago

izigibran commented 7 years ago

I have tried both dockerized and build locally with no success:

docker run -p 8443:8443 -v pwd/priv:/opt/app/priv -e PUSH_HTTPS_CERTFILE="/opt/app/priv/ssl/rest_cert.pem" -e PUSH_HTTPS_KEYFILE="/opt/app/priv/ssl/rest_key.pem" -e PUSH_APNS_PROD_CERT="/opt/app/priv/apns/prod.pem" -e PUSH_APNS_PROD_KEY="/opt/app/priv/apns/apns-pro-key-noenc.pem" -e PUSH_APNS_DEV_CERT="/opt/app/priv/apns/dev.pem" -e PUSH_APNS_DEV_KEY="/opt/app/priv/apns/apns-dev-key-noenc.pem" -e PUSH_APNS_DEV_ENDPOINT="gateway.sandbox.push.apple.com" -e PUSH_APNS_PROD_ENDPOINT="gateway.push.apple.com" -it --rm mongooseim/mongoose-push:latest

=SUPERVISOR REPORT==== 12-Sep-2017::13:45:20 ===
     Supervisor: {local,'Elixir.MongoosePush.Supervisor'}
     Context:    child_terminated
     Reason:     {bad_return_value,{stop,{error,invalid_config}}}
     Offender:   [{pid,<0.1352.0>},
                  {id,apns_prod_1},
                  {mfargs,
                      {'Elixir.Pigeon.APNSWorker',start_link,
                          [#{cert => nil,certfile => nil,
                             development_endpoint =>
                                 <<"api.development.push.apple.com">>,
                             key => nil,keyfile => nil,mode => prod,
                             name => apns_prod_1,port => 443,
                             production_endpoint =>
                                 <<"gateway.push.apple.com">>,
                             use_2197 => false}]}},
                  {restart_type,permanent},
                  {shutdown,5000},
                  {child_type,worker}]

13:45:20.073 [error] gen_server apns_prod_1 terminated with reason: bad return value: {stop,{error,invalid_config}}
13:45:20.073 [error] CRASH REPORT Process apns_prod_1 with 0 neighbours exited with reason: bad return value: {stop,{error,invalid_config}} in gen_server:terminate/7 line 812
13:45:20.074 [error] Supervisor 'Elixir.MongoosePush.Supervisor' had child apns_prod_1 started with 'Elixir.Pigeon.APNSWorker':start_link(#{cert => nil,certfile => nil,development_endpoint => <<"api.development.push.apple.com">>,key => nil,...}) at <0.1352.0> exit with reason bad return value: {stop,{error,invalid_config}} in context child_terminated

Also building locally

MIX_ENV=prod mix do docker.build, docker.release

config/dev.exs

config :mongoose_push, apns: [ dev: [ endpoint: "gateway.sandbox.push.apple.com", cert: "priv/apns/dev.pem", key: "priv/apns/apns-dev-key-noenc.pem", mode: :dev, use_2197: true, pool_size: 5 ], prod: [ endpoint: "gateway.push.apple.com", cert: "priv/apns/prod.pem", key: "priv/apns/apns-pro-key-noenc.pem", mode: :prod, use_2197: false, pool_size: 5 ] ]

config/prod.exs

config :mongoose_push, apns: [ dev: [ endpoint: {:system, :string, "PUSH_APNS_DEV_ENDPOINT", "gateway.sandbox.push.apple.com"}, cert: {:system, :string, "PUSH_APNS_DEV_CERT", "priv/apns/dev.pem"}, key: {:system, :string, "PUSH_APNS_DEV_KEY", "priv/apns/apns-dev-key-noenc.pem"}, mode: :dev, use_2197: {:system, :boolean, "PUSH_APNS_DEV_USE_2197", false}, pool_size: {:system, :integer, "PUSH_APNS_DEV_POOL_SIZE", 5}, default_topic: {:system, :string, "PUSH_APNS_DEV_DEFAULT_TOPIC", nil} ], prod: [ endpoint: {:system, :string, "PUSH_APNS_PROD_ENDPOINT", "gateway.push.apple.com"}, cert: {:system, :string, "PUSH_APNS_PROD_CERT", "priv/apns/prod.pem"}, key: {:system, :string, "PUSH_APNS_PROD_KEY", "priv/apns/apns-pro-key-noenc.pem"}, mode: :prod, use_2197: {:system, :boolean, "PUSH_APNS_PROD_USE_2197", false}, pool_size: {:system, :integer, "PUSH_APNS_PROD_POOL_SIZE", 5}, default_topic: {:system, :string, "PUSH_APNS_PROD_DEFAULT_TOPIC", nil} ] ]

rslota commented 7 years ago

Hi @izigibran ,

The error message states that certificates you provide cannot be located. Could you attach the result of running tree `pwd`/priv in the directory from which you run the docker container? If you don't have tree, please use ls -l `pwd`/priv and ls -l `pwd`/priv/apns.

izigibran commented 7 years ago
$ ls -l `pwd`/priv/apns
total 136
-rw-r--r--  1 user  staff  1675 Sep 11 16:03 apns-dev-key-noenc.pem
-rw-r--r--  1 user  staff  1910 Jul  6 16:39 apns-dev-key.pem
-rw-r--r--  1 user  staff  3927 Sep 11 16:03 apns-dev.pem
-rw-r--r--  1 user  staff  1675 Sep 11 16:04 apns-pro-key-noenc.pem
-rw-r--r--  1 user  staff  1908 Jul  6 16:39 apns-pro-key.pem
-rw-r--r--  1 user  staff  3870 Sep 11 16:04 apns-pro.pem
-rw-r--r--  1 user  staff  1623 Jul  6 16:39 dev.cer
-rw-r--r--  1 user  staff  3405 Jul  6 16:39 dev.p12
-rw-r--r--  1 user  staff  2252 Jul  6 16:39 dev.pem
-rw-r--r--  1 user  staff  1135 Sep 11 16:12 dev_cert.pem
-rw-r--r--  1 user  staff  1679 Sep 11 16:12 dev_key.pem
-rw-r--r--  1 user  staff  1581 Jul  6 16:39 prod.cer
-rw-r--r--  1 user  staff  3345 Jul  6 16:39 prod.p12
-rw-r--r--  1 user  staff  2195 Jul  6 16:39 prod.pem
-rw-r--r--  1 user  staff  1354 Sep 11 16:12 prod_cert.pem
-rw-r--r--  1 user  staff  1675 Sep 11 16:12 prod_key.pem
izigibran commented 7 years ago
ls -l `pwd`/priv
total 0
drwxr-xr-x  19 user  staff  646 Sep 11 16:12 apns
drwxr-xr-x   6 user  staff  204 Sep  8 14:37 ssl
izigibran commented 7 years ago

@rslota Also please note that I am using APNS old version gateway.sandbox.push.apple.com:2195 so I want to be able to change the port as well. The documentation does not tell me anything.

Building locally I was able to hard code the configs on

deps/pigeon/lib/pigeon/apns_config.ex

     production_endpoint: config[:production_endpoint] ||  "gateway.sandbox.push.apple.com",
      development_endpoint: config[:development_endpoint] ||  "gateway.sandbox.push.apple.com",
      port: config[:port] ||  2195, 

But I do not think this should be the way. I should be able to change the version api as well because I think the default is V2?

11:38:43.842 [debug] POST /v2/notification/7B5FE70FD2D0ADC97629E63D64E15F8CE08DAB48D8F6CEDF85DE3464E5FF0FC9

11:38:43.843 [info]  Reconnecting to push service provider before request
11:38:43.843 [debug] Supervisor inet_gethost_native_sup started undefined at pid <0.1733.0>
11:38:43.843 [debug] Supervisor kernel_safe_sup started inet_gethost_native:start_link() at pid <0.1732.0>
11:38:44.082 [debug] Spawning ack timeout alarm clock: <0.1731.0> + {#Ref<0.2044486086.4287102979.126735>,{settings,4096,1,unlimited,65535,16384,unlimited}}
11:38:44.082 [debug] NewStream {active_stream,1,<0.1736.0>,<0.1703.0>,65535,65535,undefined,false}
11:38:44.082 [debug] [client] added stream #1 to {stream_set,client,{peer_subset,unlimited,1,0,3,[{active_stream,1,<0.1736.0>,<0.1703.0>,65535,65535,undefined,false}]},{peer_subset,unlimited,0,0,2,[]}}
11:38:44.082 [debug] [client] {send headers, 1, [{<<":method">>,<<"POST">>},{<<":path">>,<<"/3/device/7B5FE70FD2D0ADC97629E63D64E15F8CE08DAB48D8F6CEDF85DE3464E5FF0FC9">>},{<<":scheme">>,<<"https">>},{<<":authority">>,<<"gateway.sandbox.push.apple.com">>},{<<"content-length">>,<<"89">>},{<<"content-type">>,<<"application/json">>},{<<"accept">>,<<"application/json">>},{<<"apns-topic">>,<<"some_apns_topic">>}]}
11:38:44.083 [debug] [client] Send Body Stream 1

nil
iex(mongoose_push@127.0.0.1)4> 
rslota commented 7 years ago

Well, I cannot see the issue with the certs. I could look into it tomorrow but I don't think there is a need for that since you need the old APNS endpoint. I'm sorry but MongoosePush does not support the old APNS API. It's obsolete and not recommended by Apple. You cannot just change port number and hostname, since the old APNS is using a custom binary protocol while the new one is based on text protocol - HTTP/2. There is literally no single common thing about those two API versions, so we decided that we are not gonna support the obsolete one.

izigibran commented 7 years ago

@rslota, understand, I just learnt that I can still use the new protocol with my current certificates as this works

curl -v -d '{"aps":{"alert":"Test Push","sound":"default"}}' --cert dev.pem --key apns-dev-key-noenc.pem -H "apns-topic: mybundle.com" --http2 https://api.development.push.apple.com/3/device/7B5FE70FD2D0ADC97629E63D64E15F8CE08DAB48D8F6CEDF85DE3464E5FF0FC9

but I am still back to the same issue cant read the certificates or topics when building

izigibran commented 7 years ago

$ MIX_ENV=dev mix do deps.get, compile, certs.dev, release _build/dev/rel/mongoose_push/bin/mongoose_push console Erlang/OTP 20 [erts-9.0.4] [source] [64-bit] [smp:8:8] [ds:8:8:10] [async-threads:10] [hipe] [kernel-poll:false] [dtrace]

15:04:09.531 [info] Setup running ...

15:04:09.532 [info] Directories verified. Res = :ok

15:04:09.532 [info] Setup finished processing hooks (Mode=:normal)...

15:04:09.535 [info] Starting Elixir.MongoosePush.Router with Cowboy on https://127.0.0.1:8443 15:04:09.520 [error] Supervisor 'Elixir.Logger.Supervisor' had child 'Elixir.Logger.ErrorHandler' started with 'Elixir.Logger.Watcher':start_link({error_logger,'Elixir.Logger.ErrorHandler',{true,false,500}}) at <0.1428.0> exit with reason normal in context child_terminated 15:04:09.530 [info] Application lager started on node 'mongoose_push@127.0.0.1' 15:04:09.530 [info] Application asn1 started on node 'mongoose_push@127.0.0.1' 15:04:09.530 [info] Application crypto started on node 'mongoose_push@127.0.0.1' 15:04:09.530 [info] Application public_key started on node 'mongoose_push@127.0.0.1' 15:04:09.530 [info] Application ssl started on node 'mongoose_push@127.0.0.1' 15:04:09.530 [info] Application chatterbox started on node 'mongoose_push@127.0.0.1' 15:04:09.530 [info] Application metrics started on node 'mongoose_push@127.0.0.1' 15:04:09.530 [info] Application ssl_verify_fun started on node 'mongoose_push@127.0.0.1' 15:04:09.530 [info] Application certifi started on node 'mongoose_push@127.0.0.1' 15:04:09.530 [info] Application mimerl started on node 'mongoose_push@127.0.0.1' 15:04:09.531 [info] Application unicode_util_compat started on node 'mongoose_push@127.0.0.1' 15:04:09.531 [info] Application idna started on node 'mongoose_push@127.0.0.1' 15:04:09.531 [info] Application hackney started on node 'mongoose_push@127.0.0.1' 15:04:09.531 [info] Application httpoison started on node 'mongoose_push@127.0.0.1' 15:04:09.531 [info] Application pigeon started on node 'mongoose_push@127.0.0.1' 15:04:09.531 [info] Application pobox started on node 'mongoose_push@127.0.0.1' 15:04:09.531 [info] Setup running ... 15:04:09.532 [info] Directories verified. Res = ok 15:04:09.532 [info] Setup finished processing hooks (Mode=normal)... 15:04:09.532 [info] Application setup started on node 'mongoose_push@127.0.0.1' 15:04:09.533 [info] Starting reporters with [{reporters,[{exometer_report_tty,[]}]}] 15:04:09.533 [info] exometer_report_tty([]): Starting 15:04:09.533 [info] Application exometer_core started on node 'mongoose_push@127.0.0.1' 15:04:09.534 [info] Application elixometer started on node 'mongoose_push@127.0.0.1' 15:04:09.534 [info] Application exometer started on node 'mongoose_push@127.0.0.1' 15:04:09.534 [info] Application mime started on node 'mongoose_push@127.0.0.1' 15:04:09.534 [info] Application plug started on node 'mongoose_push@127.0.0.1'

15:04:09.550 [warn] Unable to extract APNS topic from the dev certificate due to: :undef 15:04:09.552 [warn] Unable to extract APNS topic from the prod certificate due to: :undef

Interactive Elixir (1.5.1) - press Ctrl+C to exit (type h() ENTER for help) iex(mongoose_push@127.0.0.1)1> 15:04:10.014 [warning] lager_error_logger_h dropped 58 messages in the last second that exceeded the limit of 50 messages/sec 15:04:10.020 [debug] Lager installed handler lager_backend_throttle into lager_event

nil iex(mongoose_push@127.0.0.1)2> nil

rslota commented 7 years ago

Can you please provide details on which operating system and what docker release / type you use? Tomorrow I'll try to prepare some debug command you could run to give me more informations.

izigibran commented 7 years ago

Ok I made it work but there are definitely some issues when building the project. On the first attempt running MIX_ENV=dev mix do deps.get, compile, certs.dev, release I get the following warning

warning: function :"APNS-Topics".decode/2 is undefined (module :"APNS-Topics" is not available)
  lib/mongoose_push/service/apns/certificate.ex:31

building again would actually fix it

17:09:35.391 [debug] Successfully extracted default APNS topic: mybundle.com
17:09:35.394 [debug] Successfully extracted default APNS topic: mybundle.com

Also, I would assume running MIX_ENV=dev mix do deps.get, compile, certs.dev, release would take the config/dev.exs which it doesn't and it always will point to production endpoint (so I had to hardcode the string and configs )

izigibran commented 7 years ago

I am using docker for mac

docker -v
Docker version 17.06.2-ce, build cec0b72

Mac Sierra
10.12.5
rslota commented 7 years ago

warning: function :"APNS-Topics".decode/2 is undefined (module :"APNS-Topics" is not available) lib/mongoose_push/service/apns/certificate.ex:31

This is actually kind of expected. The 'APNS-Topics' module is an pure-erlang one, but the Erlang compiler runs after Elixir (it just has to). Therefore Elixir's compiler warns that the module in not there. But the module is eventually compiled, a moment after that, so it should be available on runtime. The second compilation doesn't generate this warning, because, well, the previous compilation already generated the module, so the order of compiler doesn't matter the second time.

Also, I would assume running MIX_ENV=dev mix do deps.get, compile, certs.dev, release would take the config/dev.exs which it doesn't and it always will point to production endpoint (so I had to hardcode the string and configs )

Are you 100% sure? I just run this exact command (copy-paste from you post) and the file _build/dev/rel/mongoose_push/releases/0.1.0/sys.config is indeed generated from config/dev.exs. Can you double check on that?

izigibran commented 7 years ago

MIX_ENV=dev mix do deps.get, compile, certs.dev, release Generates this

[{sasl,[{errlog_type,error}]},
 {exometer_core,[{report,[{reporters,[{exometer_report_tty,[]}]}]}]},
 {elixometer,
     [{reporter,exometer_report_tty},
      {env,dev},
      {metric_prefix,<<"mongoose_push">>}]},
 {mongoose_push,
     [{loglevel,debug},
      {apns,
          [{dev,
               [{cert,<<"priv/apns/dev.pem">>},
                {key,<<"priv/apns/apns-dev-key-noenc.pem">>},
                {mode,dev},
                {use_2197,true},
                {pool_size,5}]},
           {prod,
               [{cert,<<"priv/apns/prod.pem">>},
                {key,<<"priv/apns/apns-pro-key-noenc.pem">>},
                {mode,prod},
                {use_2197,false},
                {pool_size,5}]}]}]},
 {maru,
     [{'Elixir.MongoosePush.Router',
          [{versioning,[{using,path}]},
           {https,
               [{bind_addr,<<"127.0.0.1">>},
                {port,8443},
                {keyfile,<<"priv/ssl/rest_key.pem">>},
                {certfile,<<"priv/ssl/rest_cert.pem">>},
                {otp_app,mongoose_push}]}]},
      {test,false}]}].

However the request is sent toapi.push.apple.com not api.development.push.apple.com

iex(mongoose_push@127.0.0.1)2> 
17:44:37.477 [debug] POST /v2/notification/7B5FE70FD2D0ADC97629E63D64E15F8CE08DAB48D8F6CEDF85DE3464E5FF0FC9

17:44:37.477 [info]  Reconnecting to push service provider before request
17:44:37.477 [debug] Supervisor inet_gethost_native_sup started undefined at pid <0.1732.0>
17:44:37.477 [debug] Supervisor kernel_safe_sup started inet_gethost_native:start_link() at pid <0.1731.0>
17:44:37.843 [debug] Spawning ack timeout alarm clock: <0.1730.0> + {#Ref<0.304219397.4075028484.183256>,{settings,4096,1,unlimited,65535,16384,unlimited}}
17:44:37.844 [debug] NewStream {active_stream,1,<0.1735.0>,<0.1703.0>,65535,65535,undefined,false}
17:44:37.844 [debug] [client] added stream #1 to {stream_set,client,{peer_subset,unlimited,1,0,3,[{active_stream,1,<0.1735.0>,<0.1703.0>,65535,65535,undefined,false}]},{peer_subset,unlimited,0,0,2,[]}}
17:44:37.845 [debug] [client] Received SETTINGS
17:44:37.845 [debug] [client] IWS undefined
17:44:37.845 [debug] [client] Sent Settings ACK
17:44:37.845 [debug] [client] {send headers, 1, [{<<":method">>,<<"POST">>},{<<":path">>,<<"/3/device/7B5FE70FD2D0ADC97629E63D64E15F8CE08DAB48D8F6CEDF85DE3464E5FF0FC9">>},{<<":scheme">>,<<"https">>},{<<":authority">>,<<"api.push.apple.com">>},{<<"content-length">>,<<"91">>},{<<"content-type">>,<<"application/json">>},{<<"accept">>,<<"application/json">>},{<<"apns-topic">>,<<"mybundle.com">>}]}
17:44:37.845 [debug] [client] Send Body Stream 1
17:44:37.982 [debug] [client][connected] {frame, "[Frame Header: L:0, T:\"SETTINGS\", F:1, StrId:0] | []"}
17:44:37.983 [debug] [client] Received SETTINGS ACK
17:44:37.983 [debug] [client][connected] {frame, "[Frame Header: L:30, T:\"SETTINGS\", F:0, StrId:0] | [{header_table_size,4096},\n {max_concurrent_streams,1000},\n {initial_window_size,65535},\n {max_frame_size,16384},\n {max_header_list_size,8000}]"}
17:44:37.983 [debug] [client] Received SETTINGS
17:44:37.983 [debug] old IWS: 65535 new IWS: 65535
17:44:37.983 [debug] [client] Sent Settings ACK
17:44:37.983 [debug] [client][connected] {frame, "[Frame Header: L:37, T:\"HEADERS\", F:4, StrId:1] | [Headers: {headers,undefined,\n                   <<140,64,133,29,117,33,99,73,156,109,252,47,181,133,150,\n                     150,101,183,68,179,78,224,18,207,129,151,86,189,121,220,\n                     23,131,121,188,15,190,247>>}]"}
17:44:37.983 [debug] [client] Received HEADERS Frame for Stream 1
17:44:37.983 [debug] read_binary L: 27, actually: 27
17:44:37.983 [debug] [client][connected] {frame, "[Frame Header: L:27, T:\"DATA\", F:1, StrId:1] | [Data: {data: <<\"{\\\"reason\\\":\\\"BadDeviceToken\\\"}\">> ...}]"}
17:44:37.983 [debug] [client] Received DATA Frame for Stream 1
17:44:37.983 [info] [client] Stream 1 WindowUpdate 27
rslota commented 7 years ago

The endpoint is chosen based on the request to the MongoosePush. In top level JSON for the notification, you send mode field that can be either prod (default) or dev (described in README.md). This is not related to how the MongoosePush has been build, since both are available at all times.

izigibran commented 7 years ago

@rslota I still do not understand where I should make this change. from MongooseIM?

rslota commented 7 years ago

I didn't know that you're using MongooseIM with MongoosePush (if I've missed it, sorry about that). Anyhow, in such case, MongooseIM is able to change this based on the XEP-0357 enable stanza's options. You should add to your XMPP client's enable stanza, the: <field var='mode'><value>dev</value></field>.

Here you can see example of the enable stanza along with description of the additional options (including mode): https://mongooseim.readthedocs.io/en/latest/user-guide/Push-notifications/.

rslota commented 7 years ago

Hi @izigibran ,

What is the status of this issue? Did you manage to test the dev mode? Do you need more help with that?

izigibran commented 7 years ago

@rslota yes, thanks for your help