mirror of
https://github.com/sourcegraph/sourcegraph.git
synced 2026-02-06 15:12:02 +00:00
- Closes #33834 - Upgraded react-router to v6 - Migrated the web application to [the data-aware router introduced in v6.4.0](https://reactrouter.com/en/main/routers/picking-a-router#using-v64-data-apis). - Migrated `history.block` usages to the `unstable_useBlock` hook [introduced in v6.7.0](https://github.com/remix-run/react-router/issues/8139). - Removed explicit history reference from the `renderWithBrandedContext` utility used in unit tests. - Migrated the search-query state observer from `history.listen` to `useLocation` API. ## Test plan CI and manually visiting all the pages.
114 lines
4.8 KiB
TypeScript
114 lines
4.8 KiB
TypeScript
import { Options, responseInterceptor } from 'http-proxy-middleware'
|
|
|
|
import { ENVIRONMENT_CONFIG, HTTPS_WEB_SERVER_URL } from './environment-config'
|
|
|
|
// One of the API routes: "/-/sign-in".
|
|
const PROXY_ROUTES = ['/.api', '/search/stream', '/-', '/.auth']
|
|
|
|
interface GetAPIProxySettingsOptions {
|
|
apiURL: string
|
|
/**
|
|
* If provided, the server will proxy requests to index.html
|
|
* and inject the `window.context` defined there into the local template.
|
|
*/
|
|
getLocalIndexHTML?: (jsContextScript?: string) => string
|
|
}
|
|
|
|
interface ProxySettings extends Options {
|
|
proxyRoutes: string[]
|
|
}
|
|
|
|
export function getAPIProxySettings(options: GetAPIProxySettingsOptions): ProxySettings {
|
|
const { apiURL, getLocalIndexHTML } = options
|
|
|
|
return {
|
|
// Enable index.html proxy if `getLocalIndexHTML` is provided.
|
|
proxyRoutes: [...PROXY_ROUTES, ...(getLocalIndexHTML ? [''] : [])],
|
|
target: apiURL,
|
|
// Do not SSL certificate.
|
|
secure: false,
|
|
// Change the origin of the host header to the target URL.
|
|
changeOrigin: true,
|
|
// Rewrite domain of `set-cookie` headers for all cookies received.
|
|
cookieDomainRewrite: '',
|
|
// Prevent automatic call of res.end() in `onProxyRes`. It is handled by `responseInterceptor`.
|
|
selfHandleResponse: true,
|
|
// eslint-disable-next-line @typescript-eslint/no-misused-promises, @typescript-eslint/require-await
|
|
onProxyRes: responseInterceptor(async (responseBuffer, proxyRes) => {
|
|
// Propagate cookies to enable authentication on the remote server.
|
|
if (proxyRes.headers['set-cookie']) {
|
|
// Remove `Secure` and `SameSite` from `set-cookie` headers.
|
|
const cookies = proxyRes.headers['set-cookie'].map(cookie =>
|
|
cookie.replace(/; secure/gi, '').replace(/; samesite=.+/gi, '')
|
|
)
|
|
|
|
proxyRes.headers['set-cookie'] = cookies
|
|
}
|
|
|
|
// Extract remote `window.context` from the HTML response and inject it into
|
|
// the index.html generated by `getLocalIndexHTML`.
|
|
if (
|
|
getLocalIndexHTML &&
|
|
// router.go is not up to date with client routes and still serves index.html with 404
|
|
(proxyRes.statusCode === 200 || proxyRes.statusCode === 404) &&
|
|
proxyRes.headers['content-type'] &&
|
|
proxyRes.headers['content-type'].includes('text/html')
|
|
) {
|
|
const remoteIndexHTML = responseBuffer.toString('utf8')
|
|
|
|
return getLocalIndexHTML(getRemoteJsContextScript(remoteIndexHTML))
|
|
}
|
|
|
|
return responseBuffer
|
|
}),
|
|
onProxyReq: proxyRequest => {
|
|
// Not really clear why, but the `changeOrigin: true` setting does NOT add the correct
|
|
// Origin header to requests sent to k8s.sgdev.org, which e.g. breaks sign in and more. So
|
|
// we add it ourselves.
|
|
proxyRequest.setHeader('Origin', apiURL)
|
|
},
|
|
// TODO: share with `client/web/gulpfile.js`
|
|
// Avoid crashing on "read ECONNRESET".
|
|
onError: () => undefined,
|
|
// Don't log proxy errors, these usually just contain
|
|
// ECONNRESET errors caused by the browser cancelling
|
|
// requests. This should not be needed to actually debug something.
|
|
logLevel: 'silent',
|
|
onProxyReqWs: (_proxyRequest, _request, socket) =>
|
|
socket.on('error', error => console.error('WebSocket proxy error:', error)),
|
|
}
|
|
}
|
|
|
|
const jsContextChanges = `
|
|
// Changes to remote 'window.context' required for local development.
|
|
Object.assign(window.context, {
|
|
// Only username/password auth-provider provider is supported with the standalone server.
|
|
authProviders: window.context.authProviders.filter(provider => provider.isBuiltin),
|
|
|
|
// For some reason, the standalone server crashes with legacy extensions enabled.
|
|
enableLegacyExtensions: false,
|
|
|
|
// Sync externalURL with the development environment config.
|
|
externalURL: '${HTTPS_WEB_SERVER_URL}',
|
|
|
|
// Enable local testing of OpenTelemtry endpoints.
|
|
openTelemetry: {
|
|
endpoint: '${ENVIRONMENT_CONFIG.CLIENT_OTEL_EXPORTER_OTLP_ENDPOINT}',
|
|
},
|
|
|
|
// Do not send errors to Sentry from the development environment.
|
|
sentryDSN: null,
|
|
|
|
siteGQLID: 'TestGQLSiteID',
|
|
siteID: 'TestSiteID',
|
|
version: 'web-standalone',
|
|
})
|
|
`
|
|
|
|
function getRemoteJsContextScript(remoteIndexHTML: string): string {
|
|
const remoteJsContextStart = remoteIndexHTML.indexOf('window.context = {')
|
|
const remoteJsContextEnd = remoteIndexHTML.indexOf('</script>', remoteJsContextStart)
|
|
|
|
return remoteIndexHTML.slice(remoteJsContextStart, remoteJsContextEnd) + jsContextChanges
|
|
}
|