Osprey
Generate Node.JS API middleware from a RAML definition
Install / Use
/learn @mulesoft/OspreyREADME
Osprey
[![NPM version][npm-image]][npm-url]
[![NPM Downloads][downloads-image]][downloads-url]
[![Build status][travis-image]][travis-url]
[![Test coverage][coveralls-image]][coveralls-url]
Generate API middleware from a RAML definition, which can be used locally or globally for validating API requests and responses.
Features
- Automatic Request Validations
- Bodies
- Form data
- Url Encoded bodies
- JSON schemas
- XML schemas
- Headers
- Query parameters
- RAML 1.0 types
- Bodies
- Automatic Request Parameters
- Default Headers
- Default Parameters
- RAML Router
- Uses osprey-router for RAML paths
- Integrates with Express-format middleware servers
- Simple
req/res/nextmiddleware format that works with Connect, Express and evenhttp
- Simple
- API documentation Currently disabled
- Optionally mount API documentation generated from your RAML definition
- Built-in Error Handling Middleware
- I18n support
- Map validation paths to readable strings (with i18n support)
- Built-in Response Handling Coming soon
- Validate response bodies against status code definition
- Automatically fill default response headers
- Authentication
- OAuth 1.0 Coming Soon
- OAuth 2.0
- Basic Authentication
- Digest Authentication
- Custom Security Schemes
- RAML Mock Service
Osprey is built to enforce a documentation-first approach to APIs. It achieves this by:
Server
404ing on undocumented resources- Rejecting invalid requests bodies, headers and query parameters
- Populating default headers and query parameters
- Filtering undocumented headers and query parameters
- Validating API responses Coming soon
- Fill default response headers Coming soon
Security
- Setting up authentication endpoints and methods for you
- Authenticating endpoints as defined in RAML
Installation
Global
npm install osprey -g
Osprey can be used as a validation proxy with any other API server. Just install the module globally and use the CLI to set up the application endpoint(s) to proxy, as well as the RAML definition to use. Invalid API requests will be blocked before they reach your application server.
# Proxy to a running application (with optional documentation)
osprey -f api.raml -p 3000 -a localhost:8080
Options
-aApplication endpoint address (can be fully qualified URLs) and specify multiple, comma-separated addresses-fPath to the root RAML definition (E.g./path/to/api.raml)-pPort number to bind the proxy locally
Locally
npm install osprey --save
Usage
Osprey is normally used as a local node module and is compatible with any library supporting HTTP middleware, including Express and Connect. Just require the module locally and generate the middleware from a RAML definition file.
const osprey = require('osprey')
const express = require('express')
const join = require('path').join
const app = express()
const path = join(__dirname, 'assets', 'api.raml')
// Be careful, this uses all middleware functions by default. You might just
// want to use each one separately instead - `osprey.server`, etc.
osprey.loadFile(path)
.then(function (middleware) {
app.use(middleware)
app.use(function (err, req, res, next) {
// Handle errors.
})
app.listen(3000)
})
.catch(function(e) { console.error("Error: %s", e.message); });
Please note: The middleware function does not use the RAML baseUri. Make sure you mount the application under the correct path. E.g. app.use('/v1', middleware).
Server (Resource Handling)
const wap = require('webapi-parser').WebApiParser
// webapi-parser.WebApiDocument
const model = wap.raml10.parse('/some/api.raml')
const handler = osprey.server(model, options)
console.log(handler) //=> function (req, res, next) {}
console.log(handler.ramlUriParameters) //=> {} // A merged object of used URI parameters.
Undefined API requests will always be rejected with a 404.
Options
These are also passed along to osprey-method-handler).
- cors Enable CORS by setting to
trueor an object from cors (default:false) - compression Enable response compression using compression (default:
false) - notFoundHandler Use a
404error in middleware to skip over invalid/undefined routes from RAML (default:true)
From Osprey Method Handler:
- discardUnknownBodies Discard undefined request bodies (default:
true) - discardUnknownQueryParameters Discard undefined query parameters (default:
true) - discardUnknownHeaders Discard undefined header parameters (always includes known headers) (default:
true) - parseBodiesOnWildcard Toggle parsing bodies on wildcard body support (default:
false) - reviver The reviver passed to JSON.parse for JSON endpoints
- limit The maximum bytes for XML, JSON and URL-encoded endpoints (default:
'100kb') - parameterLimit The maximum number of URL-encoded parameters (default:
1000) - busboyLimits The limits for Busboy multipart form parsing
If you disable the default "not found" handler, it should be mounted later using osprey.server.notFoundHandler. For example, app.use(osprey.server.notFoundHandler).
Invalid Headers and Query Parameters
Invalid headers and query parameters are removed from the request. To read them they need to be documented in the RAML definition.
Request Bodies
Request bodies are parsed and validated for you, when you define the schema.
For application/json and application/x-www-form-urlencoded, the data will be an object under req.body. For text/xml, the body is stored as a string under req.body while the parsed XML document is under req.xml (uses LibXMLJS, not included). For multipart/form-data, you will need to attach field and file listeners to the request form (uses Busboy):
app.post('/users/{userId}', function (req, res, next) {
req.form.on('field', function (name, value) {
console.log(name + '=' + value)
})
req.form.on('file', function (name, stream, filename) {
stream.pipe(fs.createWriteStream(join(os.tmpDir(), filename)))
})
req.form.on('error', next)
req.pipe(req.form)
})
Headers, Parameters and Query Parameters
All parameters are automatically validated and parsed to the correct types according to the RAML document using webapi-parser and raml-sanitize. URL parameter validation comes with Osprey Router, available using osprey.Router.
// Similar to `express.Router`, but uses RAML paths.
const Router = require('osprey').Router
const utils = require('./utils')
// Array<webapi-parser.Parameter>
const parameters = utils.getUriParameters()
const app = new Router()
app.use(...)
app.get('/{slug}', parameters, function (req, res) {
res.send('success')
})
module.exports = app
You can initialize a Router with ramlUriParameters. This is helpful, since every router collects an object with merged URI parameters. For example, you can combine it with the server middleware to generate a router with your RAML URI parameters:
const handler = osprey.server(model)
const router = osprey.Router({ ramlUriParameters: handler.ramlUriParameters })
// Uses an existing `userId` URI parameter, if it exists.
router.get('/{userId}', function (req, res, next) {})
Handling Errors
Osprey returns a middleware router instance, so you can mount this within any compatible application and handle errors with the framework. For example, using HTTP with finalhandler (the same module Express uses):
const http = require('http')
const osprey = require('osprey')
const finalhandler = require('finalhandler')
const join = require('path').join
osprey.loadFile(join(__dirname, 'api.raml'))
.then(function (middleware) {
http.createServer(function (req, res) {
middleware(req, res, finalhandler(req, res))
}).listen(process.env.PORT || 3000)
})
.catch(function(e) { console.error("Error: %s", e.message); });
Error Types
error.ramlAuthorization = trueAn unauthorized error containing an array of errors that occured is set onerror.authorizationErrorserror.ramlValidation = trueA request failed validation and an array of validation data is set onerror.requestErrors(beware, different types contain different information)error.ramlNotFound = trueA request 404'd because it was not specified in the RAML definition for the API
Add JSON Schemas
JSON schemas can be added to the application for when external JSON references are needed. From osprey-method-handler.
osprey.addJsonSchema(schema, key)
Error Handler
Osprey comes with support for a built-in error handler middleware that formats request errors for APIs. It comes with built-in i18n with some languages already included for certain formats (help us add more!). The default fallback language is en and the default responder renders JSON, XML, HTML and plain text - all options are overridable.
Related Skills
node-connect
337.4kDiagnose OpenClaw node connection and pairing failures for Android, iOS, and macOS companion apps
frontend-design
83.2kCreate distinctive, production-grade frontend interfaces with high design quality. Use this skill when the user asks to build web components, pages, or applications. Generates creative, polished code that avoids generic AI aesthetics.
openai-whisper-api
337.4kTranscribe audio via OpenAI Audio Transcriptions API (Whisper).
commit-push-pr
83.2kCommit, push, and open a PR
