Code Monkey home page Code Monkey logo

openapi-cop's Introduction

openapi-cop

OpenAPI Compliance Proxy that validates requests and responses against an OpenAPI document

License CI status NPM version Docker Image Version (latest semver)

The idea is to place the proxy between a client (e.g. a frontend app) and a web server to catch invalid requests or responses during development. Use this proxy locally or set it up in your development server. In production environments, set the _silent_ flag to forward unmodified response bodies. In any case, validation headers are set that allow to trace down violations to your OpenAPI definition.

Proxy Diagram

Requirements

We run all tests with Node.js versions 10 and 12. Higher versions could possibly work but are not currently supported.

Installation

To install the CLI globally:

npm install -g openapi-cop

To install the package locally (inside an existing NPM package) and run the proxy programatically:

npm install openapi-cop

Usage

There are three ways to run openapi-cop:

  1. Start it with the CLI (1).
  2. Run it programatically inside Node.js (2).
  3. Start a container based on the Docker image (3).

CLI Usage

The openapi-cop node package installs itself as an executable linked as openapi-cop. Run the command with the --help flag to get information about the CLI:

Usage: openapi-cop [options]

Options:
  -s, --file <file>                       path to the OpenAPI definition file
  -h, --host <host>                       the host of the proxy server (default: "localhost")
  -p, --port <port>                       port number on which to run the proxy (default: 8888)
  -t, --target <target>                   full base path of the target API (format: http(s)://host:port/basePath)
  --default-forbid-additional-properties  disallow additional properties when not explicitly specified
  --silent                                do not send responses with validation errors, just set validation headers
  -w, --watch [watchLocation]             watch for changes in a file or directory (falls back to the OpenAPI file)
                                             and restart server accordingly
  -v, --verbose                           show verbose output
  -V, --version                           output the version number
  -h, --help                              output usage information

The proxy validates the requests and responses in the communication with a target server. By default, the proxy will respond with a 500 status code when the validation fails.

Sample validation failure response
{
  "error": {
    "message": "openapi-cop Proxy validation failed",
    "request": {
      "method": "POST",
      "path": "/pets",
      "headers": {
        "host": "localhost:8888",
        "user-agent": "curl/7.59.0",
        "accept": "*/*",
        "content-type": "application/json",
        "content-length": "16"
      },
      "query": {},
      "body": {
        "data": "sent"
      }
    },
    "response": {
      "statusCode": 201,
      "body": "{}",
      "headers": {
        "x-powered-by": "Express",
        "openapi-cop-openapi-file": "7-petstore.yaml",
        "content-type": "application/json; charset=utf-8",
        "content-length": "2",
        "etag": "W/\"2-vyGp6PvFo4RvsFtPoIWeCReyIC8\"",
        "date": "Thu, 25 Jul 2019 13:39:58 GMT",
        "connection": "close"
      },
      "request": {
        "uri": {
          "protocol": "http:",
          "slashes": true,
          "auth": null,
          "host": "localhost:8889",
          "port": "8889",
          "hostname": "localhost",
          "hash": null,
          "search": null,
          "query": null,
          "pathname": "/pets",
          "path": "/pets",
          "href": "http://localhost:8889/pets"
        },
        "method": "POST",
        "headers": {
          "host": "localhost:8888",
          "user-agent": "curl/7.59.0",
          "accept": "*/*",
          "content-type": "application/json",
          "content-length": "16",
          "accept-encoding": "gzip, deflate"
        }
      }
    },
    "validationResults": {
      "request": {
        "valid": true,
        "errors": null
      },
      "response": {
        "valid": false,
        "errors": [
          {
            "keyword": "required",
            "dataPath": "",
            "schemaPath": "#/required",
            "params": {
              "missingProperty": "code"
            },
            "message": "should have required property 'code'"
          }
        ]
      },
      "responseHeaders": {
        "valid": true,
        "errors": null
      }
    }
  }
}

Two headers are added to the response:

  • openapi-cop-validation-result: contains the validation results as JSON.

    Interface
    {
        request: {
          valid: boolean;
          errors?: Ajv.ErrorObject[] | null;
        },
        response: {
          valid: boolean;
          errors?: Ajv.ErrorObject[] | null;
        },
        responseHeaders: {
          valid: boolean;
          errors?: Ajv.ErrorObject[] | null;
        }
    }
  • openapi-cop-source-request: contains a simplified version of the original request sent by the client as JSON.

    Interface
    {
      method: string;
      path: string;
      headers: {
        [key: string]: string | string[];
      };
      query?: {
        [key: string]: string | string[];
      } | string;
      body?: any;
    }

See the references of OpenAPI Backend and Ajv for more information.

When the --silent is provided, the proxy will forward the server's response body without modification. In this case, the validation headers are still added.

Module Usage

To run the proxy programatically use runProxy, which returns a Promise<http.Server>:

import {runProxy} from 'openapi-cop';

const server = await runProxy({
  port: 8888,
  host: 'proxyhost',
  targetUrl: 'http://targethost:8989',
  apiDocPath: '/path/to/openapi-file.yaml',
  defaultForbidAdditionalProperties: false,
  silent: false
});

Docker Image Usage

We publish a Docker image lxlu/openapi-cop that you can use for your convenience. This means you can also run openapi-cop with something like

docker run --rm -p 8888:8888 --env TARGET=https://some-host-name:1234 --env FILE=some-openapi-document.json lxlu/openapi-cop

Read more information about the usage here.

FAQ

Can I use this in production? This tool was originally meant for development scenarios. You can use this in production but we cannot give you any security guarantees. Also running the JSON schema validation is quite CPU-expensive and you likely do not want to validate in both directions in production because of that overhead.
Do I need this if I already generate my client from the OpenAPI? In case your client and server code is generated from the OpenAPI spec, you might still want to use this proxy. Generated code does usually only provide typing information, but JSON Schema defines much more than that. For example you might define a string property to match a given RegEx and start with the letter "C". This will not be ensured by your generated code at compile time, but will be caught by openapi-cop.
Can I use this with other programming languages? Yes. This is a proxy and not a middleware. You can use it between whatever HTTP-endpoints you have in your architecture.

Contributing

If you want to contribute to openapi-cop, be sure to check the Contributing guidelines and the Contributing wiki page.



Made By
Alexis and Daniel

at

Exxeta

Join us now!



openapi-cop's People

Contributors

lexluengas avatar morawskim avatar pubkey avatar renovate-bot avatar renovate[bot] 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

openapi-cop's Issues

test fails

After

npm i [email protected]
cd mock
npm i
cd ..
npm i
npm run test

i get

...
Validating against 7-petstore.yaml ("Test API 7 - Petstore", version: 1.0.0)
Running test...
Sending request GET /pets
Sending request GET /pets/1
Shutting down servers...
      โœ” should respond with validation headers that are ValidationResult: 7-petstore.yaml
Starting proxy server...
Reading output

...
d_for,"___cxa_allocate_exception":___cxa_allocate_exception,"_emscripten_memcpy_big":_emscripten_memcpy_big,"___cxa_end_catch":___cxa_end_catch,"___resumeException":___resumeException,"__ZSt18uncaught_exceptionv":__ZSt18uncaught_exceptionv,"___cxa_begin_catch":___cxa_begin_catch,"_pthread_getspecific":_pthread_getspecific,"__arraySum":__arraySum,"_pthread_once":_pthread_once,"___syscall54":___syscall54,"___unlock":___unlock,"__isLeapYear":__isLeapYear,"_pthread_setspecific":_pthread_setspecific,"___cxa_throw":___cxa_throw,"___cxa_rethrow":___cxa_rethrow,"___syscall6":___syscall6,"_pthread_cleanup_push":_pthread_cleanup_push,"___cxa_pure_virtual":___cxa_pure_virtual,"___syscall140":___syscall140,"___cxa_find_matching_catch":___cxa_find_matching_catch,"___syscall145":___syscall145,"___syscall146":___syscall146,"STACKTOP":STACKTOP,"STACK_MAX":STACK_MAX,"DYNAMICTOP_PTR":DYNAMICTOP_PTR,"tempDoublePtr":tempDoublePtr,"ABORT":ABORT,"cttz_i8":cttz_i8};// EMSCRIPTEN_START_ASM



