Skip to content

Commit

Permalink
big restructuring of project layout
Browse files Browse the repository at this point in the history
  • Loading branch information
casualjim committed Jan 2, 2015
1 parent b73e3be commit ac3c88c
Show file tree
Hide file tree
Showing 445 changed files with 341 additions and 424 deletions.
141 changes: 106 additions & 35 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,50 +1,121 @@
# Swagger 2.0
# Framework design

[![Build Status](https://travis-ci.org/casualjim/go-swagger.svg?branch=feature/serve)](https://travis-ci.org/casualjim/go-swagger)
[![Coverage Status](https://coveralls.io/repos/casualjim/go-swagger/badge.png?branch=feature/serve)](https://coveralls.io/r/casualjim/go-swagger?branch=feature/serve)
[![GoDoc](https://godoc.org/github.com/casualjim/go-swagger?status.svg)](http://godoc.org/github.com/casualjim/go-swagger)
[![license](http://img.shields.io/badge/license-Apache%20v2-orange.svg)](https://raw.githubusercontent.com/swagger-api/swagger-spec/master/LICENSE)
The goals are to be as unintrusive as possible. The swagger spec is the source of truth for your application.

Contains an implementation of Swagger 2.0.
It knows how to serialize and deserialize swagger specifications.
The reference framework will make use of a swagger API that is based on the denco router.

Swagger is a simple yet powerful representation of your RESTful API.
With the largest ecosystem of API tooling on the planet, thousands of developers are supporting Swagger
in almost every modern programming language and deployment environment.
The general idea is that it is a middleware which you provide with the swagger spec.
This document can be either JSON or YAML as both are required.

With a Swagger-enabled API, you get interactive documentation, client SDK generation and discoverability.
We created Swagger to help fulfill the promise of APIs.
In addition to the middleware there are some generator commands that will use the swagger spec to generate models, parameter models, operation interfaces and a mux.

Swagger helps companies like Apigee, Getty Images, Intuit, LivingSocial, McKesson, Microsoft, Morningstar, and PayPal
build the best possible services with RESTful APIs.Now in version 2.0, Swagger is more enabling than ever.
And it's 100% open source software.
## The middleware

## Docs
Takes a raw spec document either as a []byte, and it adds the /api-docs route to serve this spec up.

http://godoc.org/github.com/casualjim/go-swagger
The middleware performs validation, data binding and security as defined in the swagger spec.
It also uses the API to match request paths to functions of `func(paramsObject) (responseModel, error)`

Install:
When a request comes in that doesn't match the /api-docs endpoint it will look for it in the swagger spec routes.
These are provided in the API. There is a tool to generate a statically typed API, based on operation names and
operation interfaces

go get -u github.com/casualjim/go-swagger/cmd/swagger
### The API

The implementation also provides a number of command line tools to help working with swagger.
The reference API will use the denco router to register route handlers.
The actual request handler implementation is always the same. The API must be designed in such a way that other frameworks can use their router implementation and perhaps their own validation infrastructure.

Currently there is a spec validator tool:
An API is served over http by a router, the default implementation is a router based on denco. This is just an interface implemenation so it can be replaced with another router should you so desire.

swagger validate https://raw.githubusercontent.com/swagger-api/swagger-spec/master/examples/v2.0/json/petstore-expanded.json
The API comes in 2 flavors an untyped one and a typed one.

## What's inside?
#### Untyped API

The untyped API is the main glue. It takes registrations of operation ids to operation handlers.
It also takes the registrations for mime types to consumers and producers. And it links security schemes to authentication handlers.

```go
type OperationHandler func(interface{}) (interface{}, error)
```

The API has methods to register consumers, producers, auth handlers and operation handlers

The register consumer and producer methods are responsible for attaching extra serializers to media types. These are then used during content negotiation phases for look up and binding the data.

When an API is used to initialize a router it goes through a validation step.
This validation step will verify that all the operations in the spec have a handler registered to them.
It also ensures that for all the mentioned media types there are consumers and producers provided.
And it checks if for each authentication scheme there is a handler present.
If this is not the case it will exit the application with a non-zero exit code.

The register method takes an operation name and a swagger operation handler.
It will then use that to build a path pattern for the router and it uses the swagger operation handler to produce a result based on the information in an incoming web request. It does this by injecing the handler in the swagger web request handler.

#### Typed API

The typed API uses a swagger spec to generate a typed API.

For this there is a generator that will take the swagger spec document.
It will then generate an interface for each operation and optionally a default implementation of that interface.
The default implemenation of an interface just returns a not implemented api error.

When all the interfaces and default implementations are generated it will generate a swagger mux implementation.
This swagger mux implemenation links all the interface implementations to operation names.
The typed API wraps an untyped API to do the actual route registration, it's mostly sugar for providing better compile time type safety.

This is done through integration in the `go generate` command

### The request handler

The request handler does the following things:

1. Authenticate and authorize if necessary
2. Validate the request data
3. Bind the request data to the parameter struct based on the swagger schema
4. Validate the parameter struct based on the swagger schema
5. Produce a model or an error by invoking the operation interface
6. Create a response with status code etc based on the operation interface invocation result

#### Authentication

TODO: put some coherent sentences here that describe how the auth integration is supposed to work.

Does this make it so that we require a context type object or add a pointer param for the principal on each authenticated operation?

Maybe it's better add a SwaggerPrincipal property to the operation parameter object?

```go
type SecurityHandler func(*http.Request) (interface{}, error)
```

#### Binding

Binding makes use of plain vanilla golang serializers and they are identified by the media type they consume and produce.

Binding is not only about request bodies but also about values obtained from headers, query string parameters and potentially the route path pattern. So the binding should make use of the full request object to produce a model.

It determines a serializer to use by looking in the the merged consumes values and the `Content-Type` header to determine which deserializer to use.
When a result is produced it will do the same thing by making use of the `Accept` http header etc and the merged produces clauses for the operation endpoint.

#### Validation

When the muxer registers routes it also builds a suite of validation plans, one for each operation.
Validation allows for adding custom validations for types through implementing a Validatable interface. This interface does not override but extends the validations provided by the swagger schema.

There is a mapping from validation name to status code, this mapping is also prioritized so that in the event of multiple validation errors that would required different status codes we get a consistent result.

```go
type Validatable interface {
Validate() []Error
}

type Error struct {
Code int32
Path string
In string
Value interface{}
Message string
}
```

* An object model that serializes to swagger yaml or json
* A tool to work with swagger:
* validate a swagger spec document
* Middlewares:
* routing
* validation

## Planned:
* Generate validations based on the swagger spec
* Later it will also know how to generate those specifications from your source code.
* Generate a stub api based on a swagger spec
* Generate a client from a swagger spec
* Build a full swagger spec by inspecting your source code and embedding it in a go file.
4 changes: 2 additions & 2 deletions swagger/api.go → api.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ import (
"net/http"
"strings"

"github.com/casualjim/go-swagger/swagger/errors"
"github.com/casualjim/go-swagger/swagger/spec"
"github.com/casualjim/go-swagger/errors"
"github.com/casualjim/go-swagger/spec"
)

// NewAPI creates the default untyped API
Expand Down
2 changes: 1 addition & 1 deletion swagger/api_test.go → api_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import (
"sort"
"testing"

"github.com/casualjim/go-swagger/swagger/spec"
"github.com/casualjim/go-swagger/spec"
"github.com/stretchr/testify/assert"
)

Expand Down
File renamed without changes.
File renamed without changes.
1 change: 1 addition & 0 deletions autoclean.sh
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
set -e

# Run test coverage on each subdirectories and merge the coverage profile.
godep go test -race ./...

echo "mode: count" > profile.cov

Expand Down
2 changes: 1 addition & 1 deletion cmd/swagger/commands/validate.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import (
"errors"
"fmt"

"github.com/casualjim/go-swagger/swagger/load"
"github.com/casualjim/go-swagger/load"
)

// ValidateSpec is a command that validates a swagger document
Expand Down
File renamed without changes.
File renamed without changes.
28 changes: 0 additions & 28 deletions doc.go

This file was deleted.

File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
6 changes: 3 additions & 3 deletions examples/2.0/petstore/server/api/petstore.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@ import (
"net/http"
"sync"

"github.com/casualjim/go-swagger/swagger"
"github.com/casualjim/go-swagger/swagger/spec"
"github.com/casualjim/go-swagger/swagger/testing"
"github.com/casualjim/go-swagger"
"github.com/casualjim/go-swagger/spec"
"github.com/casualjim/go-swagger/testing"
)

// NewPetstore creates a new petstore api handler
Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ import (
"net/url"
"strings"

"github.com/casualjim/go-swagger/swagger/jsonpointer"
"github.com/casualjim/go-swagger/jsonpointer"
)

const (
Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
2 changes: 1 addition & 1 deletion swagger/jsonschema/document.go → jsonschema/document.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ import (
"reflect"
"regexp"

"github.com/casualjim/go-swagger/swagger/jsonreference"
"github.com/casualjim/go-swagger/jsonreference"
)

// Load loads a json schema document from a loader
Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
Loading

0 comments on commit ac3c88c

Please sign in to comment.