diff --git a/README.md b/README.md index d694c6c..0a891a9 100644 --- a/README.md +++ b/README.md @@ -25,6 +25,8 @@ $ npm i @nestlab/google-recaptcha secretKey: process.env.GOOGLE_RECAPTCHA_SECRET_KEY, response: req => req.headers.recaptcha, skipIf: () => process.env.NODE_ENV !== 'production', + useRecaptchaNet: false, + agent: null }) ], }) @@ -32,6 +34,17 @@ export class AppModule { } ``` +**Configuration options** + +| Property | | Type | Description | +|-------------------|---|----------------------------|-------------| +| `secretKey` | ✔ | string | Google recaptcha secret key | +| `response` | ✔ | (request) => string | Function that returns response (recaptcha token) by request | +| `skipIf` | ✖ | () => boolean | Function that returns true if you need skip check for development or testing | +| `useRecaptchaNet` | ✖ | boolean | If your server has trouble connecting to https://www.google.com. You can use https://recaptcha.net instead, just set true | +| `agent` | ✖ | https.Agent | If you need to use an agent | + + If you want import configs from your [ConfigService](https://docs.nestjs.com/techniques/configuration#getting-started) via [custom getter function](https://docs.nestjs.com/techniques/configuration#custom-getter-functions) that will return `GoogleRecaptchaModuleOptions` object. ```typescript diff --git a/package.json b/package.json index 6c6bfcd..4096f3b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@nestlab/google-recaptcha", - "version": "1.1.3", + "version": "1.1.4", "description": "Google recaptcha module for NestJS.", "keywords": [ "nest", diff --git a/src/interfaces/google-recaptcha-validator-options.ts b/src/interfaces/google-recaptcha-validator-options.ts index bcf07f2..9ea5fc8 100644 --- a/src/interfaces/google-recaptcha-validator-options.ts +++ b/src/interfaces/google-recaptcha-validator-options.ts @@ -1,3 +1,15 @@ +import * as https from "https"; + export interface GoogleRecaptchaValidatorOptions { secretKey: string; + /** + * If your server has trouble connecting to https://www.google.com, + * set it to `true` to use https://recaptcha.net instead. + */ + useRecaptchaNet?: boolean; + /** + * If your server has trouble connecting to https://www.google.com, + * you can use an agent (`proxy-agent` or other NPM modules) + */ + agent?: https.Agent; } diff --git a/src/services/google-recaptcha.validator.ts b/src/services/google-recaptcha.validator.ts index f2a7465..1358f03 100644 --- a/src/services/google-recaptcha.validator.ts +++ b/src/services/google-recaptcha.validator.ts @@ -8,6 +8,7 @@ import { ErrorCode } from '../enums/error-code'; @Injectable() export class GoogleRecaptchaValidator { private readonly apiUrl = 'https://www.google.com/recaptcha/api/siteverify'; + private readonly apiUrlUseRecaptchaNet = 'https://recaptcha.net/recaptcha/api/siteverify'; private readonly headers = {'Content-Type': 'application/x-www-form-urlencoded'}; constructor(private readonly http: HttpService, @@ -17,7 +18,13 @@ export class GoogleRecaptchaValidator { validate(response: string): Promise { const data = qs.stringify({secret: this.options.secretKey, response}); - return this.http.post(this.apiUrl, data, {headers: this.headers}) + const url = this.options.useRecaptchaNet ? this.apiUrlUseRecaptchaNet : this.apiUrl; + + return this.http.post(url, data, { + headers: this.headers, + httpsAgent: this.options.agent + } + ) .toPromise() .then(res => res.data) .then(result => ({ diff --git a/test/google-recaptcha-async-module.spec.ts b/test/google-recaptcha-async-module.spec.ts index 932b036..8ac693a 100644 --- a/test/google-recaptcha-async-module.spec.ts +++ b/test/google-recaptcha-async-module.spec.ts @@ -17,6 +17,8 @@ export class TestConfigService { secretKey: 'secret', response: req => req.body.recaptcha, skipIf: () => true, + useRecaptchaNet: false, + agent: null }; } } diff --git a/test/google-recaptcha-module.spec.ts b/test/google-recaptcha-module.spec.ts index c8dae04..eb1b30f 100644 --- a/test/google-recaptcha-module.spec.ts +++ b/test/google-recaptcha-module.spec.ts @@ -3,6 +3,9 @@ import { INestApplication } from '@nestjs/common'; import { GoogleRecaptchaValidator } from '../src/services/google-recaptcha.validator'; import { GoogleRecaptchaGuard } from '../src/guards/google-recaptcha.guard'; import { GoogleRecaptchaModule } from '../src/google-recaptcha.module'; +import { Agent } from 'https'; +import { RECAPTCHA_OPTIONS } from '../src/provider.declarations'; +import { GoogleRecaptchaModuleOptions } from '../src'; describe('Google recaptcha module', () => { let app: INestApplication; @@ -14,7 +17,9 @@ describe('Google recaptcha module', () => { secretKey: process.env.GOOGLE_RECAPTCHA_SECRET_KEY, response: req => req.headers.authorization, skipIf: () => process.env.NODE_ENV !== 'production', - }) + useRecaptchaNet: true, + agent: new Agent({maxFreeSockets: 10}), + }), ], }).compile(); @@ -32,4 +37,14 @@ describe('Google recaptcha module', () => { expect(guard).toBeInstanceOf(GoogleRecaptchaGuard); }); + + test('Test use recaptcha net options', async () => { + const options: GoogleRecaptchaModuleOptions = app.get(RECAPTCHA_OPTIONS); + + expect(options).toBeDefined(); + expect(options.useRecaptchaNet).toBeTruthy(); + expect(options.agent).toBeDefined(); + expect(options.agent).toBeInstanceOf(Agent); + expect(options.agent.maxFreeSockets).toBe(10); + }); });