Skip to content

Commit

Permalink
Merge pull request #79 from lidofinance/develop
Browse files Browse the repository at this point in the history
develop to main
  • Loading branch information
infoster42 authored Jul 20, 2023
2 parents 4f5debc + 6984205 commit 972fda4
Show file tree
Hide file tree
Showing 8 changed files with 127 additions and 72 deletions.
3 changes: 2 additions & 1 deletion .env.sample
Original file line number Diff line number Diff line change
Expand Up @@ -26,4 +26,5 @@ CSP_REPORT_ONLY=true

# api endpoint for reporting csp violations
# for prod and dev use https and real domain
CSP_REPORT_URI=http://localhost/api/csp-report
CSP_REPORT_URI=http://localhost:3000/api/csp-report

11 changes: 0 additions & 11 deletions middleware.ts

This file was deleted.

86 changes: 79 additions & 7 deletions next.config.mjs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { createSecureHeaders } from 'next-secure-headers'
import buildDynamics from './scripts/build-dynamics.mjs';

buildDynamics();
Expand All @@ -9,14 +10,20 @@ const apiProviderUrls = {
[5]: process.env[`API_PROVIDER_URL_5`],
};

const cspTrustedHosts = process.env.CSP_TRUSTED_HOSTS;
const cspTrustedHosts = process.env.CSP_TRUSTED_HOSTS?.split(',') ?? ['https://*.lido.fi'];
const cspReportOnly = process.env.CSP_REPORT_ONLY;
const cspReportUri = process.env.CSP_REPORT_URI;

const rateLimit = process.env.RATE_LIMIT || 100;
const rateLimitTimeFrame = process.env.RATE_LIMIT_TIME_FRAME || 60; // 1 minute;

// we will swap `CACHE_CONTROL_HEADER` with `cache-control` inside custom server (server.mjs)
export const CACHE_CONTROL_HEADER = 'x-cache-control'
export const CACHE_CONTROL_VALUE =
'public, s-max-age=30, stale-if-error=1200, stale-while-revalidate=30';

