Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add linter plugin to check for array responses
- Loading branch information
Mike Kistler
committed
Feb 15, 2018
1 parent
3b40d65
commit 922394f
Showing
5 changed files
with
139 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -7,6 +7,10 @@ | |
# Swift | ||
.build | ||
Packages | ||
# Node | ||
node_modules | ||
package-lock.json | ||
bundle.json | ||
# vi | ||
*.swp | ||
# vscode | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
|
||
GNOSTIC = $(GOPATH)/src/github.com/googleapis/gnostic | ||
|
||
plugin: | ||
node_modules/.bin/pbjs -t json \ | ||
$(GNOSTIC)/OpenAPIv2/OpenAPIv2.proto \ | ||
$(GNOSTIC)/OpenAPIv3/OpenAPIv3.proto \ | ||
$(GNOSTIC)/discovery/discovery.proto \ | ||
$(GNOSTIC)/surface/surface.proto \ | ||
$(GNOSTIC)/plugins/plugin.proto \ | ||
> bundle.json | ||
node_modules/.bin/nexe gnostic-lint-responses.js | ||
mv gnostic-lint-responses $(GOPATH)/bin | ||
|
||
run: plugin | ||
gnostic $(GNOSTIC)/examples/v2.0/yaml/petstore.yaml --lint-responses | ||
|
||
setup: | ||
npm install |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
This directory contains a gnostic linter written with node. | ||
|
||
It is built using [dcodeIO/Protobuf.js](https://github.com/dcodeIO/ProtoBuf.js). | ||
|
||
### SETUP | ||
|
||
- Install node. | ||
- Run `make setup` to install node dependencies. | ||
|
||
### TRY IT | ||
|
||
- Run `make run` to test-run the plugin. | ||
|
||
|
||
|
83 changes: 83 additions & 0 deletions
83
linters/node/gnostic-lint-responses/gnostic-lint-responses.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,83 @@ | ||
// import libraries | ||
const protobuf = require("protobufjs"); | ||
const getStdin = require("get-stdin"); | ||
const find = require("lodash/find"); | ||
const forEach = require("lodash/forEach"); | ||
const pick = require("lodash/pick"); | ||
|
||
// import messages | ||
const root = protobuf.Root.fromJSON(require("./bundle.json")); | ||
const Request = root.lookupType("gnostic.plugin.v1.Request"); | ||
const Response = root.lookupType("gnostic.plugin.v1.Response"); | ||
const Document = root.lookupType("openapi.v2.Document"); | ||
|
||
getStdin.buffer().then(buffer => { | ||
const request = Request.decode(buffer); | ||
var messages = []; | ||
for (var j in request.models) { | ||
const m = request.models[j]; | ||
if (m.type_url == "openapi.v2.Document") { | ||
const openapi2 = Document.decode(m.value); | ||
const paths = openapi2.paths.path; | ||
for (var i in paths) { | ||
const path = paths[i]; | ||
// console.error('path %s\n\n', path.name) | ||
|
||
// Arrays MUST NOT be returned as the top-level structure in a response body. | ||
let pathOps = pick(path.value, ["get","head","post", "put", "patch", "delete", "options"]); | ||
forEach(pathOps, (op, opKey) => { | ||
if (op != null) { | ||
forEach(op.responses.responseCode, responseObj => { | ||
// console.error('responseObj is %j', responseObj) | ||
name = responseObj.name; | ||
response = responseObj.value.response; | ||
if (response.schema && response.schema.schema) { | ||
if (!response.schema.schema._ref) { | ||
if ( | ||
response.schema.schema.type != null && | ||
response.schema.schema.type.value == "array" | ||
) { | ||
messages.push({ | ||
level: 3, | ||
code: "NO_ARRAY_RESPONSES", | ||
text: "Arrays MUST NOT be returned as the top-level structure in a response body.", | ||
keys: ["paths", path.name, opKey, "responses", name, "schema"] | ||
}); | ||
} | ||
} else { | ||
let schemaName = response.schema.schema._ref.match(/#\/definitions\/(\w+)/); | ||
if (schemaName) { | ||
const definitions = openapi2.definitions.additionalProperties; | ||
const schemaKvp = find(definitions, {name: schemaName[1] | ||
}); | ||
//console.error('schemaKvp.value.type = %s', schemaKvp.value.type.value) | ||
if (schemaKvp && schemaKvp.value.type && schemaKvp.value.type.value.indexOf("array") >= 0) { | ||
messages.push({ | ||
level: 3, | ||
code: "NO_ARRAY_RESPONSES", | ||
text: "Arrays MUST NOT be returned as the top-level structure in a response body.", | ||
keys: ["paths", path.name, opKey, "responses", name, "schema" ] | ||
}); | ||
} | ||
} | ||
} | ||
} | ||
}); | ||
} | ||
}); | ||
} | ||
} | ||
} | ||
|
||
const payload = { | ||
messages: messages | ||
}; | ||
|
||
// Verify the payload if necessary (i.e. when possibly incomplete or invalid) | ||
const errMsg = Response.verify(payload); | ||
if (errMsg) throw Error(errMsg); | ||
|
||
const message = Response.create(payload); | ||
process.stdout.write(Response.encode(message).finish()); | ||
}) | ||
.catch(err => console.error(err)); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
{ | ||
"name": "gnostic-lint-responses", | ||
"version": "1.0.0", | ||
"description": "Gnostic linter plugin to check responses", | ||
"main": "gnostic-lint-responses.js", | ||
"dependencies": { | ||
"get-stdin": "^5.0.1", | ||
"lodash": "^4.17.5", | ||
"nexe": "^2.0.0-rc.24", | ||
"protobufjs": "^6.8.4" | ||
}, | ||
"devDependencies": {}, | ||
"scripts": { | ||
"test": "echo \"Error: no test specified\" && exit 1" | ||
}, | ||
"author": "", | ||
"license": "ISC" | ||
} |