Buckets:
ktongue/docker_container / .cache /opencode /node_modules /@fastify /rate-limit /example /example-sequelize.js
| // Example of a Custom Store using Sequelize ORM for PostgreSQL database | |
| // Sequelize Migration for "RateLimits" table | |
| // | |
| // module.exports = { | |
| // up: (queryInterface, { TEXT, INTEGER, BIGINT }) => { | |
| // return queryInterface.createTable( | |
| // 'RateLimits', | |
| // { | |
| // Route: { | |
| // type: TEXT, | |
| // allowNull: false | |
| // }, | |
| // Source: { | |
| // type: TEXT, | |
| // allowNull: false, | |
| // primaryKey: true | |
| // }, | |
| // Count: { | |
| // type: INTEGER, | |
| // allowNull: false | |
| // }, | |
| // TTL: { | |
| // type: BIGINT, | |
| // allowNull: false | |
| // } | |
| // }, | |
| // { | |
| // freezeTableName: true, | |
| // timestamps: false, | |
| // uniqueKeys: { | |
| // unique_tag: { | |
| // customIndex: true, | |
| // fields: ['Route', 'Source'] | |
| // } | |
| // } | |
| // } | |
| // ) | |
| // }, | |
| // down: queryInterface => { | |
| // return queryInterface.dropTable('RateLimits') | |
| // } | |
| // } | |
| const fastify = require('fastify')() | |
| const Sequelize = require('sequelize') | |
| const databaseUri = 'postgres://username:password@localhost:5432/fastify-rate-limit-example' | |
| const sequelize = new Sequelize(databaseUri) | |
| // OR | |
| // const sequelize = new Sequelize('database', 'username', 'password'); | |
| // Sequelize Model for "RateLimits" table | |
| // | |
| const RateLimits = sequelize.define( | |
| 'RateLimits', | |
| { | |
| Route: { | |
| type: Sequelize.TEXT, | |
| allowNull: false | |
| }, | |
| Source: { | |
| type: Sequelize.TEXT, | |
| allowNull: false, | |
| primaryKey: true | |
| }, | |
| Count: { | |
| type: Sequelize.INTEGER, | |
| allowNull: false | |
| }, | |
| TTL: { | |
| type: Sequelize.BIGINT, | |
| allowNull: false | |
| } | |
| }, | |
| { | |
| freezeTableName: true, | |
| timestamps: false, | |
| indexes: [ | |
| { | |
| unique: true, | |
| fields: ['Route', 'Source'] | |
| } | |
| ] | |
| } | |
| ) | |
| function RateLimiterStore (options) { | |
| this.options = options | |
| this.route = '' | |
| } | |
| RateLimiterStore.prototype.routeKey = function routeKey (route) { | |
| if (route) this.route = route | |
| return route | |
| } | |
| RateLimiterStore.prototype.incr = async function incr (key, cb) { | |
| const now = new Date().getTime() | |
| const ttl = now + this.options.timeWindow | |
| const cond = { Route: this.route, Source: key } | |
| const RateLimit = await RateLimits.findOne({ where: cond }) | |
| if (RateLimit && parseInt(RateLimit.TTL, 10) > now) { | |
| try { | |
| await RateLimit.update({ Count: RateLimit.Count + 1 }, cond) | |
| cb(null, { | |
| current: RateLimit.Count + 1, | |
| ttl: RateLimit.TTL | |
| }) | |
| } catch (err) { | |
| cb(err, { | |
| current: 0 | |
| }) | |
| } | |
| } else { | |
| sequelize.query( | |
| `INSERT INTO "RateLimits"("Route", "Source", "Count", "TTL") | |
| VALUES('${this.route}', '${key}', 1, | |
| ${RateLimit?.TTL || ttl}) | |
| ON CONFLICT("Route", "Source") DO UPDATE SET "Count"=1, "TTL"=${ttl}` | |
| ) | |
| .then(() => { | |
| cb(null, { | |
| current: 1, | |
| ttl: RateLimit?.TTL || ttl | |
| }) | |
| }) | |
| .catch(err => { | |
| cb(err, { | |
| current: 0 | |
| }) | |
| }) | |
| } | |
| } | |
| RateLimiterStore.prototype.child = function child (routeOptions = {}) { | |
| const options = Object.assign(this.options, routeOptions) | |
| const store = new RateLimiterStore(options) | |
| store.routeKey(routeOptions.routeInfo.method + routeOptions.routeInfo.url) | |
| return store | |
| } | |
| fastify.register(require('../../fastify-rate-limit'), | |
| { | |
| global: false, | |
| max: 10, | |
| store: RateLimiterStore, | |
| skipOnError: false | |
| } | |
| ) | |
| fastify.get('/', { | |
| config: { | |
| rateLimit: { | |
| max: 10, | |
| timeWindow: '1 minute' | |
| } | |
| } | |
| }, (_req, reply) => { | |
| reply.send({ hello: 'from ... root' }) | |
| }) | |
| fastify.get('/private', { | |
| config: { | |
| rateLimit: { | |
| max: 3, | |
| timeWindow: '1 minute' | |
| } | |
| } | |
| }, (_req, reply) => { | |
| reply.send({ hello: 'from ... private' }) | |
| }) | |
| fastify.get('/public', (_req, reply) => { | |
| reply.send({ hello: 'from ... public' }) | |
| }) | |
| fastify.listen({ port: 3000 }, err => { | |
| if (err) throw err | |
| console.log('Server listening at http://localhost:3000') | |
| }) | |
Xet Storage Details
- Size:
- 4.14 kB
- Xet hash:
- 2e61b1bb52aac03c0d57e3c4c6623d189b6073882e5a6e72aeea0ed4ae361d0a
·
Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.