How to send a http2 request to APNs?

I am assuming require(‘http2’) is involved
Not sure how to build the rest, never touched http2 before. Is it even possible?
In python, it looks like this:

HEADERS

  • END_STREAM
  • END_HEADERS
    :method = POST
    :scheme = https
    :path = /3/device/DEVICE_REGISTRATION_ID
    host = api.development.push.apple.com
    authorization = bearer AUTH_TOKEN
    apns-id = OPTIONAL_UUID
    apns-expiration = 0
    apns-priority = 10
    apns-topic = TOPIC
    DATA
  • END_STREAM
    { “aps” : { “alert” : “Hello” } }

For anyone ineterested here is a solution I came up with. It works!
Code comes with example get endpoint

import jwt from 'jsonwebtoken';
import http2 from 'http2';
import { Http2Session, ClientHttp2Session } from 'http2';
export function get_testAPN(request) {
let options = {
"headers": {
"Content-Type": "application/json"
}
}; 
let note = { "aps": { "alert": "Hello" } };
return send(note, '<deviceId>').then(function (result) {
options.body = { "result": result };
return ok(options);
});
}
function getAPNAccessToken() {
var priv = "-----BEGIN PRIVATE ...your p8 file content";
return jwt.sign({}, priv, {
algorithm: "ES256",
issuer: "<Team ID>",
header: { kid: "<Key ID>" }
});
}
let session = null;
function ensureConnected() {
if (!session || session.destroyed) {
session = http2.connect("https://api.development.push.apple.com:443");
}
}
let _lastTokenTime = Date.now();
let _lastToken = getAPNAccessToken();
function getAuthToken() {
// return the same token for 3000 seconds
if (_lastTokenTime > Date.now() - 3000 * 1000) {
return _lastToken;
}
_lastTokenTime = Date.now();
_lastToken = getAPNAccessToken();
return _lastToken;
}
function send(APNNotification, deviceToken) {
return new Promise(function (resolve, reject) {
ensureConnected();
let authToken = getAuthToken();
var header = {
':method': 'POST',
':path': '/3/device/' + deviceToken,
'authorization': 'bearer ' + authToken,
'apns-topic': '<Bundle ID>'
};
return sendPostRequest(header, JSON.stringify(APNNotification), deviceToken)
.then(results => {
resolve(results);
});
});
}
function sendPostRequest(header, payload, deviceToken) {
return new Promise((resolve, reject) => {
var req = session.request(header);
req.setEncoding('utf8');
req.on('response', (headers) => {
let status = headers[http2.constants.HTTP2_HEADER_STATUS].toString();
// ...
let data = '';
req.on('data', (chunk) => {
data += chunk;
});
req.on('end', () => {
resolve({ status: status, body: data, device: deviceToken });
})
});
req.on('error', (err) => {
resolve({ error: err });
});
req.write(payload);
req.end();
});
}
function shutdown() {
this.session.destroy();
}