export default {
poweredByHeader: false,
eslint: {
ignoreDuringBuilds: true,
},
Expand Down Expand Up @@ -59,22 +66,87 @@ export default {

return config
},
async headers() {
headers() {
return [
{
// required for gnosis save apps
source: '/:path*',
headers: createSecureHeaders({
contentSecurityPolicy: {
directives: {
styleSrc: ["'self'", 'https://fonts.googleapis.com', "'unsafe-inline'"],
fontSrc: ["'self'", "data:", 'https://fonts.gstatic.com', ...cspTrustedHosts],
imgSrc: [
"'self'",
'data:',
'https://*.walletconnect.org',
'https://*.walletconnect.com',
...cspTrustedHosts,
],
scriptSrc: ["'self'", "'unsafe-eval'", "'unsafe-inline'", ...cspTrustedHosts],
connectSrc: [
"'self'",
'wss://*.walletconnect.org',
'https://*.walletconnect.org',
'wss://*.walletconnect.com',
'https://*.walletconnect.com',
'https://*.coinbase.com',
'wss://*.walletlink.org',
'https://api.1inch.exchange',
'https://api.1inch.io',
'https://rpc.ankr.com',
'https://cdn.live.ledger.com',
'https://apiv5.paraswap.io',
'https://api.cow.fi',
'https://cloudflare-eth.com',
'https://api.coingecko.com',
...cspTrustedHosts,
],
formAction: ["'self'", ...cspTrustedHosts],
frameAncestors: ['*'],
manifestSrc: ["'self'", ...cspTrustedHosts],
mediaSrc: ["'self'", ...cspTrustedHosts],
childSrc: [
"'self'",
'https://*.walletconnect.org',
'https://*.walletconnect.com',
...cspTrustedHosts,
],
objectSrc: ["'self'", ...cspTrustedHosts],
defaultSrc: ["'self'", ...cspTrustedHosts],
baseUri: ["'none'"],
reportURI: cspReportUri,
},
reportOnly: cspReportOnly,
},
frameGuard: false,
})
},
{
// required for gnosis safe apps
source: '/manifest.json',
headers: [{ key: 'Access-Control-Allow-Origin', value: '*' }],
headers: [
{ key: 'Access-Control-Allow-Origin', value: '*' },
{ key: CACHE_CONTROL_HEADER, value: CACHE_CONTROL_VALUE },
],
},
{
source: '/favicon:size*',
headers: [
{ key: CACHE_CONTROL_HEADER, value: CACHE_CONTROL_VALUE },
]
},
{
source: '/(|aragon|snapshot|admin)',
headers: [
{ key: CACHE_CONTROL_HEADER, value: CACHE_CONTROL_VALUE },
]
}
];
},
serverRuntimeConfig: {
infuraApiKey,
alchemyApiKey,
apiProviderUrls,
cspTrustedHosts,
cspReportOnly,
cspReportUri,
rateLimit,
rateLimitTimeFrame,
},
Expand Down
5 changes: 2 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@
"private": true,
"type": "module",
"scripts": {
"dev": "next dev",
"dev": "node server.mjs",
"build": "next build",
"start": "NODE_OPTIONS='-r next-logger' next start",
"start": "NODE_OPTIONS='-r next-logger' NODE_ENV=production node server.mjs",
"lint": "eslint --ext ts,tsx .",
"lint:fix": "yarn lint --fix",
"types": "tsc --noEmit",
Expand All @@ -21,7 +21,6 @@
"@lidofinance/api-rpc": "^0.18.0",
"@lidofinance/lido-ui": "^3.2.0",
"@lidofinance/next-api-wrapper": "^0.17.0",
"@lidofinance/next-cache-files-middleware": "^0.17.0",
"@lidofinance/next-ip-rate-limit": "^0.18.0",
"@lidofinance/next-pages": "^0.17.0",
"@lidofinance/rpc": "^0.17.0",
Expand Down
5 changes: 1 addition & 4 deletions pages/_app.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import {
migrationThemeCookiesToCrossDomainCookiesClientSide,
CookieThemeProvider,
} from '@lidofinance/lido-ui';
import { withCsp } from 'shared/api/withCsp';
import { GlobalStyle } from 'shared/ui';
import { ModalProvider } from 'features/walletModal';
import { ProviderWeb3 } from 'reef-knot/web3-react';
Expand Down Expand Up @@ -65,6 +64,4 @@ AppWrapper.getInitialProps = async (appContext: AppContext) => {
return await NextApp.getInitialProps(appContext);
};

export default process.env.NODE_ENV === 'development'
? AppWrapper
: withCsp(AppWrapper);
export default AppWrapper;
43 changes: 43 additions & 0 deletions server.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import { createServer } from 'http'
import { parse } from 'url'
import next from 'next'
import { CACHE_CONTROL_HEADER } from './next.config.mjs'

const dev = process.env.NODE_ENV !== 'production'
const hostname = 'localhost'
const port = 3000
// when using middleware `hostname` and `port` must be provided below
const app = next({ dev, hostname, port })
const handle = app.getRequestHandler()

app.prepare().then(() => {
createServer(async (req, res) => {
// Be sure to pass `true` as the second argument to `url.parse`.
// This tells it to parse the query portion of the URL.
const parsedUrl = parse(req.url, true)

const setHeader = res.setHeader
let cacheControlOverwritten = false
res.setHeader = function(header, value) {
if (header.toLowerCase() === CACHE_CONTROL_HEADER) {
cacheControlOverwritten = true
return setHeader.call(this, 'Cache-Control', value)
}

if (header.toLowerCase() === 'cache-control' && cacheControlOverwritten) {
return this
}

return setHeader.call(this, header, value);
}

await handle(req, res, parsedUrl)
})
.once('error', (err) => {
console.error(err)
process.exit(1)
})
.listen(port, () => {
console.log(`> Ready on http://${hostname}:${port}`)
})
})
1 change: 0 additions & 1 deletion shared/api/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,2 @@
export * from './default-error-handler';
export * from './fetchRPC';
export * from './withCsp';
45 changes: 0 additions & 45 deletions shared/api/withCsp.ts

This file was deleted.

0 comments on commit 972fda4

Please sign in to comment.