Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feature: add server validation the Http Client #351

Merged
merged 35 commits into from Jun 14, 2019

Conversation

chris-miaskowski
Copy link
Contributor

@chris-miaskowski chris-miaskowski commented Jun 12, 2019

This PR adds server validation the Prism Http Server and Prism Http Client.

What changed?

We have exposed a query parameter __server that you can use to check whether the server matches the one in the spec.

This is now supported in the CLI

prism mock spec.json
curl -X GET /pet?__server=http://someserver.com/basePath

and in the JS-API

prism.process({
   url: {
      baseUrl: 'http://xyz.com/api'
   }
})

More details in the README.md file

@chris-miaskowski
Copy link
Contributor Author

@XVincentX @philsturgeon @lag-of-death
Feel free to start reviewing folks. I have to add a bunch of e2e tests and update the readme but other than that it's done.

Pay special attention to tests so see whether we're all in alignment.

@XVincentX
Copy link
Contributor

@chris-miaskowski I fixed the build for you.

@@ -63,36 +63,42 @@ export const router: IRouter<IHttpOperation, IHttpRequest, IHttpConfig> = {
};
});

matches = matches.filter(match => match.pathMatch !== MatchType.NOMATCH);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this route function is so long and full of ifs, mutations and throwing errors. The cognitive load one has to invest to understand it is a bit too much. Can this be refactored before it's too late?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I want to ditch it completely and use a routing library, such as https://github.com/delvedor/find-my-way

Happy to see this refactored though.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@XVincentX to your point on the library I'm happy to replace the code if you find a library that does what we need. We have a very special use case here - we not only route but check the server validity.

@lag-of-death I'm happy to see what I can do if you can suggest a refactoring.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

at least we could move all these ifs that throw errors and make an array of "tuples" like so:
[{predicate: () => false, action: () => throw 'A'}, {predicate: () => true, action: () => throw 'B'}]
and move this array out of route

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey I'd like to leave that for some other time. I'm usually all for boy scouting but lots of things will change in the code base in next weeks/months so that may soon be irrelevant.

@XVincentX
Copy link
Contributor

P.S: I'm jumping on this in the afternoon.

README.md Outdated Show resolved Hide resolved
README.md Outdated Show resolved Hide resolved
@chris-miaskowski
Copy link
Contributor Author

Thanks for the review everyone! I hear you all!
As much as I'd love to clean up the code I'm not sure if I will have the time to boyscout it now.
Will see what I can do but the priority for me now is to get the feature in.

README.md Outdated Show resolved Hide resolved
Copy link
Contributor

@XVincentX XVincentX left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've added a first batch. I want to have a second look though

CONTRIBUTING.md Outdated Show resolved Hide resolved
README.md Outdated Show resolved Hide resolved
README.md Outdated Show resolved Hide resolved
README.md Outdated Show resolved Hide resolved
README.md Outdated Show resolved Hide resolved
examples/petstore.oas3.json Show resolved Hide resolved
packages/http/package.json Outdated Show resolved Hide resolved
packages/http/src/__tests__/http-prism-instance.spec.ts Outdated Show resolved Hide resolved
packages/http/src/forwarder/HttpForwarder.ts Show resolved Hide resolved
Chris Miaskowski and others added 21 commits June 14, 2019 10:07
…htio/prism into feature/so-257/server-validation
…htio/prism into feature/so-257/server-validation
Co-Authored-By: Phil Sturgeon <me@philsturgeon.uk>
Co-Authored-By: Vincenzo Chianese <vincenz.chianese@icloud.com>
Co-Authored-By: Vincenzo Chianese <vincenz.chianese@icloud.com>
…htio/prism into feature/so-257/server-validation
- don't embarrass yourself Chris! Read the docs!

SO-257
…htio/prism into feature/so-257/server-validation
Copy link
Contributor

@XVincentX XVincentX left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some suggestions, but I think this is good to go.

I'd probably avoid the string comparison and parse the content instead, but it shouldn't be blocking this from being merged.

#### Server Validation

OpenAPI lets API spec authors make only certain servers available, and they also allow certain operations to be restricted to certain servers. Make sure the server URL you plan to use is a valid server this the particular operation you are attempting.
by providing a `__server` query param.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess this should be on the same line

packages/core/src/factory.ts Show resolved Hide resolved
@@ -37,23 +39,41 @@ export function factory<Resource, Input, Output, Config, LoadOpts>(
// build the config for this request
const configMerger = configMergerFactory(defaultConfig, customConfig, c);
const configObj: Config | undefined = configMerger(input);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is probably an old leftover.

Suggested change
const configObj: Config | undefined = configMerger(input);
const configObj: Config = configMerger(input);

});

const expectedPayload = (serverUrl: string) =>
`{"type":"https://stoplight.io/prism/errors#NO_SERVER_MATCHED_ERROR","title":"Route not resolved, no server matched.","status":404,"detail":"The base url ${serverUrl} hasn\'t been matched with any of the provided servers"}`;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm wondering if there's a way to check out this stuff without using this templated string.


expect(response.statusCode).toBe(422);
expect(response.payload).toEqual(
'{"type":"https://stoplight.io/prism/errors#UNPROCESSABLE_ENTITY","title":"Invalid request body payload","status":422,"detail":"Your request body is not valid: [{\\"path\\":[\\"body\\"],\\"code\\":\\"type\\",\\"message\\":\\"should be object\\",\\"severity\\":0}]"}',
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, it might be worth parse this content

expect(response.payload).toEqual(
'{"type":"https://stoplight.io/prism/errors#UNPROCESSABLE_ENTITY","title":"Invalid request body payload","status":422,"detail":"Your request body is not valid: [{\\"path\\":[\\"body\\"],\\"code\\":\\"type\\",\\"message\\":\\"should be object\\",\\"severity\\":0}]"}',
);
await server.fastify.close();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be in a after statement

@@ -228,6 +295,67 @@ describe.each([['petstore.oas2.json'], ['petstore.oas3.json']])('server %s', fil
}
});

describe('server validation: given __server query param', () => {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

According to Phil (or at least, if I understood correctly), these should be two nested describe blocks

});

// oas2 does not support overriding servers
if (file === 'petstore.oas3.json') {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is ok for now, but maybe we could have oas3 specific tests instead of branching

@chris-miaskowski chris-miaskowski merged commit 6f1ece9 into master Jun 14, 2019
@chris-miaskowski chris-miaskowski deleted the feature/so-257/server-validation branch June 14, 2019 13:30
On the other hand, putting a server which is not defined in the specification, for example:

```bash
curl -X GET localhost:4010/pet?__server=ftp://acme.com/api
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh this is weird that we introduced FTP here just without any explanation, just snuck it in there. I honestly do not know if FTP is even allowed in OpenAPI, it doesn't mentioned either way but... it has never come up. https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.0.md#serverObject

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants