diff --git a/public/demo/globals.js b/public/demo/globals.js index 3461213d..306d74c7 100644 --- a/public/demo/globals.js +++ b/public/demo/globals.js @@ -19,4 +19,4 @@ const ALLOWED_MTR_PROTOCOLS = [ 'TCP', 'UDP', 'ICMP' ]; // http const ALLOWED_HTTP_PROTOCOLS = [ 'HTTP', 'HTTPS', 'HTTP2' ]; -const ALLOWED_HTTP_METHODS = [ 'GET', 'HEAD' ]; +const ALLOWED_HTTP_METHODS = [ 'GET', 'HEAD', 'OPTIONS' ]; diff --git a/public/v1/components/schemas.yaml b/public/v1/components/schemas.yaml index 61402384..69434b25 100644 --- a/public/v1/components/schemas.yaml +++ b/public/v1/components/schemas.yaml @@ -449,6 +449,7 @@ components: enum: - HEAD - GET + - OPTIONS default: HEAD headers: type: object diff --git a/src/measurement/schema/command-schema.ts b/src/measurement/schema/command-schema.ts index acdeb95e..151e0241 100644 --- a/src/measurement/schema/command-schema.ts +++ b/src/measurement/schema/command-schema.ts @@ -49,7 +49,7 @@ export const ipVersionDnsSchema = Joi.number().when(Joi.ref('resolver'), { export const validCmdTypes = [ 'ping', 'dns', 'traceroute', 'mtr', 'http' ]; const allowedHttpProtocols = [ 'HTTP', 'HTTPS', 'HTTP2' ]; -const allowedHttpMethods = [ 'GET', 'HEAD' ]; +const allowedHttpMethods = [ 'GET', 'HEAD', 'OPTIONS' ]; // Http const httpTargetSchema = Joi.alternatives() diff --git a/src/measurement/types.ts b/src/measurement/types.ts index 058a76ca..fbfadb75 100644 --- a/src/measurement/types.ts +++ b/src/measurement/types.ts @@ -126,7 +126,7 @@ type DnsResult = TestResult & (DnsRegularResult | DnsTraceResult); type HttpTest = { request: { - method: 'HEAD' | 'GET'; + method: 'HEAD' | 'GET' | 'OPTIONS'; host?: string; path: string; query: string; diff --git a/test/e2e/cases/http.test.ts b/test/e2e/cases/http.test.ts index e81243f7..f5dfec59 100644 --- a/test/e2e/cases/http.test.ts +++ b/test/e2e/cases/http.test.ts @@ -36,6 +36,25 @@ describe('http measurement', () => { expect(response).to.matchApiSchema(); }); + it('should finish successfully in case of OPTIONS request', async () => { + const { id } = await got.post('http://localhost:80/v1/measurements', { json: { + target: 'www.jsdelivr.com', + type: 'http', + measurementOptions: { + request: { + method: 'OPTIONS', + }, + }, + } }).json(); + + const response = await waitMeasurementFinish(id); + + expect(response.body.status).to.equal('finished'); + expect(response.body.results[0].result.status).to.equal('finished'); + expect(response.body.results[0].result.rawBody.length).to.be.above(0); + expect(response).to.matchApiSchema(); + }); + it('should finish successfully in case of IPv6 domain target', async () => { const { id } = await got.post('http://localhost:80/v1/measurements', { json: { target: 'www.jsdelivr.com', diff --git a/test/tests/unit/measurement/schema/schema.test.ts b/test/tests/unit/measurement/schema/schema.test.ts index 74ceae03..4e2cacf5 100644 --- a/test/tests/unit/measurement/schema/schema.test.ts +++ b/test/tests/unit/measurement/schema/schema.test.ts @@ -2109,7 +2109,7 @@ describe('command schema', async () => { const valid = globalSchema.validate(input, { convert: true }); expect(valid.error).to.exist; - expect(valid.error!.message).to.equal('"measurementOptions.request.method" must be one of [GET, HEAD]'); + expect(valid.error!.message).to.equal('"measurementOptions.request.method" must be one of [GET, HEAD, OPTIONS]'); }); it('should fail (unsupported protocol)', () => {