AssertionError: should show failure to communicate with the target server: expected false to be true
    at ChildProcess.<anonymous> (***/openapi-cop/test/02.integration.test.ts:239:18)
    at ChildProcess.emit (events.js:400:28)
    at Process.ChildProcess._handle.onexit (internal/child_process.js:282:12) {
  showDiff: true,
  actual: false,
  expected: true,
  operator: 'strictEqual'
}
npm ERR! code ELIFECYCLE
npm ERR! errno 7
npm ERR! [email protected] test: `mocha --bail --timeout 60000 --exit build/test/*.test.js`
npm ERR! Exit status 7

please describe in the readme how to set up the dev environment and run the tests.

Support target URIs with https protocol

We are currently rejecting target URI's with protocol https with error message:
HTTPS is not supported. Not possible to modify requests/responses when the channel is encrypted. Consider to use openapi-cop behind a SSL proxy.

However it would be useful to support the following scenario:
client --http--> proxy --https--> target server

GitHub package publishing fails

The publish-npm-package.yml workflow fails during npm publish. The package name in package.json must have the same scope as the repository, i.e. "@exxeta/openapi-cop". For this to work also for npmjs.com, we would need to publish under the "exxeta" scope there as well.

Reference Resolution error

Hi there!

I love the idea of a validation proxy and tried it with an OpenAPI 3 spec used by our team.

