Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions lib/plausible.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
export const PLAUSIBLE_SCRIPT_PATH = '/js/script.js'
export const PLAUSIBLE_EVENT_PATH = '/api/event'

export const PLAUSIBLE_DESTINATIONS = {
[PLAUSIBLE_SCRIPT_PATH]: 'https://plausible.io/js/pa-EScEhWlTi3E-sauvdFABb.js',
[PLAUSIBLE_EVENT_PATH]: 'https://plausible.io/api/event'
}
5 changes: 2 additions & 3 deletions next.config.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
const { withPlausibleProxy } = require('next-plausible')
const { InjectManifest } = require('workbox-webpack-plugin')
const CopyPlugin = require('copy-webpack-plugin')
const webpack = require('webpack')
Expand Down Expand Up @@ -71,7 +70,7 @@ const getAllowedDevOrigins = () => {
return devOrigins
}

module.exports = withPlausibleProxy({ src: 'https://plausible.io/js/pa-EScEhWlTi3E-sauvdFABb.js' })({
module.exports = {
allowedDevOrigins: getAllowedDevOrigins(),
env: {
NEXT_PUBLIC_COMMIT_HASH: commitHash,
Expand Down Expand Up @@ -362,4 +361,4 @@ module.exports = withPlausibleProxy({ src: 'https://plausible.io/js/pa-EScEhWlTi

return config
}
})
}
3 changes: 2 additions & 1 deletion pages/_app.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { gql } from '@apollo/client'
import { ApolloProvider } from '@apollo/client/react'
import { MeProvider } from '@/components/me'
import PlausibleProvider from 'next-plausible'
import { PLAUSIBLE_SCRIPT_PATH, PLAUSIBLE_EVENT_PATH } from '@/lib/plausible'
import getApolloClient from '@/lib/apollo.js'
import { PriceProvider } from '@/components/price'
import { BlockHeightProvider } from '@/components/block-height'
Expand Down Expand Up @@ -114,7 +115,7 @@ export default function MyApp ({ Component, pageProps: { ...props } }) {
<meta name='viewport' content='initial-scale=1.0, width=device-width, viewport-fit=cover' />
</Head>
<ErrorBoundary>
<PlausibleProvider>
<PlausibleProvider src={PLAUSIBLE_SCRIPT_PATH} init={{ endpoint: PLAUSIBLE_EVENT_PATH }}>
<ApolloProvider client={client}>
<BrandingProvider branding={branding}>
<MeProvider me={me}>
Expand Down
26 changes: 26 additions & 0 deletions proxy.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,14 @@ import {
DOMAINS_AUTH_VERIFIER_TTL_S
} from '@/lib/domains/auth'
import { getDomainMapping, createDomainsDebugLogger } from '@/lib/domains'
import { PLAUSIBLE_DESTINATIONS } from '@/lib/plausible'

const REFERRER_TTL_S = 60 * 60 * 24
const PLAUSIBLE_REQUEST_HEADERS = [
'accept', 'accept-encoding', 'accept-language',
'content-type', 'content-encoding', 'content-length',
'if-none-match', 'if-modified-since', 'referer', 'user-agent', 'x-forwarded-for'
]

const referrerPattern = new URLPattern({ pathname: ':pathname(*)/r/:referrer([\\w_]+)' })
const itemPattern = new URLPattern({ pathname: '/items/:id(\\d+){/:other(\\w+)}?' })
Expand Down Expand Up @@ -244,10 +250,28 @@ function applySecurityHeaders (resp) {
}

export async function proxy (req) {
// Own the external rewrite and its header policy together: no Plausible
// request may bypass sanitization through a separate next.config rewrite.
const destination = PLAUSIBLE_DESTINATIONS[req.nextUrl.pathname.toLowerCase()]
if (destination) {
const url = new URL(destination)
url.search = req.nextUrl.search
const headers = new Headers()
for (const name of PLAUSIBLE_REQUEST_HEADERS) {
const value = req.headers.get(name)
if (value !== null) headers.set(name, value)
}
// Next also derives x-forwarded-host from this. Keep the override nonempty
// even when no permitted headers were supplied, so all others are removed.
headers.set('host', url.host)
return applySecurityHeaders(NextResponse.rewrite(url, { request: { headers } }))
}

// clear subname header to prevent potential spoofing
const headers = new Headers(req.headers)
headers.delete('x-stacker-news-subname')
headers.delete('x-stacker-news-domain')

const request = new NextRequest(req, { headers })

// domain can have a port (local dev), so we pass the whole domain to the middleware
Expand Down Expand Up @@ -281,6 +305,8 @@ export async function proxy (req) {

export const config = {
matcher: [
// Next requires a literal matcher. Tests keep this in sync with lib/plausible.
'/([aA][pP][iI]/[eE][vV][eE][nN][tT])',

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have trouble understanding:

  • the "tests" comment here because how does this sync? Doesn't this in fact desync?
  • why PLAUSIBLE_SCRIPT_PATH does not match here
  • the point of the uppercase. Is /aPi/ in a path the same as /ApI/?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the "tests" comment here because how does this sync? Doesn't this in fact desync?

Sorry. That's referencing some bot tests and a bot comment.

why PLAUSIBLE_SCRIPT_PATH does not match here

It's already covered by the other matcher. PLAUSIBLE_EVENT_PATH needed its own matcher because the other matcher excludes /api paths.

the point of the uppercase. Is /aPi/ in a path the same as /ApI/?

Bots being bots. I'll see if I can use PLAUSIBLE_EVENT_PATH.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll see if I can use PLAUSIBLE_EVENT_PATH.

We can't use constants in matchers, but I'll make it all lowercase and add a comment about needing to keep it in sync.

// NextJS recommends to not add the CSP header to prefetches and static assets
// prefetches are handled separately in the middleware for custom domain rewrites
// See https://nextjs.org/docs/app/building-your-application/configuring/content-security-policy
Expand Down
Loading