Coder Social home page Coder Social logo

open-api's Introduction

@open-api Coveralls Status

A Monorepo of various packages to power OpenAPI in node.

Quick Start Express

Quick Start Koa

Packages

Development

This monorepo uses lerna for development. See the root package.json for helpful scripts.

Typical Workflow for Contributors

Let's say you're working on a package under ./packages. Here's what you do:

  1. cd open-api
  2. npm run bootstrap
  3. npm t
  4. Make your changes.
  5. Do not bump the version in package.json. A maintainer will handle that once your PR is merged.
  6. Once you're satisfied with your changes:
  7. Create a new branch git checkout -b my-branch (in case you haven't done so already).
  8. ./bin/commit packages/<package_you're_working_on> 'commit message describing your change. can be multi line here. just close with a single quote like so:'
  9. Push your change to your fork
  10. Open a PR.

bin

Several scripts have been created to aid in the development of this monorepo (see ./bin). They assume that your $PWD is the root of the repository. Here is a brief summary of common actions:

  • Commit changes to a package - ./bin/commit packages/<package_to_commit> 'Commit message' (the commit message will be prepended with the package name e.g. <package_to_commit>: Commit message
  • These reduce boilerplate and are called from npm scripts in leaf repos.
    • nyc
    • tsc
    • mocha

LICENSE

The MIT License (MIT)

Copyright (c) 2018 Kogo Software LLC

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

open-api's People

Contributors

alexholly avatar alrik avatar asarver avatar bcrastnopol avatar bill-kitsune avatar dependabot[bot] avatar dmatteo avatar greenkeeper[bot] avatar jjdonov avatar jsau- avatar jsdevel avatar kanreisa avatar keijokapp avatar koocbor avatar manny651 avatar maxime-morand avatar mbsimonovic avatar medfreeman avatar mghignet avatar mika-fischer avatar mugeso avatar nulltoken avatar phillip-hall avatar rthunbo avatar seb-pereira avatar sebasmagri avatar troymolsberry avatar tuckerwhitehouse avatar wszydlak avatar xuluwarrior avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

open-api's Issues

Possibility to separate openapi-spec from http-controller

As far as i can see, the execution of any middleware like parameter validation happens based on the apiDoc property of a single http endpoint / route.

module.exports.GET = () => {} // handler
module.exports.GET.apiDoc = {} // open api route schema

It would be nice if express-openapi could fallback to path-definitions passed to the initialize({ apiDoc }) routine.

That way the developer could choose between having the route-handler and the api-spec in one file or separated.

I'd like to run the following setup:

api.js // openapi.initialize({ apiDoc: loadOpenApiSpec({ path: './' }), paths: './'})
api-doc.yml // swagger: 2.0 ...
paths/some-route/resource.js // module.export.GET = (req, res) => { ... }
paths/some-route/resource.yml // paths: { /some-route/resource: { get: { ... } } }

I would like to load and assemble the whole open-api spec with all path definitions just before passing it to initialize.

const { sync: globSync } = require('glob');
const deepAssign = require('deep-assign');
const fs = require('fs');
const yaml = require('js-yaml');

module.exports = function loadOpenApiSpec({ version, path, specGlob = '/**/*.yml' }) {
  const files = globSync(specGlob, {root: path});

  const spec = {};

  files.forEach((file) => {
    deepAssign(spec, yaml.safeLoad(fs.readFileSync(file, 'utf8')));
  });

  spec.info.version = version;

  return spec;
};

So my idea is to keep backwards compatibility and to allow for populating the "global" spec down to a specific route.

@jsdevel I could submit a PR if you like the idea.

validation error for formData type boolean

Given the following operation definition

{
    post: {
        summary: 'Application information',
        operationId: 'info',
        tags: ['/info'],
        parameters: [
            {
                name: 'booleanParam',
                in: 'formData',
                required: true,
                type: 'boolean',
                default: false
            }
        ],
        responses: {
            200: {
                description: 'Success',
                schema: {
                    $ref: '#/definitions/Success'
                }
            },
            default: {
                description: 'Error',
                schema: {
                    $ref: '#/definitions/Error'
                }
            }
        }
    }
}

and then calling using the following
curl -X POST --header 'Content-Type: application/x-www-form-urlencoded' --header 'Accept: text/html' -d 'booleanParam=false' 'http://localhost:3200/api/info'

the following error is returned
error: status=400, errors=[path=booleanParam, errorCode=type.openapi.validation, message=instance.booleanParam is not of a type(s) boolean, location=body]

Support external schema reference

Problem

Now my api receives json schema object.

so, i wrote:

// in handler
post.apiDoc = {
    description: "create new schema definition",
    operationId: "createSchema",
    parameters: [
        {
            in: 'body',
            name: 'schema',
            schema: {$ref: '#/definitions/schema' }
        }
    ],
    responses: {
        "201": { $ref: '#/responses/created' },
        "default": { $ref: "#/responses/error" }
    }
}

// in apidoc.js#definitions
{ 
    "schema": { "$ref": "http://json-schema.org/schema" }
}  

Then i sent request to it and got:

{
    "status":400,
    "errors":[
        {
            "message":"no such schema <http://json-schema.org/schema>",
            "schema":{"$ref":"http://json-schema.org/schema"},
            "location":"body"
        }
    ]
}

Suggestion

  1. support external schema
  2. support maping external id to local file (for when can not connect to server hosting the external schema or the url don't serve schema json.)
  3. keep external reference as is in exposed api doc, not expanded loaded schema.

Have case insensitive query parameters

I know this is kind of against the open api documentation, but we are moving legacy public endpoints from .net (query params are case insensitive), and right now we have to disable input validation using "x-express-openapi-disable-validation-middleware", and then we read the parameters by below function:

export function getCaseInsensitiveProperty(query: any, property: string): any {
    for (let p in query) {
        if (query.hasOwnProperty(p) && property.toLowerCase() === p.toLowerCase()) {
            return query[p];
        }
    }
    return null;
}

Meaning we can't benefit from validation rules we already wrote in the open api spec.

Any thoughts on this one?

BTW Great work.

Request validation sending [object Object] in Express response

If I'm not mistaken, express-openapi is using express-openapi-validation by default and will validate requests to endpoints when the endpoint has given a value to the apiDoc parameter.

The validation is working correctly, but the response that a user receives is not helpful. Below is an example of what I get when hitting an endpoint with an improper request using Postman:

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="utf-8">
        <title>Error</title>
    </head>
    <body>
        <pre>[object Object]</pre>
    </body>
</html>

Providing a custom errorTransformer function when initializing express-openapi doesn't solve the issue.

I've done some debugging and tracing and believe this issue is being caused by the way express-openapi-validation formats the error object it passes into next(). In short, the error object does not have a stack property and so toString() is called on the object before sending it out, resulting in the [object Object] we see in the response.

Maybe I'm missing some fundamental solution here, but it would be much nicer to have the response sent back as JSON, or at the very least a message that simply says "Incorrect data format received."

I can go into further detail and provide example code another time if you'd like.

Alterative route declaration

The only thing I don't like about express-openapi is the "convention based programming", I found very confusing and limiting.

I would prefer a simple javascript api doc with embedded handlers.

openapi.initialize({
    app: app,
    swagger: '2.0',
    basePath: '/v1',
    info: {
        title: 'App',
        version: '1.0.0',
    },
    paths: {
        '/users': {
            get: {
                parameters: [],
                responses: {
                    200: {
                        description: 'Get all users',
                        schema: {
                            type: 'array',
                            items: {
                                title: 'User',
                                type: 'object',
                                properties: {
                                    name: {
                                        type: 'string'
                                    }
                                }
                            },
                        }
                    }
                },
                handler(req, res) {
                    res.json([{name: 'Dale'}]);
                }
            },
            post: {
                handler(req, res) {
                    res.status(201);
                }
            }
        },
        '/users/{userId}': {
            get: {
                handler(req, res) {
                    res.json({name: 'Dale'});
                }
            }
        }
    }
});

You can use modules to split up the code, you have the full javascript language to generate routes or do whatever you like.

openapi.initialize({
    app: app,
    swagger: '2.0',
    basePath: '/v1',
    info: {
        title: 'App',
        version: '1.0.0',
    },
    paths: {
        '/users': require('./routes/users'),
        '/messages': {
            'get': require('./routes/messages').get
        },
        '/books': createCrudEndpoints("Books"),
        ...require('./lotsOfEndpointsUsingSpread')
    }
});

The existing convention based system could be used to build this structure internally.

Use object destructuring for dependency injection

Introspecting function parameter names is nasty business. Relying on something like fn.toString() as a core technique is error prone and hacky. With native object destructuring there is no need.

Hacky parameter name introspection:

function route (fooService) {
  fooService.getFoo();
};

const deps = { fooService: {} };
route.apply(route, someInsaneToStringMagic(route, deps));

Clean object destructuring:

module.exports = function route ({ fooService }) {
  fooService.getFoo();
};

const deps = { fooService: {} };
route(deps);

Body validation does not work?

I'm trying to get validator to work on the body of this route:

  '/filtered':
    put:
      summary: blah
      parameters:
        - in: body
          name: body
          required: true
          schema:
            type: object
            required:
              - filtered
            properties:
              filtered:
                description: status of ssid
                type: boolean

here are my request parameters:
{ uri: 'http://127.0.0.1/apiv2/filtered', headers: { 'x-api-key': 'blah' }, json: { test: 'test' } }

I expect openapi-express to return 400, because body should be an object with filtered prop. Yet I get 200 response. Swaggerize express worked fine with this one. Am I doing something wrong here? I'll edit this to make it more reproducible after lunch....

Using "$ref: '#/definitions/...'" for responses has been deprecated.

All the examples in the test suite have API definitions similar to

responses: { default: { $ref: '#/definitions/Error' } }

These are flagged as errors in the Swagger Editor.

A valid alternative is to use

responses: { default: { description: "Unexpected error", schema: { $ref: '#/definitions/Error' } } }

Set apiDoc.host to running host

When the api docs json is requested the basePath is automatically updated to include the baseUrl of the request. It would make sense if the host is also updated to reflect the host in the request object.

This would allow the same code to run in different environments (dev, production, etc) without having to manually change the host.

Output [object Object] when trying to identify 'body' parameter in path's apiDoc

I was trying to do a PUT /inventories/{id} endpoint that will accept request body as:
{ "inventory": 100 }

I defined the apiDoc in each path js file, and this is the one for PUT.

// paths/inventories/{id}.js
const inventoryByIdPath = (inventoriesService) => {
  const PUT = (req, res) => {
    const id = _.get(req, 'params.id');
    const data = _.get(req, 'params.data');
    ...
  };
  PUT.apiDoc = {
   ...
    parameters: [
      {
        in: 'path',
        name: 'id',
        description: 'productId',
        required: true,
        type: 'string'
      },
      {
        in: 'body',
        name: 'data',
        description: 'Inventory Data',
        required: true,
        schema: {
          $ref: '../../configs/schemas.json#/Inventory'
        }
      }
  ]
  ...
}

// schemas.json:

{
  "Inventory": {
    "properties": {
      "inventory": {
        "type": "number"
      }
    }
  }
}

However, when I call this endpoint, it will always return html error response instead of json:

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="utf-8">
        <title>Error</title>
    </head>
    <body>
        <pre>[object Object]</pre>
    </body>
</html>

and console would have logged: [object Object] after I send the request, which I didn't log it anywhere in code.
After setting the break point, I found out it didn't even make it to the line: const PUT = (req, res) => {...}

Though after removing:

{
  in: 'body',
  name: 'data',
  description: 'Inventory Data',
  required: true,
  schema: {
    $ref: '../../configs/schemas.json#/Inventory'
  }
}

It would work normal, but it won't have 'body' in req.

I tried to find more similar examples online, but only found those provided in express-openapi docs.
Having no clue where would it go wrong. Any ideas? And is there anyway I could know what's inside that mystery [object, Object]?

Using these packages:

{
    "express": "^4.16.2",
    "express-openapi": "^1.2.0"
}

Option to validate all responses

I can't find an option to validate all responses, it gets repetitive to keep doing.

const validationError = res.validateResponse(200, json);
if (validationError) {
    return next(validationError);
}

res.json(json);

(feature): ES7/TypeScript Decorators

Add Support for ES7/TypeScript Decorators

Per my convo with @jsdevel on Gitter, I'd like to propose adding some implementation for decorators.

Example

ZooController.ts

@controller({
   // default route
   route: '/zoo'

   // add additional middlewares for express
   middlewares: [ ... ],

   // custom override for global spec
   spec: './zoo-spec.yml'
})
export class ZooController {
    @api(/get’, [ ...middlewares ])
    getAnimals(req, res, next) { 
          // doo stuff
    }
}

App.ts

import { ZooController } from './ZooController';
import { register } from 'express-openapi';

let app = express();
register(app, {
    spec: './spec.yml',
    route: '/api',
    paths: [ '**/*.ts' ]
});

This is kinda angular2-esque with the loaded decorator design pattern which works nicely IMO, define the config at top and the real work happens in body.

If it were me, I'd consider making this project more generic like node-openapi and then writing this proposal seperate like node-openapi-router and then add adapters for connect/koa/etc like node-openapi-connect-middleware.

Resources

What about refactoring? ^_^

To be honest I don't like the way which you choose for routing.
What about to make your router optional?
How can it be? For example:

openapi.initialize({
  apiDoc: require('./api-doc.js'),
  app: app,
  router: myRouter // if not set, by default it can be 'fs-routes'
});

If you don't mind, I can try to make PR

modular approach

Hello, thank you for the excellent framework. I have a question about using it to construct modular express applications, where multiple routes are defined in individual npm modules, and the final product is composed from these. Can I call openapi.initialize() multiple times in a single app, once for each module? This implies that instead of a single routes folder, I may have several...

File upload not working

Hello,

I have an endpoint documented like this:

post.apiDoc = {
    description: 'Upload an image for the category',
    operationId: 'uploadCategoryImage',
    tags: ['categories'],
    consumes: ['multipart/form-data'],
    parameters: [
        {
            name: 'image',
            in: 'formData',
            type: 'file',
            description: 'An image for this category',
            required: true
        }
    ],
    responses: {
        201: {
            description: 'Image successfully uploaded'
        },
        default: {
            description: 'Unexpected error',
            schema: {
                $ref: '#/definitions/Error'
            }
        }
    }
};

In the Swagger UI, a file upload thing is visible:

swagger

However, I keep getting this error when I send a file:

{
    path: 'image',
    errorCode: 'required.openapi.validation',
    message: 'instance requires property "image"',
    location: 'body'
}

I do have a Content-Type: multipart/form-data header in the HTTP request.
Am I doing something wrong or is it a bug?

Console.log ??

I notice that all logging is hard-coded to use Console. Is there some way to redirect this modules console output to a application specific logger so it can be routed to eg, a file then ELK, like all the other logs in our api?

Option to strip out unused parameters

This may already be included somewhere, but it would be awesome if there was an option to strip out parameters that aren't in the docs. For example:

If a query parameter age is defined, but ?age=30&foo=bar is passed, I would like req.query to only contain age.

I'm not sure which underlying express-openapi-* module would contain this, or perhaps it would be a new one.

Thanks for creating this package :)

Just want to say thank you so much for investing time and sharing this package with the community.

It's extremely useful, especially for API first design & development.

Cheers!

Allow del alias for delete

delete is a javascript keyword / unary operator. It is invalid for functions to be named delete in javascript, so it would be good to support a del alias to allow for this:

module.exports = {
  del
};

function del(req, res, next) {
  // ...
}

Add vendor extension for scoped middleware

'x-express-openapi-additional-middleware': [myMiddleware].

The middleware should be appended after coercion, defaults, and validation middleware, but not after operation middleware.

Directory structure for a nested paths

Hi I'm noob,

The paths I want look something like this:

/v1/resource/{type}/
/v1/resource/{type}/something

I assume I'll need this directory structure :

|-<package>
    |-v1
        |-resource
            |-{type}
                |-index.js
                |-something.js

however it doesn't seem to be working. It is returning 404 for either endpoint.
The documentation only helps with a specific type of nested pattern and doesn't have any further examples for this particular pattern I'm having trouble with.

I have tried various other directory structures including...

|-resource
    |-{type}.js
    |-{type}
        |-something

but that didn't help either

Account for deeply nested apps in basePath.

When express-openapi is mounted on a sub app, the basePath ignores the mount path of the parent app.

var app = express(),
    sub = express(),
    sub2 = express();

openapi.initialize({
  apiDoc: require('./api-doc.js'),
  app: sub2,
  routes: './api-routes'
});

sub.use('/subapp2', sub2);
app.use('/subapp', sub);

If ./api-doc.js has a basePath of /v1, I would expect the basePath in the generated api doc in this case to be /subapp/subapp2/v1. Instead, the basePath of the api doc is /subapp2/v1, ignoring the highest mount path.

Filename with ":" is not supported in Windows

npm install express-openapi fails because it cannot create the file name ":id.js" from the sample-projects.

npm install express-openapi --save
npm ERR! tar.unpack untar error C:\Users\fries\AppData\Roaming\npm-cache\express-openapi\0.4.2\package.tgz
npm WARN EPACKAGEJSON [email protected] No repository field.
npm ERR! Windows_NT 10.0.10586
npm ERR! argv "C:\Program Files\nodejs\node.exe" "C:\Program Files\nodejs\node_modules\npm\bin\npm-cli.js" "install" "express-openapi" "--save"
npm ERR! node v5.4.1
npm ERR! npm v3.3.12
npm ERR! path C:\projects\misc-swagger-howto\nodejs\node_modules.staging\express-openapi-2cbd6e854429c6f69613c40e36d233e3\test\sample-projects\basic-usage\api-routes\users:id.js
npm ERR! code ENOENT
npm ERR! errno -4058
npm ERR! syscall open

npm ERR! enoent ENOENT: no such file or directory, open 'C:\projects\misc-swagger-howto\nodejs\node_modules.staging\express-openapi-2cbd6e854429c6f69613c40e36d233e3\test\sample-projects\basic-usage\api-routes\users:id.js'
npm ERR! enoent This is most likely not a problem with npm itself
npm ERR! enoent and is related to npm not being able to find a file.
npm ERR! enoent

npm ERR! Please include the following file with any support request:
npm ERR! C:\projects\misc-swagger-howto\nodejs\npm-debug.log

Validation messaging

Liking this more and more so thanks for making such a stellar implementation. Question:

I'm not getting req validation messaging back - ( just 400s ) - can I enable that somehow?

API - How to have valid nullable fields in swagger ?

Hi,

Thanks for express-openapi. I really appreciate to use it :)
But I have a problem, I need to expose fields which the type strings that could be nullable.
This following code works when i run the server based on express-api :

responses: { 200: { schema: { title: 'MyObject', properties: { myfield: { type: ['string', 'null'],

But it's not valid against Swagger (editor.swagger.io) :(

Semantic error at definitions.MyObject.myfield "type" should be a string

Do you have a valid way to use nullable fields with express-openapi ?

Thanks by advance !

And Thanks for this top library.

Regards,

F.

BasePath problems with empty string vs '/'

My application doesn't have anything like '/v1', for a basePath. I need either '' or '/'.
Unfortunately neither option is completely problem free while using express-openapi:

If I set it to '/', I get routing problems, my routes are defined like:

openapi.initialize({
  app,
  ...
  paths: [
    {
      path: '/auth/token',
      module: require('./auth_token')
    },
    ...
  ]
});

If I have a leading '/' in the path for my module, then the route ends up being set up as '//auth/token', which obviously breaks things. If I don't have the leading '/' in the path, I get this error: Error: express-openapi: args.apiDoc was invalid after populating paths.

Alternatively, if I set basePath to '' (or don't set it, as express-openapi defaults it to '') then I can get routing to work, however SwaggerUI will report a problem with the basePath being invalid (supposed to match '^/'),

I've resolved the problem as far as running my application by setting basePath to '' while letting express-openapi set up, and then intercepting the api docs for SwaggerUI with the following hack:

app.use('/api-doc.json', (req, res, next) => {
  const json = res.json;
  res.json = function(obj) {
    obj.basePath = '/';
    json.apply(res, arguments);
  };
  next();
});

Lerna Rewrite

I'm thinking the project could benefit from using lerna. That way the middleware etc. could be brought into the same repo. Doing so could make maintenance easier as PRs, issues and so forth wouldn't be spread across multiple repositories. Looking for thoughts from the community.

  • Move project root files to packages/express-openapi with the exception of files that belong in the project root i.e. .travis.yml etc.
  • Move dependency packages under packages/
  • Add lerna
  • Ensure that travis builds are running.
  • Create a README.md file at the project root
  • Rename repository (decide on name later)
  • Combine coverage reports for coveralls

router-level middleware

I tried to add an router-level middleware to expose some routes depending on NODE_ENV. But I could not figure out how to do it.
I used x-express-openapi-additional-middleware to include my middleware, but express-openapi does not execute it. There is an elegant way to expose/hide routes depending on NODE_ENV?
And there is a way to add middleware using api-doc as json file?

Middleware should be opt-in like express

This project has been really nicely designed to be modular with separated middleware, but all of the middleware seems to be included by default. In express, koa and other frameworks all middleware is optional so you are free to add what you wish and use alternatives which allows for a rich ecosystem.

I suggest we define a middleware spec for express-openapi.

function myCoolMiddleware(apiDoc) {
    return function (req, res, next) {
        // Do stuff
        next();
    }
}

// or

function myCoolMiddleware(req, res, next) {
   const apiDoc = req.apiDoc;   
   // Do stuff
   next();
}

const openapiInstance = openapi.initialize({
});

openapiInstance.use(myCoolMiddleware);

// or

openapi.initialize({
    middleware: [myCoolMiddleware, express-openapi-defaults]
});

Parameters question

First off thanks for the framework. It's been very useful for growing my knowledge of OpenAPI and the ecosystem while getting prototypes up fast!

I was wondering if there was a best practice for utilizing and working off of route parameters. All examples end in a {id}.js file, but what if I want to have a nested structure against {id}?

For example, two routes such as:
/items/{id}/this
/items/{id}/that

There are two primary issues I'm running into and wondering what you think best practice would be:

  • I have to declare parameters in both this and that. Is there any way to define parameters for a whole sub-tree?
  • Where would I put a loadItem helper that runs before either route? As far as I can tell, any utility functions can't go under the routes directory, as it would be processed as a route.

Both of these may also be alleviated by the routing refactor in #12 , but not sure the timeline on that.

Looking for feedback

This issue is to request feedback from the community so express-openapi may be improved. For any who wish not to be apart of this, please comment herein with please remove me and I'll delete any comment herein containing your @ mention.

Security Filtering

I'm eager to switch over to express-openapi but we're missing one feature which we require: security filtering of the documentation itself. Essentially we only want to show scopes, paths and operations that the user has access to in the documentation. It is described in the spec: https://github.com/OAI/OpenAPI-Specification/blob/master/versions/2.0.md#security-filtering

Any plans to implement this? It should reuse the security handlers. With swaggerize-express we handle it by adding an explicit route for the documentation which calls a middleware that does the filtering.
app.get('/v1/api-docs', filter_openapi); Works great!

We've done a similar POC middleware for express-openapi, but the route is overriden, so the filtered api-docs isn't returned. Code for reference below. It would be great if an option to turn on security filtering could be added.

function filter_openapi(req, res, next) {
  // remove scopes the user does not have access to
  Object.values(api_docs.securityDefinitions).forEach(function (securityDefinition) {
    Object.keys(securityDefinition.scopes).forEach(function (scope) {
      if (req.user.scope.indexOf(scope) == -1) {
        delete securityDefinition.scopes[scope]
      }
    })

  })

  // remove paths the user does not have access to
  Object.keys(api_docs.paths).forEach(function (path) {
    var def = api_docs.paths[path]
    verbs.forEach(function (verb) {
      var operation = def[verb]
      if (!operation) {
        return;
      }
      if (operation.security || api_docs.security) {
        var securityDeclarations
        if (!operation.security) {
          securityDeclarations = api_docs.security
        }
        else {
          securityDeclarations = operation.security
        }
        securityDeclarations.forEach(function (security) {
          const authorizer = require('./authorizers')[Object.keys(security)[0]]  // TODO: Fix this fuglymess
          authorizer(req, Object.values(security)[0] ,security, function (error, authorized) {
            console.log(authorized)
            if (!authorized) {
              delete def[verb]
            }
          })

        })
      }
    })

    //Check if any operations remain, if not we should remove the paths object also
    var operationExists = false
    verbs.forEach(function (verb) {
      var operation = def[verb]
      if (operation) {
        operationExists = true
      }
    })
    if (!operationExists) {
      delete api_docs.paths[path]
    }
  })

  //Check if definitions are still referenced
  if (api_docs.definitions) {
    Object.keys(api_docs.definitions).forEach(function (definition) {
      var def = '#/definitions/' + definition
      if (!_isContains(api_docs, def)) {
        delete api_docs.definitions[definition]
      }
    })
  }

  //Check if parameters are still referenced
  if (api_docs.parameters) {
    Object.keys(api_docs.parameters).forEach(function (parameter) {
      var def = '#/parameters/' + parameter
      if (!_isContains(api_docs, def)) {
        delete api_docs.parameters[parameter]
      }
    })
  }
  //Check if responses are still referenced
  if (api_docs.responses) {
    Object.keys(api_docs.responses).forEach(function (response) {
      var def = '#/responses/' + response
      if (!_isContains(api_docs, def)) {
        delete api_docs.responses[response]
      }
    })
  }

  // remove empty objects
  api_docs = removeEmptyObject(api_docs);

  // add back the paths object if it was removed, must be there per the spec
  if (!api_docs.paths) {
    api_docs.paths = {}
  }

  next();
}

external schemas appear to not render in swagger-ui

running the test/sample-projects/with-external-schema-references app and viewing the generated api doc in swagger UI results in html markup displayed as well as errors implying that the external schemas could not be referenced.

Does express-openapi actually attempt to pull the schemas from the uris specified as the keys to the externalSchemas option object? Seems like the with-external-schema-references project inlines the definitions of the schema, and the uri is really just a key.

screen shot 2016-09-02 at 11 54 43 pm

$ref external yaml file does not work

I use the dist folder files in master, and use $ref to reference external yaml file, but it can't resolved.
my yaml format is :

  parameters:
    -
      name: request
      in: body
      required: true
      schema:
        $ref: './deviceManageDF.yaml#/definitions/AddDeviceDTONA2Cloud'

even modified with full acess path as:

  parameters:
    -
      name: request
      in: body
      required: true
      schema:
        $ref: 'http://localhost:8080/swagger-ui/deviceManageDF.yaml#/definitions/AddDeviceDTONA2Cloud'

It displayed:
http://localhost:8080/swagger-ui/deviceManageDF.yaml#/definitions/AddDeviceDTOCloud2NA is not defined!

200 is invalid

Getting:

September 16 22:59:13: express-openapi:  validation errors [
  {
    "property": "instance.paths./provider.post.parameters[2]",
    "message": "is not exactly one from <#/definitions/parameter>,<#/definitions/jsonReference>",
    "schema": {
      "oneOf": [
        {
          "$ref": "#/definitions/parameter"
        },
        {
          "$ref": "#/definitions/jsonReference"
        }
      ]
    },
    "instance": {
      "name": "columns",
      "in": "body",
      "description": "Columns to include in response",
      "type": "array",
      "schema": {
        "$ref": "#/definitions/columnList"
      }
    },
    "name": "oneOf",
    "argument": [
      "<#/definitions/parameter>",
      "<#/definitions/jsonReference>"
    ],
    "stack": "instance.paths./provider.post.parameters[2] is not exactly one from <#/definitions/parameter>,<#/definitions/jsonReference>"
  },
  {
    "property": "instance.paths./provider.post.responses[200]",
    "message": "is not exactly one from <#/definitions/response>,<#/definitions/jsonReference>",
    "schema": {
      "oneOf": [
        {
          "$ref": "#/definitions/response"
        },
        {
          "$ref": "#/definitions/jsonReference"
        }
      ]
    },
    "instance": {},
    "name": "oneOf",
    "argument": [
      "<#/definitions/response>",
      "<#/definitions/jsonReference>"
    ],
    "stack": "instance.paths./provider.post.responses[200] is not exactly one from <#/definitions/response>,<#/definitions/jsonReference>"
  }
]

when I try to do the example in the readme

I'm a bit new to openapi but it seems like it's not recognizing 200 as a valid responses key, which I believe it should be

... michael

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.