11import * as express from "express"
2- import * as http from "http"
3- import nodeFetch from "node-fetch"
42import { HttpCode } from "../../../src/common/http"
5- import { proxy } from "../../../src/node/proxy"
63import { wss , Router as WsRouter } from "../../../src/node/wsRouter"
7- import { getAvailablePort , mockLogger } from "../../utils/helpers"
4+ import { mockLogger } from "../../utils/helpers"
85import * as httpserver from "../../utils/httpserver"
96import * as integration from "../../utils/integration"
107
118describe ( "proxy" , ( ) => {
12- const nhooyrDevServer = new httpserver . HttpServer ( )
9+ const proxyTarget = new httpserver . HttpServer ( )
1310 const wsApp = express . default ( )
1411 const wsRouter = WsRouter ( )
1512 let codeServer : httpserver . HttpServer | undefined
@@ -19,21 +16,22 @@ describe("proxy", () => {
1916
2017 beforeAll ( async ( ) => {
2118 wsApp . use ( "/" , wsRouter . router )
22- await nhooyrDevServer . listen ( ( req , res ) => {
19+ await proxyTarget . listen ( ( req , res ) => {
2320 e ( req , res )
2421 } )
25- nhooyrDevServer . listenUpgrade ( wsApp )
26- proxyPath = `/proxy/${ nhooyrDevServer . port ( ) } /wsup`
22+ proxyTarget . listenUpgrade ( wsApp )
23+ proxyPath = `/proxy/${ proxyTarget . port ( ) } /wsup`
2724 absProxyPath = proxyPath . replace ( "/proxy/" , "/absproxy/" )
2825 } )
2926
3027 afterAll ( async ( ) => {
31- await nhooyrDevServer . dispose ( )
28+ await proxyTarget . dispose ( )
3229 } )
3330
3431 beforeEach ( ( ) => {
3532 e = express . default ( )
3633 mockLogger ( )
34+ delete process . env . PASSWORD
3735 } )
3836
3937 afterEach ( async ( ) => {
@@ -283,65 +281,42 @@ describe("proxy", () => {
283281 const resp = await codeServer . fetch ( proxyPath , { method : "OPTIONS" } )
284282 expect ( resp . status ) . toBe ( 200 )
285283 } )
286- } )
287284
288- // NOTE@jsjoeio
289- // Both this test suite and the one above it are very similar
290- // The main difference is this one uses http and node-fetch
291- // and specifically tests the proxy in isolation vs. using
292- // the httpserver abstraction we've built.
293- //
294- // Leaving this as a separate test suite for now because
295- // we may consider refactoring the httpserver abstraction
296- // in the future.
297- //
298- // If you're writing a test specifically for code in
299- // src/node/proxy.ts, you should probably add it to
300- // this test suite.
301- describe ( "proxy (standalone)" , ( ) => {
302- let URL = ""
303- let PROXY_URL = ""
304- let testServer : http . Server
305- let proxyTarget : http . Server
285+ it ( "should return a 500 when no target is running " , async ( ) => {
286+ const target = new httpserver . HttpServer ( )
287+ await target . listen ( ( ) => { } )
288+ const port = target . port ( )
289+ target . dispose ( )
290+ codeServer = await integration . setup ( [ "--auth=none" ] , "" )
291+ const resp = await codeServer . fetch ( `/proxy/${ port } /wsup` )
292+ expect ( resp . status ) . toBe ( HttpCode . ServerError )
293+ expect ( resp . statusText ) . toBe ( "Internal Server Error" )
294+ } )
306295
307- beforeEach ( async ( ) => {
308- const PORT = await getAvailablePort ( )
309- const PROXY_PORT = await getAvailablePort ( )
310- URL = `http://localhost:${ PORT } `
311- PROXY_URL = `http://localhost:${ PROXY_PORT } `
312- // Define server and a proxy server
313- testServer = http . createServer ( ( req , res ) => {
314- proxy . web ( req , res , {
315- target : PROXY_URL ,
316- } )
317- } )
296+ it ( "should strip token cookie" , async ( ) => {
297+ const token = "my-super-secure-token"
298+ process . env . HASHED_PASSWORD = token
299+ codeServer = await integration . setup ( [ "--auth=password" ] )
318300
319- proxyTarget = http . createServer ( ( req , res ) => {
320- res . writeHead ( 200 , { "Content-Type" : "text/plain" } )
321- res . end ( )
301+ // Set up a listener that just prints the cookies it got.
302+ e . get ( "/wsup/cookies" , ( req , res ) => {
303+ res . writeHead ( HttpCode . Ok , { "Content-Type" : "text/plain" } )
304+ res . end ( req . headers . cookie )
322305 } )
323306
324- // Start both servers
325- proxyTarget . listen ( PROXY_PORT )
326- testServer . listen ( PORT )
327- } )
328-
329- afterEach ( async ( ) => {
330- testServer . close ( )
331- proxyTarget . close ( )
332- } )
333-
334- it ( "should return a 500 when proxy target errors " , async ( ) => {
335- // Close the proxy target so that proxy errors
336- proxyTarget . close ( )
337- const errorResp = await nodeFetch ( `${ URL } /error` )
338- expect ( errorResp . status ) . toBe ( HttpCode . ServerError )
339- expect ( errorResp . statusText ) . toBe ( "Internal Server Error" )
340- } )
307+ // Send the token along with other cookies which should be preserved.
308+ // Encode one to make sure they are being re-encoded properly.
309+ const value = "hello=there"
310+ const encodedValue = encodeURIComponent ( value )
311+ const resp = await codeServer . fetch ( proxyPath + "/cookies" , {
312+ headers : {
313+ cookie : `cookie1=${ encodedValue } ; code-server-session=${ token } ; cookie2=hello;` ,
314+ } ,
315+ } )
341316
342- it ( "should proxy correctly" , async ( ) => {
343- const resp = await nodeFetch ( `${ URL } /route` )
317+ // The proxied listener should not have printed the code-server token.
344318 expect ( resp . status ) . toBe ( 200 )
345- expect ( resp . statusText ) . toBe ( "OK" )
319+ const text = await resp . text ( )
320+ expect ( text ) . toBe ( `cookie1=${ encodedValue } ; cookie2=hello` )
346321 } )
347322} )
0 commit comments