Skip to content

Commit f975654

Browse files
committed
convert file_server to TypeScript
1 parent 2279857 commit f975654

File tree

4 files changed

+97
-85
lines changed

4 files changed

+97
-85
lines changed

packages/https-proxy/lib/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,5 @@ import { create as createProxy, reset as resetProxy } from './proxy'
22
import { CA } from './ca'
33

44
export { createProxy, resetProxy, CA }
5+
6+
export type { Server } from './server'

packages/server/lib/file_server.js

Lines changed: 0 additions & 81 deletions
This file was deleted.

packages/server/lib/file_server.ts

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
// TODO: move this to packages/core-file-server
2+
import _ from 'lodash'
3+
import debugModule from 'debug'
4+
import url from 'url'
5+
import http from 'http'
6+
import path from 'path'
7+
import send from 'send'
8+
import { httpUtils } from '@packages/network'
9+
import { allowDestroy } from './util/server_destroy'
10+
import random from './util/random'
11+
import networkFailures from './util/network_failures'
12+
import type { AddressInfo } from 'net'
13+
14+
const debug = debugModule('cypress:server:file_server')
15+
16+
export type FileServer = {
17+
token: string
18+
port: () => number
19+
address: () => string
20+
close: () => void
21+
}
22+
23+
const onRequest = function (req: http.IncomingMessage, res: http.ServerResponse, expectedToken: string, fileServerFolder: string) {
24+
const token = req.headers['x-cypress-authorization']
25+
26+
if (token !== expectedToken) {
27+
debug('authorization failed on file_server request %o', { reqUrl: req.url, expectedToken, token })
28+
res.statusCode = 401
29+
res.end()
30+
31+
return
32+
}
33+
34+
const args = _.compact([
35+
fileServerFolder,
36+
req.url,
37+
])
38+
39+
// strip off any query params from our req's url
40+
// since we're pulling this from the file system
41+
// it does not understand query params
42+
// and make sure we decode the uri which swaps out
43+
// %20 with white space
44+
const file = decodeURI(url.parse(path.join(...args)).pathname as string)
45+
46+
res.setHeader('x-cypress-file-path', encodeURI(file))
47+
48+
return send(req, url.parse(req.url as string).pathname as string, {
49+
root: path.resolve(fileServerFolder),
50+
})
51+
.on('error', (err) => {
52+
res.setHeader('x-cypress-file-server-error', 'true')
53+
res.setHeader('content-type', 'text/html')
54+
res.statusCode = err.status
55+
56+
return res.end(networkFailures.get(file, err.status))
57+
}).pipe(res)
58+
}
59+
60+
export const create = (fileServerFolder: string): Promise<FileServer> => {
61+
return new Promise(((resolve) => {
62+
const token = random.id(64)
63+
64+
const srv = http.createServer(httpUtils.lenientOptions, (req: http.IncomingMessage, res: http.ServerResponse) => {
65+
return onRequest(req, res, token, fileServerFolder)
66+
})
67+
68+
allowDestroy(srv)
69+
70+
return srv.listen(0, '127.0.0.1', () => {
71+
return resolve({
72+
token,
73+
74+
port () {
75+
return (srv.address() as AddressInfo).port
76+
},
77+
78+
address () {
79+
// @ts-expect-error - port is defined on the object context
80+
return `http://localhost:${this.port()}`
81+
},
82+
83+
close () {
84+
// @ts-expect-error - destroyAsync is defined when allowDestroy is called
85+
return srv.destroyAsync()
86+
},
87+
})
88+
})
89+
}))
90+
}

packages/server/lib/server-base.ts

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import type { AddressInfo } from 'net'
1212
import url from 'url'
1313
import la from 'lazy-ass'
1414
import { createProxy as createHttpsProxy } from '@packages/https-proxy'
15+
import type { Server as HttpsProxyServer } from '@packages/https-proxy'
1516
import { getRoutesForRequest, netStubbingState, NetStubbingState } from '@packages/net-stubbing'
1617
import { agent, clientCertificates, httpUtils, concatStream } from '@packages/network'
1718
import { DocumentDomainInjection, getPath, parseUrlIntoHostProtocolDomainTldPort, removeDefaultPort } from '@packages/network-tools'
@@ -33,7 +34,7 @@ import type { Server as WebSocketServer } from 'ws'
3334
import { RemoteStates, RemoteState } from './remote_states'
3435
import { cookieJar, SerializableAutomationCookie } from './util/cookies'
3536
import { resourceTypeAndCredentialManager, ResourceTypeAndCredentialManager } from './util/resourceTypeAndCredentialManager'
36-
import fileServer from './file_server'
37+
import * as fileServer from './file_server'
3738
import appData from './util/app_data'
3839
import { graphqlWS } from '@packages/data-context/graphql/makeGraphQLServer'
3940
import statusCode from './util/status_code'
@@ -291,11 +292,11 @@ export class ServerBase<TSocket extends SocketE2E | SocketCt> {
291292
onUpgrade: this.onSniUpgrade.bind(this),
292293
}),
293294

294-
fileServer.create(fileServerFolder),
295+
fileServer.create(fileServerFolder as string),
295296
])
296297
.spread((httpsProxy, fileServer) => {
297-
this._httpsProxy = httpsProxy
298-
this._fileServer = fileServer
298+
this._httpsProxy = httpsProxy as HttpsProxyServer
299+
this._fileServer = fileServer as FileServer
299300

300301
// if we have a baseUrl let's go ahead
301302
// and make sure the server is connectable!

0 commit comments

Comments
 (0)