Skip to content

Commit

Permalink
fix: Fix issue where we assumed json-ptrs were always in URI fragment…
Browse files Browse the repository at this point in the history
… format.

This introduces two fixes; first `jsonPaths.jsonPointerStripPrefix()`
will now try to preserve the format of a json-ptr (i.e. if you give it a
pointer in URI fragment format, it will return a pointer in URI fragment
format.)  Second, in src/oas3/Schema/validators, if we find a json-ptr
that isn't in URI fragment format, we'll treat it properly, and convert
it.

fix #132
  • Loading branch information
jwalton committed Mar 4, 2020
1 parent 280ab88 commit 4992f95
Show file tree
Hide file tree
Showing 19 changed files with 107 additions and 16 deletions.
25 changes: 25 additions & 0 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"type": "node",
"request": "launch",
"name": "Run Current Mocha Test",
"program": "${workspaceFolder}/node_modules/mocha/bin/_mocha",
"protocol": "inspector",
"smartStep": true,
"sourceMaps": true,
"outputCapture": "std",
"args": ["--colors", "${relativeFile}"],
"env": {
"RUN_FROM_SRC": "true",
"NODE_ENV": "test",
"SETUP_DOM": "true"
},
"internalConsoleOptions": "openOnSessionStart"
}
]
}
7 changes: 4 additions & 3 deletions @types/json-ptr/index.d.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
declare module 'json-ptr' {
export function encodePointer(path: string[]) : string;
export function decode(pointer: string) : string[];
}
export function encodePointer(path: string[]): string;
export function decode(pointer: string): string[];
export function encodeUriFragmentIdentifier(path: string[]): string;
}
9 changes: 7 additions & 2 deletions src/oas3/Schema/validators.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,10 @@ import Ajv from 'ajv';
import traveseSchema from 'json-schema-traverse';
import { CustomFormats, IValidationError, ParameterLocation, ValidatorFunction } from '../../types';
import { resolveRef } from '../../utils/json-schema-resolve-ref';
import * as jsonPaths from '../../utils/jsonPaths';
import * as jsonSchema from '../../utils/jsonSchema';
import Oas3CompileContext from '../Oas3CompileContext';
import { MimeTypeRegistry } from '../../utils/mime';
import Oas3CompileContext from '../Oas3CompileContext';

// urlencoded and form-data requests do not contain any type information;
// for example `?foo=9` doesn't tell us if `foo` is the number 9, or the string
Expand Down Expand Up @@ -199,7 +200,11 @@ function generateValidator(
// So that we can replace the "root" value of the schema using ajv's type coercion...
traveseSchema(schema, node => {
if (node.$ref) {
node.$ref = `#/properties/value/${node.$ref.slice(2)}`;
if (node.$ref.startsWith('#')) {
node.$ref = `#/properties/value/${node.$ref.slice(2)}`;
} else {
node.$ref = jsonPaths.toUriFragment(`/properties/value/${node.$ref.slice(1)}`);
}
}
});
schema = {
Expand Down
12 changes: 11 additions & 1 deletion src/utils/jsonPaths.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,27 @@ function normalize(path: string): string {
return jsonPtr.encodePointer(jsonPtr.decode(path));
}

export function toUriFragment(path: string) {
return jsonPtr.encodeUriFragmentIdentifier(jsonPtr.decode(path));
}

export function jsonPointerStartsWith(path: string, prefix: string): boolean {
path = normalize(path);
prefix = normalize(prefix);
return path.startsWith(prefix);
}

export function jsonPointerStripPrefix(path: string, prefix: string): string {
const isUriFragment = path.startsWith('#');
path = normalize(path);
prefix = normalize(prefix);
if (path.startsWith(prefix)) {
return path.slice(prefix.length);
const answer = path.slice(prefix.length);
if (isUriFragment) {
return toUriFragment(answer);
} else {
return answer;
}
} else {
return path;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import * as exegesis from '../../../src';
import * as exegesis from '../../../../src';

export function echo(context: exegesis.ExegesisContext) {
return context.req.body;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { ExegesisContext } from '../../../src';
import { ExegesisContext } from '../../../../src';

export function greetGet(context: ExegesisContext) {
const { name } = context.params.query;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { ExegesisContext } from '../../../src';
import { ExegesisContext } from '../../../../src';

export function getBadResponse(_context: ExegesisContext) {
return { wat: 7 };
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { ExegesisContext } from '../../../src';
import { ExegesisContext } from '../../../../src';

export function postWithDefault(context: ExegesisContext) {
const { name } = context.requestBody;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { ExegesisContext } from '../../../src';
import { ExegesisContext } from '../../../../src';

export function postWithOptionalBody(context: ExegesisContext) {
const hasBody = !!context.requestBody;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { ExegesisContext } from '../../../src';
import { ExegesisContext } from '../../../../src';

export function setStatus(context: ExegesisContext) {
context.res.setStatus(400);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import * as http from 'http';
import * as path from 'path';
import { makeFetch } from 'supertest-fetch';
import * as exegesis from '../../src';
import * as exegesis from '../../../src';
import { handleError } from './customErrorHandler';

async function sessionAuthenticator(
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import stringToStream from '../../src/utils/stringToStream';
import { ValidationError } from '../../src/errors';
import stringToStream from '../../../src/utils/stringToStream';
import { ValidationError } from '../../../src/errors';

export function handleError(err: Error) {
if (err instanceof ValidationError) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { expect } from 'chai';
import * as http from 'http';
import * as path from 'path';
import { makeFetch } from 'supertest-fetch';
import * as exegesis from '../../src';
import * as exegesis from '../../../src';

async function sessionAuthenticator(
context: exegesis.ExegesisPluginContext
Expand Down
File renamed without changes.
22 changes: 22 additions & 0 deletions test/integration/issue-132/entry.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# entry.yaml
paths:
Entry:
get:
operationId: fetch
responses:
default:
description: Recursive entry.
content:
application/json:
schema:
type: object
properties:
entry:
$ref: '#/components/schemas/Recurse'
components:
schemas:
Recurse:
type: object
properties:
recurse:
$ref: '#/components/schemas/Recurse'
9 changes: 9 additions & 0 deletions test/integration/issue-132/issue132Test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
// import { expect } from 'chai';
import * as path from 'path';
import * as exegesis from '../../../src';

describe('Issue 132 test', function() {
it('should load a yaml file with recursive definitions', async function() {
await exegesis.compileApi(path.resolve(__dirname, './openapi.yaml'), {});
});
});
7 changes: 7 additions & 0 deletions test/integration/issue-132/openapi.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
openapi: 3.0.1
info:
title: Demo API
version: 1.0.0
paths:
/entry:
$ref: 'entry.yaml#/paths/Entry'
12 changes: 12 additions & 0 deletions test/utils/jsonPathsTest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,16 @@ describe('jsonPaths utils', function() {
it('should strip prefix', function() {
expect(jsonPaths.jsonPointerStripPrefix('/foo/bar', '/foo')).to.equal('/bar');
});

it('should strip prefix. but preserve URI fragment format', function() {
expect(jsonPaths.jsonPointerStripPrefix('#/foo/bar', '/foo')).to.equal('#/bar');
});

it('should convert a JSON pointer in string representation to URI fragment representation', function() {
expect(jsonPaths.toUriFragment('/foo/bar')).to.equal('#/foo/bar');
});

it('should convert a JSON pointer in URI fragment representation to URI fragment representation', function() {
expect(jsonPaths.toUriFragment('#/foo/bar')).to.equal('#/foo/bar');
});
});

0 comments on commit 4992f95

Please sign in to comment.