@@ -661,3 +661,160 @@ test('clashing upgrade handler', async (t) => {
661661  const  ws  =  new  WebSocket ( 'ws://localhost:'  +  fastify . server . address ( ) . port ) 
662662  await  once ( ws ,  'error' ) 
663663} ) 
664+ 
665+ test ( 'Should handleUpgradeRequest successfully' ,  async  ( t )  =>  { 
666+   t . plan ( 4 ) 
667+ 
668+   const  fastify  =  Fastify ( ) 
669+   t . after ( ( )  =>  fastify . close ( ) ) 
670+ 
671+   await  fastify . register ( fastifyWebsocket ) 
672+ 
673+   let  customUpgradeCalled  =  false 
674+ 
675+   fastify . get ( '/' ,  { 
676+     websocket : true , 
677+     handleUpgradeRequest : async  ( request ,  socket ,  head )  =>  { 
678+       customUpgradeCalled  =  true 
679+       t . assert . equal ( typeof  socket ,  'object' ,  'socket parameter is provided' ) 
680+       t . assert . equal ( Buffer . isBuffer ( head ) ,  true ,  'head parameter is a buffer' ) 
681+ 
682+       return  new  Promise ( ( resolve )  =>  { 
683+         fastify . websocketServer . handleUpgrade ( request . raw ,  socket ,  head ,  ( ws )  =>  { 
684+           resolve ( ws ) 
685+         } ) 
686+       } ) 
687+     } 
688+   } ,  ( socket )  =>  { 
689+     socket . on ( 'message' ,  ( data )  =>  { 
690+       socket . send ( `echo: ${ data }  ) 
691+     } ) 
692+     t . after ( ( )  =>  socket . terminate ( ) ) 
693+   } ) 
694+ 
695+   await  fastify . listen ( {  port : 0  } ) 
696+ 
697+   const  ws  =  new  WebSocket ( 'ws://localhost:'  +  fastify . server . address ( ) . port ) 
698+   t . after ( ( )  =>  ws . close ( ) ) 
699+ 
700+   await  once ( ws ,  'open' ) 
701+   ws . send ( 'hello' ) 
702+ 
703+   const  [ message ]  =  await  once ( ws ,  'message' ) 
704+   t . assert . equal ( message . toString ( ) ,  'echo: hello' ) 
705+ 
706+   t . assert . ok ( customUpgradeCalled ,  'handleUpgradeRequest was called' ) 
707+ } ) 
708+ 
709+ test . only ( 'Should handle errors thrown in handleUpgradeRequest' ,  async  ( t )  =>  { 
710+   t . plan ( 1 ) 
711+ 
712+   const  fastify  =  Fastify ( ) 
713+   t . after ( ( )  =>  fastify . close ( ) ) 
714+ 
715+   await  fastify . register ( fastifyWebsocket ) 
716+ 
717+   fastify . get ( '/' ,  { 
718+     websocket : true , 
719+     handleUpgradeRequest : async  ( )  =>  { 
720+       throw  new  Error ( 'Custom upgrade error' ) 
721+     } 
722+   } ,  ( )  =>  { 
723+     t . fail ( 'websocket handler should not be called when upgrade fails' ) 
724+   } ) 
725+ 
726+   await  fastify . listen ( {  port : 0  } ) 
727+ 
728+   const  ws  =  new  WebSocket ( 'ws://localhost:'  +  fastify . server . address ( ) . port ) 
729+ 
730+   let  wsErrorResolved 
731+   const  wsErrorPromise  =  new  Promise ( ( resolve )  =>  { 
732+     wsErrorResolved  =  resolve 
733+   } ) 
734+ 
735+   ws . on ( 'error' ,  ( error )  =>  { 
736+     wsErrorResolved ( error ) 
737+   } ) 
738+ 
739+   const  wsError  =  await  wsErrorPromise 
740+ 
741+   t . assert . equal ( wsError . message ,  'Unexpected server response: 500' ) 
742+ } ) 
743+ 
744+ test ( 'Should allow for handleUpgradeRequest to send a response to the client before throwing an error' ,  async  ( t )  =>  { 
745+   t . plan ( 1 ) 
746+ 
747+   const  fastify  =  Fastify ( ) 
748+   t . after ( ( )  =>  fastify . close ( ) ) 
749+ 
750+   await  fastify . register ( fastifyWebsocket ) 
751+ 
752+   fastify . get ( '/' ,  { 
753+     websocket : true , 
754+     handleUpgradeRequest : async  ( )  =>  { 
755+       const  error  =  new  Error ( 'Forbidden' ) 
756+       error . statusCode  =  403 
757+       throw  error 
758+     } 
759+   } ,  ( )  =>  { 
760+     t . fail ( 'websocket handler should not be called when upgrade fails' ) 
761+   } ) 
762+ 
763+   await  fastify . listen ( {  port : 0  } ) 
764+ 
765+   const  ws  =  new  WebSocket ( 'ws://localhost:'  +  fastify . server . address ( ) . port ) 
766+ 
767+   let  wsErrorResolved 
768+   const  wsErrorPromise  =  new  Promise ( ( resolve )  =>  { 
769+     wsErrorResolved  =  resolve 
770+   } ) 
771+ 
772+   ws . on ( 'error' ,  ( error )  =>  { 
773+     wsErrorResolved ( error ) 
774+   } ) 
775+ 
776+   const  wsError  =  await  wsErrorPromise 
777+ 
778+   t . assert . equal ( wsError . message ,  'Unexpected server response: 403' ) 
779+ } ) 
780+ 
781+ test ( 'Should not send a response if handleUpgradeRequest has already ended the underlying socket and thrown an error' ,  async  ( t )  =>  { 
782+   t . plan ( 1 ) 
783+ 
784+   const  fastify  =  Fastify ( ) 
785+   t . after ( ( )  =>  fastify . close ( ) ) 
786+ 
787+   await  fastify . register ( fastifyWebsocket ) 
788+ 
789+   fastify . get ( '/' ,  { 
790+     websocket : true , 
791+     handleUpgradeRequest : async  ( request ,  socket ,  head )  =>  { 
792+       socket . write ( 'HTTP/1.1 400 Bad Request\r\n' ) 
793+       socket . write ( 'Connection: closed\r\n' ) 
794+       socket . write ( '\r\n' ) 
795+       socket . end ( ) 
796+       socket . destroy ( ) 
797+ 
798+       throw  new  Error ( 'thrown after response has ended' ) 
799+     } 
800+   } ,  ( )  =>  { 
801+     t . fail ( 'websocket handler should not be called when upgrade fails' ) 
802+   } ) 
803+ 
804+   await  fastify . listen ( {  port : 0  } ) 
805+ 
806+   const  ws  =  new  WebSocket ( 'ws://localhost:'  +  fastify . server . address ( ) . port ) 
807+ 
808+   let  wsErrorResolved 
809+   const  wsErrorPromise  =  new  Promise ( ( resolve )  =>  { 
810+     wsErrorResolved  =  resolve 
811+   } ) 
812+ 
813+   ws . on ( 'error' ,  ( error )  =>  { 
814+     wsErrorResolved ( error ) 
815+   } ) 
816+ 
817+   const  wsError  =  await  wsErrorPromise 
818+ 
819+   t . assert . equal ( wsError . message ,  'Unexpected server response: 400' ) 
820+ } ) 
0 commit comments