Open davidmytton opened 3 months ago
ArcjetNodeRequest
are you trying to use @arcjet/node
here? That's not going to be the right adapter as node doesn't work with Request
Astro supports several rendering modes, including static
The unfortunate thing about this is that it seems like Astro handles rendering modes transparently and provides a request
object but only makes request.url
available in static mode. This won't work for our SDK.
ArcjetNodeRequest
are you trying to use@arcjet/node
here? That's not going to be the right adapter as node doesn't work withRequest
Yes. It didn't seem right to use one of the other adapters, but using @arcjet/next
works so long as you have server
rendering mode enabled.
astro.config.mjs
import { defineConfig } from 'astro/config';
import vercel from "@astrojs/vercel/serverless";
// https://astro.build/config
export default defineConfig({
output: "server",
adapter: vercel()
});
src/middleware.ts
import { defineMiddleware } from "astro:middleware";
import arcjet, { shield } from "@arcjet/next";
const aj = arcjet({
// Get your site key from https://app.arcjet.com
// and set it as an environment variable rather than hard coding.
key: "ajkey_01hm7kbgdaexeambd6w9fdpy8x",
rules: [
// Protect against common attacks with Arcjet Shield
shield({
mode: "DRY_RUN", // Change to "LIVE" to block requests
}),
],
});
// `context` and `next` are automatically typed
export const onRequest = defineMiddleware(async (context, next) => {
const decision = await aj.protect(context.request);
console.log(decision)
return next();
});
Result:
astro v4.11.4 ready in 82 ms
┃ Local http://localhost:4321/
┃ Network use --host to expose
15:18:47 watching for file changes...
15:18:48 [200] / 18ms
15:18:52 [watch] src/middleware.ts
✦Aj WARN Using 127.0.0.1 as IP address in development mode
ArcjetAllowDecision {
id: 'req_01j1wfcsycfmk8e3jct37rynnm',
ttl: 0,
results: [
ArcjetRuleResult {
ruleId: '',
ttl: 0,
state: 'RUN',
conclusion: 'ALLOW',
reason: [ArcjetShieldReason]
}
],
ip: ArcjetIpDetails {
latitude: undefined,
longitude: undefined,
accuracyRadius: undefined,
timezone: undefined,
postalCode: undefined,
city: undefined,
region: undefined,
country: undefined,
countryName: undefined,
continent: undefined,
continentName: undefined,
asn: undefined,
asnName: undefined,
asnDomain: undefined,
asnType: undefined,
asnCountry: undefined,
service: undefined
},
conclusion: 'ALLOW',
reason: ArcjetShieldReason { type: 'SHIELD', shieldTriggered: false }
}
15:18:52 [200] / 249ms
Yeah, I figured that next or another Request
adapter would "work". However, I don't think it will work in production mode because there's no IP available in the Astro request. We'll need to investigate Astro.clientAddress
to get an IP
Right. This is also working with the Vercel adapter locally, but there are others like Cloudflare and Deno Deploy that will probably need #759 and #758.
There are others like Cloudflare and Deno Deploy that will probably need https://github.com/arcjet/arcjet-js/issues/759 and https://github.com/arcjet/arcjet-js/issues/758.
I hope not. This should just need an Astro adapter. The @arcjet/next
package !== vercel adapter for astro. You are just getting it to work because Request
is fairly standardized.
Astro allows middleware and provides the request information in the
context
. Per the docs, this is a standard Request object.If we try to pass this through to
aj.protect
there is a type error:Note that Astro supports several rendering modes, including static (where middleware doesn't make sense) as well as multiple runtime adapters. So we'll need to make it clear that we require server mode otherwise you get this warning: