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
@@ -391,3 +396,73 @@ describe('cross origin', () => {
391396 )
392397 } )
393398} )
399+
400+ describe . runIf ( isServe ) ( 'invalid request' , ( ) => {
401+ const sendRawRequest = async ( baseUrl : string , requestTarget : string ) => {
402+ return new Promise < string > ( ( resolve , reject ) => {
403+ const parsedUrl = new URL ( baseUrl )
404+
405+ const buf : Buffer [ ] = [ ]
406+ const client = net . createConnection (
407+ { port : + parsedUrl . port , host : parsedUrl . hostname } ,
408+ ( ) => {
409+ client . write (
410+ [
411+ `GET ${ encodeURI ( requestTarget ) } HTTP/1.1` ,
412+ `Host: ${ parsedUrl . host } ` ,
413+ 'Connection: Close' ,
414+ '\r\n' ,
415+ ] . join ( '\r\n' ) ,
416+ )
417+ } ,
418+ )
419+ client . on ( 'data' , ( data ) => {
420+ buf . push ( data )
421+ } )
422+ client . on ( 'end' , ( hadError ) => {
423+ if ( ! hadError ) {
424+ resolve ( Buffer . concat ( buf ) . toString ( ) )
425+ }
426+ } )
427+ client . on ( 'error' , ( err ) => {
428+ reject ( err )
429+ } )
430+ } )
431+ }
432+
433+ const root = path
434+ . resolve ( __dirname . replace ( 'playground' , 'playground-temp' ) , '..' )
435+ . replace ( / \\ / g, '/' )
436+
437+ test ( 'request with sendRawRequest should work' , async ( ) => {
438+ const response = await sendRawRequest ( viteTestUrl , '/src/safe.txt' )
439+ expect ( response ) . toContain ( 'HTTP/1.1 200 OK' )
440+ expect ( response ) . toContain ( 'KEY=safe' )
441+ } )
442+
443+ test ( 'request with sendRawRequest should work with /@fs/' , async ( ) => {
444+ const response = await sendRawRequest (
445+ viteTestUrl ,
446+ path . posix . join ( '/@fs/' , root , 'root/src/safe.txt' ) ,
447+ )
448+ expect ( response ) . toContain ( 'HTTP/1.1 200 OK' )
449+ expect ( response ) . toContain ( 'KEY=safe' )
450+ } )
451+
452+ test ( 'should reject request that has # in request-target' , async ( ) => {
453+ const response = await sendRawRequest (
454+ viteTestUrl ,
455+ '/src/safe.txt#/../../unsafe.txt' ,
456+ )
457+ expect ( response ) . toContain ( 'HTTP/1.1 400 Bad Request' )
458+ } )
459+
460+ test ( 'should reject request that has # in request-target with /@fs/' , async ( ) => {
461+ const response = await sendRawRequest (
462+ viteTestUrl ,
463+ path . posix . join ( '/@fs/' , root , 'root/src/safe.txt' ) +
464+ '#/../../unsafe.txt' ,
465+ )
466+ expect ( response ) . toContain ( 'HTTP/1.1 400 Bad Request' )
467+ } )
468+ } )
0 commit comments