I am getting the following error and hope you have an idea how to tackle this.

$ npx openapi-cop -s path-to-openapi.yaml -h 8888 -t https://localhost:8083
Validating against openapi.yaml ("API Specification", version: 0.1.0)
RangeError: Maximum call stack size exceeded
    at /Volumes/some/repo/node_modules/swagger-client/dist/index.js:1:21167
    at tryCatch (/Volumes/some/repo/node_modules/babel-runtime/node_modules/regenerator-runtime/runtime.js:62:40)

And then further down..

Failed to run openapi-cop Reference resolution error: Error: Could not resolve references in OpenAPI document due to the following errors:
    [
  {},
  {}
]
โœจ  Done in 5.05s.

Also run tests against docker container

Currently

Almost all integration tests run against local server instances (server.listen() on the main process) of the proxy and the mock.

This means that problems specific to the Docker image build are not caught by the tests. Issues like #401 will go unnoticed.

This change will...

  • Build the Docker container before the tests are run.
  • Re-run integration tests also against the Docker container of openapi-cop.

mock-server fails docker build

Problem

Latest docker image build failed (https://github.com/EXXETA/openapi-cop/actions/runs/3337710608) due to package.json in mock-server not being found.

#10 17.04 npm WARN old lockfile Error: ENOENT: no such file or directory, open '/openapi-cop-docker/mock-server/package.json'
#10 17.04 npm WARN old lockfile  Could not fetch metadata for openapi-cop-mock-server@file:../mock-server [Error: ENOENT: no such file or directory, open '/openapi-cop-docker/mock-server/package.json'] {
#10 17.04 npm WARN old lockfile   errno: -2,
#10 17.04 npm WARN old lockfile   code: 'ENOENT',
#10 17.04 npm WARN old lockfile   syscall: 'open',
#10 17.04 npm WARN old lockfile   path: '/openapi-cop-docker/mock-server/package.json'
#10 17.04 npm WARN old lockfile }

There is also a warning pointing to a wrong runtime node version:

#10 17.10 npm WARN EBADENGINE Unsupported engine {
#10 17.10 npm WARN EBADENGINE   package: '@exxeta/[email protected]',
#10 17.10 npm WARN EBADENGINE   required: { node: '^10 || ^12' },
#10 17.10 npm WARN EBADENGINE   current: { node: 'v18.12.0', npm: '8.19.2' }
#10 17.10 npm WARN EBADENGINE }

Finally, there is also a minor warning about deprecated usage: #10 0.638 npm WARN config only Use --omit=dev to omit dev dependencies from the install..

mock-server fails global installation

Problem

Preinstall script fails installation. npm install -g @exxeta/openapi-cop results in:

> @exxeta/[email protected] preinstall:development /home/allu/.nvm/versions/node/v10.24.1/lib/node_modules/@exxeta/openapi-cop
> cd mock-server && npm install

sh: line 1: cd: mock-server: No such file or directory
npm ERR! code ELIFECYCLE
npm ERR! errno 1
npm ERR! @exxeta/[email protected] preinstall:development: `cd mock-server && npm install`
npm ERR! Exit status 1
npm ERR! 
npm ERR! Failed at the @exxeta/[email protected] preinstall:development script.

Reason

Since per-env defaults NODE_ENV to "development", the "preinstall:development" script is executed, which tries to install the mock server.

Workaround solution

  • Set preinstall script to (test -d mock-server && cd mock-server && npm install) || true to be more forgiving.

Proposed solution

  • Publish mock-server separately.
  • Move mock-server to its own repository.
    This would remove the necessity to install the dependencies of mock-server altogether.

Cannot cURL requests into the containerized application

Description

I am trying to use the docker image provided but I am not able to pass in requests to the containerized application. I think this is because the application is listening on localhost or 127.0.0.1. I am exposing the default port 8888 using docker run -p 8888:8888 and the response is curl: (52) Empty reply from server

To Reproduce

Run the docker image using docker run -p 8888:8888 lxlu/openapi-cop. Try any cURL request to http://127.0.0.1:8888

Tasks

Change default host address to 0.0.0.0 or add the ability to modify application host name using the environment variables

operationId is not being treated as optional

given:

openapi: 3.0.0
info:
  title: MediaIndex
  description: Enforcement proxy example
  version: 1.0.0
servers:
  - url: 'http://localhost'
paths:
  /list:
    get:
      description: A list of important stuff
      parameters:
        - $ref: '#/components/parameters/PageLimit'
      responses:
        '200':
          description: Successful response
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/media_info'

components:
  schemas:
    media_info:
      type: object
      required:
        - id_media
        - name_media
      properties:
        id_media:
          type: string
          format: uuid
        name_media:
          type: string
        extra_info:
          type: string
  parameters:
    PageLimit:
      name: limit
      in: query
      description: Limits the number of items on a page
      schema:
        type: integer

when:

openapi-cop -s MediaHost.yml -t http://localhost:8080 -v
curl --request GET 'http://localhost:8888/list' --header 'Content-Type: application/json'

then:

Validating against MediaHost.yml ("MediaIndex", version: 1.0.0)
Proxy at   http://localhost:8888 (development mode)
Target at  http://localhost:8080
  openapi-cop:proxy Proxying client request [GET /list] +0ms
  openapi-cop:proxy Received server response with status code 200 +14ms
  openapi-cop:proxy Validation results [GET /list] {
  openapi-cop:proxy   "request": {
  openapi-cop:proxy     "valid": false,
  openapi-cop:proxy     "errors": [
  openapi-cop:proxy       {
  openapi-cop:proxy         "keyword": "operation",
  openapi-cop:proxy         "dataPath": "",
  openapi-cop:proxy         "schemaPath": "",
  openapi-cop:proxy         "params": [],
  openapi-cop:proxy         "message": "Unknown operation '/list'"
  openapi-cop:proxy       }
  openapi-cop:proxy     ]
  openapi-cop:proxy   }
  openapi-cop:proxy } +1ms

by adding operationId: "/list" under get: it will validate and approve the request through as expected.

BUT based on https://github.com/OAI/OpenAPI-Specification/blob/master/schemas/v3.0/schema.json#L845 only responses should be required.

Make improvements to README

  • Link to Docker Hub.
  • Add status badges (npm, docker, license, etc.).
  • Mention required Node.js version.
  • Explain how use cases of npm install and npm install -g differ.
  • Fix "Join us now" link to Exxeta company page.
  • Try to make the Exxeta logo visible in dark mode as well.

Docker image: "Error: Cannot find module '../../package.json'"

Hello!

I can't get the Docker image to work.

Am I doing something wrong here, or is the Docker image broken?

~ $ docker run -it 'lxlu/openapi-cop:v1.3.2'
internal/modules/cjs/loader.js:638
    throw err;
    ^

Error: Cannot find module '../../package.json'
    at Function.Module._resolveFilename (internal/modules/cjs/loader.js:636:15)
    at Function.Module._load (internal/modules/cjs/loader.js:562:25)
    at Module.require (internal/modules/cjs/loader.js:692:17)
    at require (internal/modules/cjs/helpers.js:25:18)
    at Object.<anonymous> (/openapi-cop-docker/src/cli.js:13:20)
    at Module._compile (internal/modules/cjs/loader.js:778:30)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:789:10)
    at Module.load (internal/modules/cjs/loader.js:653:32)
    at tryModuleLoad (internal/modules/cjs/loader.js:593:12)
    at Function.Module._load (internal/modules/cjs/loader.js:585:3)
