@@ -49,6 +49,12 @@ const callInsufficientStorage = function(reply, msg){
4949 reply . code ( 507 ) . send ( { message : msg , error : "Insufficient Storage" , statusCode : reply . statusCode } ) ;
5050}
5151
52+ const callMethodNotAllowed = function ( reply , allowedMethods , msg ) {
53+ reply . code ( 405 )
54+ . header ( 'Allow' , allowedMethods )
55+ . send ( { message : msg , error : "Method Not Allowed" , statusCode : reply . statusCode } ) ;
56+ }
57+
5258fastify . get ( '/keys' , ( request , reply ) => {
5359 reply . send ( helper . genKeyPair ( ) ) ;
5460} )
@@ -68,11 +74,11 @@ fastify.get('/keys/:key', (request, reply) => {
6874 }
6975} )
7076
71- fastify . post ( '/public/:publicKey' , async ( request , reply ) => {
72- const { publicKey } = request . params ;
77+ fastify . post ( '/public/:publicKey/:channel? ' , async ( request , reply ) => {
78+ const { publicKey, channel } = request . params ;
7379 const redirectOnOk = request . query . ok ;
7480 const redirectOnErr = request . query . err ;
75-
81+ let payload = request . body ;
7682 try {
7783 if ( helper . parseKey ( publicKey , { validate : false } ) . type !== 'public' ) throw new Error ( 'Unauthorized' ) ;
7884
@@ -85,11 +91,20 @@ fastify.post('/public/:publicKey', async (request, reply) => {
8591 'x-vercel-ip-country' : country ,
8692 'x-vercel-ip-country-region' : region ,
8793 'x-vercel-ip-city' : city ,
88- 'x-real-ip' : ip
94+ 'x-real-ip' : ip ,
95+ 'content-length' : bodySize
8996 } = request . headers ;
9097 if ( country || region || city ) meta . geolocation = [ country , region , city ] . join ( '/' ) ;
9198 if ( ip ) meta . ip = ip ;
92- const data = helper . decoratePayload ( request . body , meta ) ;
99+ if ( channel ) {
100+ meta . channel = channel ;
101+ // If request doesn't have a body, use the value stored in channel(key) instead
102+ if ( parseInt ( bodySize ) === 0 ) {
103+ const channelData = await helper . oneToOneConsume ( publicKey , channel ) ;
104+ payload = channelData ?. data ?? { } ;
105+ }
106+ }
107+ const data = helper . decoratePayload ( payload , meta ) ;
93108
94109 // Try posting the data to webhook, if any, with timeout.
95110 // On fail, store data and send web-push notifications to owner.
@@ -366,38 +381,56 @@ fastify.get('/private/:privateKey/:key', async (request, reply) => {
366381 }
367382} )
368383
369- const streamHandler = async ( request , reply ) => {
370- const { key } = request . params ;
371- try {
372- let recvBool ;
373- switch ( request . method ) {
374- case 'POST' : // Using fallthrough! POST and PUT cases run the same code.
375- case 'PUT' :
376- recvBool = false ;
377- break ;
378- case 'HEAD' : // HEAD and GET handled similarly
379- case 'GET' :
380- recvBool = true ;
381- break ;
382- default :
383- throw new Error ( 'Unsupported Method' ) ;
384- }
385- const token = await helper . streamToken ( key , recvBool ) ;
386- reply . redirect ( 'https://ppng.io/' + token , 307 ) ;
387- } catch ( err ) {
388- if ( err . message == 'Unauthorized' ) {
389- callUnauthorized ( reply , 'This path is for internal use only' ) ;
390- } else if ( err . message == 'Invalid Key' ) {
391- callBadRequest ( reply , 'Provided key is invalid' ) ;
392- } else if ( err . message == 'Unsupported Method' ) {
393- callBadRequest ( reply , 'Unsupported method' ) ;
394- } else {
395- callInternalServerError ( reply , err . message ) ;
384+ fastify . all ( '/private/:privateKey.pipe' , async ( request , reply ) => {
385+ const { privateKey } = request . params ;
386+ const pipeFail = request . query . fail ;
387+ try {
388+ if ( helper . parseKey ( privateKey , { validate : false } ) . type !== 'private' ) throw new Error ( 'Unauthorized' ) ;
389+ const pipeURL = await helper . pipeToPublic ( privateKey , request . method ) ;
390+ if ( pipeFail ) waitUntil ( helper . cacheSet ( privateKey , { pipeFail } ) ) ;
391+ reply . redirect ( pipeURL , 307 ) ;
392+ } catch ( err ) {
393+ if ( err . message == 'Unauthorized' ) {
394+ callUnauthorized ( reply , 'Provided key is not Private' ) ;
395+ } else if ( err . message === 'Invalid Key' ) {
396+ callBadRequest ( reply , 'Provided key is invalid' ) ;
397+ } else if ( err . message === 'Method Not Allowed' ) {
398+ callMethodNotAllowed ( reply , 'GET,POST,PUT' , 'Provided method is not allowed for piping' ) ;
399+ } else {
400+ callInternalServerError ( reply , err . message ) ;
401+ }
396402 }
397- }
398- }
403+ } ) ;
399404
400- fastify . all ( '/pipe/:key' , streamHandler ) ;
405+ fastify . all ( '/public/:publicKey.pipe' , async ( request , reply ) => {
406+ const { publicKey } = request . params ;
407+ try {
408+ if ( helper . parseKey ( publicKey , { validate : false } ) . type !== 'public' ) throw new Error ( 'Unauthorized' ) ;
409+ const pipeURL = await helper . pipeToPrivate ( publicKey , request . method ) ;
410+ if ( pipeURL ) {
411+ reply . redirect ( pipeURL , 307 ) ;
412+ } else {
413+ const page404 = await helper . cacheGet ( publicKey , 'pipeFail' ) ;
414+ if ( page404 ) {
415+ reply . redirect ( page404 , 303 ) ;
416+ } else {
417+ throw new Error ( 'No Data' ) ;
418+ }
419+ }
420+ } catch ( err ) {
421+ if ( err . message == 'Unauthorized' ) {
422+ callUnauthorized ( reply , 'Provided key is not Private' ) ;
423+ } else if ( err . message === 'Invalid Key' ) {
424+ callBadRequest ( reply , 'Provided key is invalid' ) ;
425+ } else if ( err . message === 'No Data' ) {
426+ reply . callNotFound ( ) ;
427+ } else if ( err . message === 'Method Not Allowed' ) {
428+ callMethodNotAllowed ( reply , 'GET,POST,PUT' , 'Provided method is not allowed for piping' ) ;
429+ } else {
430+ callInternalServerError ( reply , err . message ) ;
431+ }
432+ }
433+ } ) ;
401434
402435export default async function handler ( req , res ) {
403436 await fastify . ready ( ) ;
0 commit comments