Quick start deep dive - apigee-127/a127-documentation GitHub Wiki
Apigee-127 projects all follow a pattern similar to the "hello world" implementation described in Quick start. The quick start example lays down a project structure that includes a Swagger API specification (in YAML format), an implemented controller JavaScript file, and a base Node.js app. Let's look at these pieces one by one:
The project files are cloned directly from the https://github.com/apigee-127/project-skeleton
repository on GitHub. This skeleton project contains all the files and internal wirings needed for a basic Apigee-127 project.
hello-world-api
/api
/controllers
hello_world.js
/swagger
swagger.yaml
/config
index.js
default.yaml
app.js
package.json
README.md
You will find the API model in api/swagger/swagger.yaml
. This file conforms to the Swagger 2.0 specification, which models API behavior in a standard way, and enables tooling that lets you model, test, and document your API on the fly.
Note: YAML is a data serialization/representation standard. If you're new to YAML, check out www.yaml.org. Another excellent introduction is the Wikipedia YAML entry.
From the hello-world
folder, execute:
`a127 project edit`
This command launches the interactive Swagger editor, which loads the project's swagger.yaml
file.
Here is the entire hello-world app Swagger model. It conforms to the Swagger 2.0 specification, which is documented here. You'll notice there are several Apigee-127 specific extensions (x-swagger-router-controller
, etc.) included in the model. These extensions are explained below.
swagger: 2
info:
version: 0.0.1
title: Skeleton App
host: localhost
basePath: /
schemes:
- http
- https
consumes:
- application/json
produces:
- application/json
x-a127-services: {}
paths:
/hello:
x-swagger-router-controller: hello_world
x-a127-authorizations: {}
x-a127-apply: {}
get:
description: "Returns 'Hello' to the caller"
operationId: hello
produces:
- application/json
parameters:
- name: name
in: query
description: The name of the person to whom to say hello
required: false
type: string
responses:
"200":
description: Success
schema:
$ref: "#/definitions/HelloWorldResponse"
default:
description: Error
schema:
$ref: "#/definitions/ErrorResponse"
definitions:
HelloWorldResponse:
required:
- message
properties:
message:
type: string
ErrorResponse:
required:
- message
properties:
message:
type: string
The paths:
object specifies the API's resource paths, HTTP verb, query parameters, and more.
The x-swagger-router-controller
extension maps a path to a controller file, where the HTTP operation's logic is implemented. For example, in the hello world app, the path /hello
maps to a controller file controller/hello_world.js
:
paths:
/hello:
x-swagger-router-controller: hello_world
x-a127-apply: {}
get:
description: "Returns 'Hello' to the caller"
operationId: hello
Note: The extension x-swagger-router-controller
is a custom Apigee-127 extension to the Swagger model.
When a request is received, Apigee-127 looks at the endpoint (/hello
) and routes the request to a controller file. In this example, the controller/hello_world.js
implementation retrieves a query parameter sends back a "hello world" response to the caller:
function hello(req, res) {
var name = req.swagger.params.name.value;
var hello = name ? util.format('Hello, %s', name) : 'Hello, stranger!';
res.json(hello);
}
The main app.js
is a simple Express app consisting of these lines:
'use strict';
var a127 = require('a127-magic');
var express = require('express');
var app = express();
// uncomment the following if you need to parse incoming form data
app.use(express.bodyParser());
a127.init(function(config) {
app.use(a127.middleware(config));
app.listen(process.env.PORT || 10010);
console.log('try this:\ncurl http://127.0.0.1:10010/hello?name=Scott');
});
The a127-magic
module loads several Apigee-127 middleware modules. These modules perform tasks like Swagger specification validation, endpoint routing, and volos configuration:
- a127-magic
- swagger-tools
- middleware
- swagger-metadata.js
- swagger-router.js
- swagger-validator.js
- middleware
- volos-swagger
- lib
- connect-middleware.js
- lib
- js-yaml
- underscore
- swagger-tools
Lets look at the middleware components:
-
swagger-tools Provides middleware functions for: * swagger-metadata -- Provides Swagger configuration metadata to downstream middleware components. * swagger-router -- Uses Swagger middleware metadata to route requests to controllers. * swagger-validator - Uses Swagger information to validate API requests before they are routed to controllers.
-
volos-swagger Lets you configure volos features like caching and OAuth directly in the Swagger model file. For example, this stanza configures the volos "in memory" caching feature for your API.
x-a127-services:
cache:
provider: "volos-cache-memory"
options:
- "memCache"
- ttl: 10000
Similarly, you could configure caching using Redis or Apigee. Refer to the volos-swagger documentation for more information.
The pattern:
var a127 = require('a127-magic');
app.express=require('express');
var app = express();
app.use(a127.middleware());
is all you need to add this support to your application. Behind the scenes, the "wiring" and interaction is driven through the Swagger configuration file. The basic programming model is:
- Model your API using the Swagger editor. Define the API endpoints, request verbs, and optionally add features like volos-based caching, quota management, and OAuth.
- Implement controllers to handle each request endpoint.
- Drive, test, and document your API with the Swagger editor.