1+ import net from 'node:net'
2+ import path from 'node:path'
3+ import { fileURLToPath } from 'node:url'
14import fetch from 'node-fetch'
25import {
36 afterEach ,
@@ -12,6 +15,8 @@ import WebSocket from 'ws'
1215import testJSON from '../safe.json'
1316import { browser , isServe , page , viteServer , viteTestUrl } from '~utils'
1417
18+ const __dirname = path . dirname ( fileURLToPath ( import . meta. url ) )
19+
1520const getViteTestIndexHtmlUrl = ( ) => {
1621 const srcPrefix = viteTestUrl . endsWith ( '/' ) ? '' : '/'
1722 // NOTE: viteTestUrl is set lazily
@@ -392,3 +397,73 @@ describe('cross origin', () => {
392397 )
393398 } )
394399} )
400+
401+ describe . runIf ( isServe ) ( 'invalid request' , ( ) => {
402+ const sendRawRequest = async ( baseUrl : string , requestTarget : string ) => {
403+ return new Promise < string > ( ( resolve , reject ) => {
404+ const parsedUrl = new URL ( baseUrl )
405+
406+ const buf : Buffer [ ] = [ ]
407+ const client = net . createConnection (
408+ { port : + parsedUrl . port , host : parsedUrl . hostname } ,
409+ ( ) => {
410+ client . write (
411+ [
412+ `GET ${ encodeURI ( requestTarget ) } HTTP/1.1` ,
413+ `Host: ${ parsedUrl . host } ` ,
414+ 'Connection: Close' ,
415+ '\r\n' ,
416+ ] . join ( '\r\n' ) ,
417+ )
418+ } ,
419+ )
420+ client . on ( 'data' , ( data ) => {
421+ buf . push ( data )
422+ } )
423+ client . on ( 'end' , ( hadError ) => {
424+ if ( ! hadError ) {
425+ resolve ( Buffer . concat ( buf ) . toString ( ) )
426+ }
427+ } )
428+ client . on ( 'error' , ( err ) => {
429+ reject ( err )
430+ } )
431+ } )
432+ }
433+
434+ const root = path
435+ . resolve ( __dirname . replace ( 'playground' , 'playground-temp' ) , '..' )
436+ . replace ( / \\ / g, '/' )
437+
438+ test ( 'request with sendRawRequest should work' , async ( ) => {
439+ const response = await sendRawRequest ( viteTestUrl , '/src/safe.txt' )
440+ expect ( response ) . toContain ( 'HTTP/1.1 200 OK' )
441+ expect ( response ) . toContain ( 'KEY=safe' )
442+ } )
443+
444+ test ( 'request with sendRawRequest should work with /@fs/' , async ( ) => {
445+ const response = await sendRawRequest (
446+ viteTestUrl ,
447+ path . posix . join ( '/@fs/' , root , 'root/src/safe.txt' ) ,
448+ )
449+ expect ( response ) . toContain ( 'HTTP/1.1 200 OK' )
450+ expect ( response ) . toContain ( 'KEY=safe' )
451+ } )
452+
453+ test ( 'should reject request that has # in request-target' , async ( ) => {
454+ const response = await sendRawRequest (
455+ viteTestUrl ,
456+ '/src/safe.txt#/../../unsafe.txt' ,
457+ )
458+ expect ( response ) . toContain ( 'HTTP/1.1 400 Bad Request' )
459+ } )
460+
461+ test ( 'should reject request that has # in request-target with /@fs/' , async ( ) => {
462+ const response = await sendRawRequest (
463+ viteTestUrl ,
464+ path . posix . join ( '/@fs/' , root , 'root/src/safe.txt' ) +
465+ '#/../../unsafe.txt' ,
466+ )
467+ expect ( response ) . toContain ( 'HTTP/1.1 400 Bad Request' )
468+ } )
469+ } )
0 commit comments