~ [1]$

Upgrade to Node.js 16

Migration to Node.js v16

Context

Version 16 is the current LTS version as of now (https://nodejs.org/en/about/releases/).

Currently

  • CI tests run on Node.js v10 and v12.
  • Dockerfile uses "node:17" image ๐Ÿ˜ข.
  • The test/docker/run-docker-test.bash script runs using the "node:10.15.3" Docker image.
  • package.json file does not declare any node versions in "engines" section.
  • The .nvmrc file has v10.24.1.
  • GitHub action "npm-publish" uses v10 during step "actions/setup-node" but the step is probably unnecessary since it does not run anything.

Tasks

  • Consolidate node versions used across code base. Consider to have a single source for the version. A dev setup script might be needed.
  • Update local configuration.
  • Update build environment of GitHub actions.
  • Upgrade dependencies one-by-one.
  • Consider to remove dependencies that can be replaced by a Node.js API.\
  • Remove "actions/setup-node" step from "npm-publish" action. Consider to upgrade to the latest "pascalgn/npm-publish-action" for the publish step.

Out of scope

Linked issues

Failed to run openapi-cop TypeError: Cannot read property 'constructor' of null

Starting revision 5cb4e9f (from PR #404) in Docker (compose) I get the below output.

Note also that it exited with code 0 which is weird considering it didn't work.

Environment

DEFAULT_FORBID_ADDITIONAL_PROPERTIES=true
VERBOSE=true
TARGET=http://xxxxxx:5058
FILE=/api.yaml

api.yaml

Proprietary, sorry, can't post it.

Output

Note how everything here is .js and the line numbers not matching the .ts source code.

pfcapi-openapi-cop-1            | Validating against api.yaml ("PFC API", version: 1.0.0)
pfcapi-openapi-cop-1            | Additional properties will be forbidden by default. Existing `additionalProperties` settings in the OpenAPI document will NOT be overwritten.
pfcapi-openapi-cop-1            | Failed to run openapi-cop TypeError: Cannot read property 'constructor' of null
pfcapi-openapi-cop-1            |     at mapWalkObject (/openapi-cop-docker/src/util.js:209:19)
pfcapi-openapi-cop-1            |     at mapWalkObject (/openapi-cop-docker/src/util.js:210:28)
pfcapi-openapi-cop-1            |     at mapWalkObject (/openapi-cop-docker/src/util.js:210:28)
pfcapi-openapi-cop-1            |     at mapWalkObject (/openapi-cop-docker/src/util.js:210:28)
pfcapi-openapi-cop-1            |     at mapWalkObject (/openapi-cop-docker/src/util.js:210:28)
pfcapi-openapi-cop-1            |     at Object.mapWalkObject (/openapi-cop-docker/src/util.js:210:28)
pfcapi-openapi-cop-1            |     at prepareApiDocument (/openapi-cop-docker/src/app.js:184:21)
pfcapi-openapi-cop-1            |     at process._tickCallback (internal/process/next_tick.js:68:7)
pfcapi-openapi-cop-1            |     at Function.Module.runMain (internal/modules/cjs/loader.js:834:11)
pfcapi-openapi-cop-1            |     at startup (internal/bootstrap/node.js:283:19)
pfcapi-openapi-cop-1            |     at bootstrapNodeJSCore (internal/bootstrap/node.js:623:3)
pfcapi-openapi-cop-1 exited with code 0

Support openapi 3.1

Context

Since February 2021, the openapi schema version 3.1.0 exists and, for the first time, is a true superset of JSON Schema. This opens the door for simpler tooling that already exists in the context of JSON Schema.

Currently

  • We run our tests against openapi documents with versions 3.0.x and 2.0.x.
  • We don't know if our current dependencies (mainly openapi-backend) support 3.1.0 out of the box.

This change will...

  • Create tests and test data targeting openapi 3.1.0.
  • Evaluate compatibility of dependencies with openapi 3.1.0.
  • Propose a minimal change that grants openapi-cop support for openapi 3.1.0.

Valid call returns 500 without neither logging nor validation error

With openapi-cop 5cb4e9f running in Docker, I get a 500 back from the proxy but no indication of any errors.

I would expect one of:

  1. The original (valid) 404 response
  2. An explanation of what's wrong, both on the openapi-cop console and in the Openapi-Cop-Validation-Result header I got back

Sequence Diagram

sequenceDiagram
    Test Driver->>openapi-cop: DELETE /internal/test/plans
    openapi-cop->>App Under Test: DELETE /internal/test/plans
    App Under Test->>openapi-cop: 404 (documented response)
    openapi-cop->>Test Driver: 500

Log Output

Console output, note the "valid": true line.

pfcapi-openapi-cop-1            | 2022-12-13T12:33:40.431Z openapi-cop:proxy Received server response with status code 404
pfcapi-openapi-cop-1            | 2022-12-13T12:33:40.432Z openapi-cop:proxy Validation results [DELETE /internal/test/plans] {
pfcapi-openapi-cop-1            |   "request": {
pfcapi-openapi-cop-1            |     "valid": true,
pfcapi-openapi-cop-1            |     "errors": null
pfcapi-openapi-cop-1            |   }
pfcapi-openapi-cop-1            | }

Received by Test Driver

Note the combination of 500 and \"valid\":true.

HTTP/1.1 500 Internal Server Error
Connection: close
Date: Tue, 13 Dec 2022 12:33:40 GMT
Openapi-Cop-Source-Request: {\"method\":\"DELETE\",\"path\":\"/internal/test/plans\",\"headers\":{\"host\":\"subscriptions:5048\",\"user-agent\":\"Go-http-client/1.1\",\"authorization\":\"Basic ***\",\"x-request-id\":\"***\",\"x-span-parent-id\":\"***\",\"accept-encoding\":\"gzip\",\"connection\":\"close\"},\"query\":{}}
Openapi-Cop-Validation-Result: {\"request\":{\"valid\":true,\"errors\":null}}
X-Powered-By: Express
Content-Length: 0

Openapi-Cop-Source-Request

Expanded from ^

{
    "method": "DELETE",
    "path": "/internal/test/plans",
    "headers": {
        "host": "subscriptions:5048",
        "user-agent": "Go-http-client/1.1",
        "authorization": "Basic ***",
        "x-request-id": "***",
        "x-span-parent-id": "***",
        "accept-encoding": "gzip",
        "connection": "close"
    },
    "query": {}
}

Charset content type identifier not supported

I've noticed that the source code doe does not properly register the response validator if an operation's content type is defined with the charset identifier, such as

content:
          application/json; charset=UTF-8:

The issue seems to be line 438 of node_modules/openapi-backend/validation.js, where it simply checks to see if the content is application/json, this missing an application/json with a charset identifier.

 const validator = this.getAjv(ValidationContext.Response);
        _.mapKeys(operation.responses, (res, status) => {
            const response = res;
            if (response.content && response.content['application/json'] && **response.content['application/json'].schema) {
                const validateFn = response.content['application/json'].schema;
                responseValidators[status] = validator.compile(validateFn);**
            }
            return null;
        });
        this.statusBasedResponseValidators[operationId] = responseValidators;

302 redirect causes max redirects error

Sorry to spam the repo with issues.

The response that is returned to the proxy is:

< HTTP/1.1 302 FOUND
< Server: Werkzeug/2.2.2 Python/3.10.7
< Date: Mon, 26 Sep 2022 22:33:59 GMT
< Content-Type: text/html; charset=utf-8
< Content-Length: 669
< Location: $REDURECT_URL
< Vary: Cookie
< Set-Cookie: session=$COOKIE HttpOnly; Path=/
< Connection: close
< 
<!doctype html>
<html lang=en>
<title>Redirecting...</title>
<h1>Redirecting...</h1>
<p>You should be redirected automatically to the target URL: <a href="$REDURECT_URL">$REDURECT_URL</a>. If not, click the link.

However, when proxied through openapi-cop, I get this error Error: Exceeded maxRedirects. Probably stuck in a redirect loop $REDIRECT_URL. With the server outputting this:

(node:8) MaxListenersExceededWarning: Possible EventEmitter memory leak detected. 11 pipe listeners added. Use emitter.setMaxListeners() to increase limit
2022-09-26T22:34:53.451Z openapi-cop:proxy Validation results [GET /api/user/signin] 
{
  "request": {
    "valid": true,
    "errors": null
  }
}
2022-09-26T22:34:53.456Z openapi-cop:proxy Could not send request: Error: Exceeded maxRedirects. Probably stuck in a redirect loop $REDIRECT_URL

This makes the proxy unusable for endpoints that redirect.

Target URL matching regex should allow URI valid characters

Description

I am trying to use this to validate a hosted backend whose target URL happens to include dots and dashes, the target URL validation regex used only validates word characters /w and it should allow any URI valid character.

To Reproduce

Try any URL with dots, dashes in it, i.e. http://demo-server:8000/v1/

Tasks

Modify target URL validation regex to allow more characters, something like \w+:\/\/[A-Za-z0-9\-._~:\/?#[\]@!$&'()*+,;=]+:(\d{4})(\/|$)

Feature request: Log failed results on higher level

Could you log failed validations on warning level, and keep non-failed validations at debug?

If you have lots of successes and only a few failures this would make the output a lot easier to read.

openapi-cop/src/app.ts

Lines 157 to 160 in fbc58eb

debug(
`Validation results [${oasRequest.method} ${oasRequest.path}] ` +
JSON.stringify(validationResults, null, 2),
);

Adding `application/health+json` as accepted Content-Type

Hello, love the project idea, but while looking to bring this into an existing codebase, I hit a snag where it was giving a 500 internal server error when using Content-Type application/health+json. I would like to follow the rfc health check endpoint spec https://inadarei.github.io/rfc-healthcheck/.

The yaml spec for the endpoint is:

  /api/health:
    get:
      summary: Healthcheck to determine health of API. 
      responses:
        200:
          description: The request's query parameters.
          content:
            application/health+json:
              schema: 
                type: object
                properties:
                  status:
                    type: string
                    example: "ok"
                  description:
                    type: string
                    example: Description of endpoint.
                  version:
                    type: string
                    example: "0.0.1"
                  releaseId:
                    type: string
                    example: "release-id"
                  notes:
                    type: array
                    items:
                      type: string
                    example: [""]
                  output:
                    type: string
                    example: "Output of error"

The curl logs are:

< HTTP/1.1 500 Internal Server Error
< X-Powered-By: Express
< openapi-cop-source-request: {"method":"GET","path":"/api/health","headers":{"host":"localhost:8888","user-agent":"curl/7.79.1","accept":"*/*"},"query":{}}
< openapi-cop-validation-result: {"request":{"valid":true,"errors":null}}
< Date: Mon, 26 Sep 2022 21:49:33 GMT
< Connection: keep-alive
< Content-Length: 0

The server logs with verbose set to 1 are:

2022-09-26T21:49:33.007Z openapi-cop:proxy Received server response with status code 200
2022-09-26T21:49:33.008Z openapi-cop:proxy Validation results [GET /api/health] 
{
  "request": {
    "valid": true,
    "errors": null
   }
 }

If I change the Content-Type to application/json in the response, I get a 200 response, with a openapi-cop-validation-result containing response and responseHeaders objects.

I would be open to contributing if needed.

Dependency Dashboard

This issue lists Renovate updates and detected dependencies. Read the Dependency Dashboard docs to learn more.

Rate-Limited

These updates are currently rate-limited. Click on a checkbox below to force their creation now.

  • chore(deps): update docker/login-action digest to 5f4866a
  • chore(deps): update docker/metadata-action digest to 1294d94
  • chore(deps): update dependency @types/debug to v4.1.12
  • chore(deps): update dependency @types/errorhandler to v1.5.3
  • chore(deps): update dependency @types/js-yaml to v3.12.10
  • chore(deps): update dependency @types/json-schema to v7.0.15
  • chore(deps): update dependency @types/lodash.merge to v4.6.9
  • chore(deps): update dependency @types/morgan to v1.9.9
  • chore(deps): update dependency @types/node to v11.15.54
  • chore(deps): update dependency @types/request-promise-native to v1.0.21
  • chore(deps): update dependency @types/wait-on to v5.3.4
  • chore(deps): update dependency @types/which to v2.0.2
  • chore(deps): update dependency depcheck to v1.4.7
  • fix(deps): update dependency @types/valid-url to v1.0.7
  • fix(deps): update dependency content-type to v1.0.5 (content-type, @types/content-type)
  • chore(deps): update dependency @exxeta/openapi-cop-mock-server to v1.1.0
  • chore(deps): update dependency chai to v4.4.1 (chai, @types/chai)
  • chore(deps): update typescript-eslint monorepo to v5.62.0 (@typescript-eslint/eslint-plugin, @typescript-eslint/parser)
  • fix(deps): update dependency chokidar to v3.6.0
  • fix(deps): update dependency openapi-types to v12.1.3
  • fix(deps): update dependency qs to v6.12.1 (qs, @types/qs)
  • fix(deps): update dependency swagger-client to v3.27.2
  • chore(deps): update actions/checkout action to v4
  • chore(deps): update actions/setup-node action to v4
  • chore(deps): update dependency @types/prettier to v3
  • chore(deps): update dependency @types/swagger-parser to v7
  • chore(deps): update dependency @types/which to v3
  • chore(deps): update dependency chai to v5
  • chore(deps): update dependency eslint to v9
  • chore(deps): update dependency gts to v5
  • chore(deps): update dependency node to v20 (node, @types/node)
  • chore(deps): update dependency typescript to v5
  • chore(deps): update typescript-eslint monorepo to v7 (major) (@typescript-eslint/eslint-plugin, @typescript-eslint/parser)
  • fix(deps): update dependency commander to v12
  • fix(deps): update dependency wait-on to v7
  • fix(deps): update dependency which to v4
  • ๐Ÿ” Create all rate-limited PRs at once ๐Ÿ”

Open

These updates have all been created already. Click a checkbox below to force a retry/rebase of any.

Ignored or Blocked

These are blocked by an existing closed PR and will not be recreated unless you click a checkbox below.

Detected dependencies

dockerfile
docker/Dockerfile
  • node 10
  • node 10
github-actions
.github/workflows/nodejs.yml
  • actions/checkout v3
  • actions/setup-node v3
.github/workflows/publish-docker-image.yml
  • actions/checkout v3
  • docker/login-action f4ef78c080cd8ba55a85445d5b36e214a81df20a
  • docker/login-action f4ef78c080cd8ba55a85445d5b36e214a81df20a
  • docker/metadata-action 57396166ad8aefe6098280995947635806a0e6ea
  • docker/build-push-action 6e95f19fb8c9e00a1a391941edbc0ae30c1799f7
.github/workflows/publish-npm-package-mock-server.yml
  • actions/checkout v3
  • actions/setup-node v3
  • actions/checkout v3
  • actions/setup-node v3
.github/workflows/publish-npm-package.yml
  • actions/checkout v3
  • actions/setup-node v3
  • actions/checkout v3
  • actions/setup-node v3
npm
mock-server/package.json
  • chalk 4.1.2
  • chokidar 3.5.3
  • commander 4.1.1
  • debug 4.3.4
  • errorhandler 1.5.1
  • express 4.18.1
  • json-schema-ref-parser 9.0.9
  • js-yaml 3.14.1
  • morgan 1.10.0
  • openapi-backend 3.9.2
  • source-map-support 0.5.21
  • which 2.0.2
  • @types/errorhandler 1.5.0
  • @types/jest 27.5.2
  • @types/js-yaml 3.12.7
  • @types/json-schema 7.0.11
  • @types/morgan 1.9.3
  • @types/node 11.15.53
  • @types/prettier 2.6.0
  • @types/swagger-parser 4.0.3
  • @types/wait-on 5.3.1
  • @types/which 2.0.1
  • @typescript-eslint/eslint-plugin 5.41.0
  • @typescript-eslint/parser 5.41.0
  • axios 0.19.2
  • depcheck 1.4.3
  • eslint 7.32.0
  • gts 3.1.1
  • jest 27.5.1
  • ts-jest 27.1.5
  • typescript 4.8.4
  • wait-on 6.0.1
  • node ^10 || ^12
package.json
  • @types/express 4.17.13
  • @types/valid-url ^1.0.3
  • ajv 6.12.6
  • api-spec-converter 2.12.0
  • chalk 4.1.2
  • chokidar 3.5.3
  • commander 4.1.1
  • content-type 1.0.4
  • debug 4.3.4
  • express 4.18.1
  • js-yaml 3.14.1
  • json-schema-ref-parser 9.0.9
  • lodash 4.17.21
  • openapi-backend 3.9.2
  • openapi-types 12.0.2
  • qs 6.11.0
  • request-promise-native 1.0.9
  • swagger-client 3.18.5
  • swagger-parser 9.0.1
  • valid-url ^1.0.9
  • wait-on 6.0.1
  • @types/chai 4.3.3
  • @types/content-type 1.1.5
  • @types/debug 4.1.7
  • @types/js-yaml 3.12.7
  • @types/json-schema 7.0.11
  • @types/lodash.merge 4.6.7
  • @types/mocha 9.1.1
  • @types/node 10.17.60
  • @types/qs 6.9.7
  • @types/request-promise-native 1.0.18
  • @types/swagger-parser 4.0.3
  • @types/wait-on 5.3.1
  • @typescript-eslint/eslint-plugin 5.41.0
  • @typescript-eslint/parser 5.41.0
  • axios 0.19.2
  • chai 4.3.6
  • eslint 7.32.0
  • find-process 1.4.7
  • gts 3.1.1
  • mocha 9.2.2
  • @exxeta/openapi-cop-mock-server 1.0.1
  • typescript 4.0.5
  • node ^10 || ^12
nvm
.nvmrc
  • node 10

  • Check this box to trigger a request for Renovate to run again on this repository

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.