fafb09ddc2e4 — Sean Russell 11 years ago
First unmarshal tests pass
6 files changed, 728 insertions(+), 0 deletions(-)

A => api.go
A => resource_listing.go
A => swagger_test.go
A => test/api-docs.json
A => test/api-docs_pet.json
A => util.go
A => api.go +84 -0
@@ 0,0 1,84 @@ 
+package sashay
+
+type ApiDecl struct {
+	SwaggerVersion string
+	ApiVersion     string
+	BasePath       string
+	ResourcePath   string
+	Apis           []Api
+	Models         map[string]Model
+	Produces       []string
+	Consumes       []string
+	Authorizations map[string][]Scope
+}
+
+type Api struct {
+	Path        string
+	Description string
+	Operations  []Operation
+}
+
+type Model struct {
+	Id            string
+	Description   string
+	Required      []string
+	Properties    map[string]Property
+	SubTypes      []string
+	Discriminator string
+}
+type Method string
+
+const (
+	GET     Method = "GET"
+	POST    Method = "POST"
+	PUT     Method = "PUT"
+	PATCH   Method = "PATCH"
+	DELETE  Method = "DELETE"
+	OPTIONS Method = "OPTIONS"
+)
+
+type Operation struct {
+	DataTypeFields
+	Method           string // "GET", "POST", "PUT", "PATCH", "DELETE", "OPTIONS"
+	Summary          string
+	Notes            string
+	Nickname         string
+	Authorizations   map[string][]Scope
+	Parameters       []Parameter
+	ResponseMessages []ResponseMessage
+	Produces         []string
+	Consumes         []string
+	Deprecated       string
+}
+
+type Property struct {
+	DataTypeFields
+	Description string
+}
+
+type Parameter struct {
+	DataTypeFields
+	ParamType     string
+	Name          string
+	Description   string
+	Required      bool
+	AllowMultiple bool
+}
+
+type ResponseMessage struct {
+	code          int
+	message       string
+	responseModel string
+}
+
+type DataTypeFields struct {
+	Type         string
+	Ref          string
+	Format       string
+	DefaultValue interface{}
+	Enum         []string
+	Minimum      string
+	Maximum      string
+	Items        map[string]string
+	UniqueItems  bool
+}

          
A => resource_listing.go +64 -0
@@ 0,0 1,64 @@ 
+package sashay
+
+type ResourceListing struct {
+	Info           Info
+	Authorizations map[string]Authorization
+	ApiVersion     string
+	SwaggerVersion string
+	Apis           []Resource
+}
+
+type Info struct {
+	Title             string
+	Description       string
+	TermsOfServiceUrl string
+	Contact           string
+	License           string
+	LicenseUrl        string
+}
+type Authorization struct {
+	Type       string
+	PassAs     string
+	Keyname    string
+	Scopes     []Scope
+	GrantTypes GrantTypes
+}
+type Resource struct {
+	Path        string
+	Description string
+}
+
+type Scope struct {
+	Scope       string
+	Description string
+}
+
+type GrantTypes struct {
+	Implicit           Implicit
+	Authorization_code AuthorizationCode
+}
+
+type Implicit struct {
+	LoginEndpoint LoginEndpoint
+	TokenName     string
+}
+
+type AuthorizationCode struct {
+	TokenRequestEndpoint TokenRequestEndpoint
+	TokenEndpoint        TokenEndpoint
+}
+
+type LoginEndpoint struct {
+	Url string
+}
+
+type TokenRequestEndpoint struct {
+	Url              string
+	ClientIdName     string
+	ClientSecretName string
+}
+
+type TokenEndpoint struct {
+	Url       string
+	TokenName string
+}

          
A => swagger_test.go +62 -0
@@ 0,0 1,62 @@ 
+package sashay
+
+import (
+	"testing"
+	"io/ioutil"
+	"fmt"
+	"os"
+	. "gopkg.in/check.v1"
+)
+
+// Boiler plate for check
+func Test(t *testing.T) { TestingT(t) }
+type MySuite struct {}
+var _ = Suite(&MySuite{})
+
+var resourceListing, apiDocs []byte
+
+func init() {
+	fname := "test/api-docs.json"
+	b, e := ioutil.ReadFile(fname)
+	if e != nil {
+		fmt.Printf("error reading %s: %s", fname, e.Error())
+		os.Exit(1)
+	}
+	resourceListing = b
+
+	fname = "test/api-docs_pet.json"
+	b, e = ioutil.ReadFile(fname)
+	if e != nil {
+		fmt.Printf("error reading %s: %s", fname, e.Error())
+		os.Exit(1)
+	}
+	apiDocs = b
+}
+
+func (s *MySuite) TestParseResource(c *C) {
+	k, e := ParseResource(resourceListing)
+	c.Assert(e, IsNil)
+	c.Assert(len(k.Authorizations), Equals, 1)
+	c.Assert(len(k.Apis), Equals, 3)
+	c.Assert(k.SwaggerVersion, Equals, "1.2")
+	c.Assert(k.ApiVersion, Equals, "1.0.0")
+	c.Assert(k.Apis[0].Path, Equals, "/pet")
+}
+
+func (s *MySuite) TestParseApi(c *C) {
+	k, e := ParseApi(apiDocs)
+	c.Assert(e, IsNil)
+	c.Assert(len(k.Produces), Equals, 4)
+	c.Assert(len(k.Apis), Equals, 5)
+	c.Assert(k.Apis[0].Path, Equals, "/pet/{petId}")
+	c.Assert(k.Apis[0].Operations[0].Method, Equals, "DELETE")
+	c.Assert(k.Apis[0].Operations[1].Produces[0], Equals, "application/json")
+}
+
+
+func (s *MySuite) TestGen(c *C) {
+}
+
+
+// http://petstore.swagger.wordnik.com/api/api-docs
+// http://petstore.swagger.wordnik.com/api/api-docs/pet

          
A => test/api-docs.json +60 -0
@@ 0,0 1,60 @@ 
+{
+   "info" : {
+      "termsOfServiceUrl" : "http://helloreverb.com/terms/",
+      "licenseUrl" : "http://www.apache.org/licenses/LICENSE-2.0.html",
+      "contact" : "apiteam@wordnik.com",
+      "title" : "Swagger Sample App",
+      "license" : "Apache 2.0",
+      "description" : "This is a sample server Petstore server.  You can find out more about Swagger \n    at <a href=\"http://swagger.wordnik.com\">http://swagger.wordnik.com</a> or on irc.freenode.net, #swagger.  For this sample,\n    you can use the api key \"special-key\" to test the authorization filters"
+   },
+   "authorizations" : {
+      "oauth2" : {
+         "scopes" : [
+            {
+               "description" : "Modify pets in your account",
+               "scope" : "write:pets"
+            },
+            {
+               "description" : "Read your pets",
+               "scope" : "read:pets"
+            }
+         ],
+         "grantTypes" : {
+            "authorization_code" : {
+               "tokenRequestEndpoint" : {
+                  "clientIdName" : "client_id",
+                  "clientSecretName" : "client_secret",
+                  "url" : "http://petstore.swagger.wordnik.com/oauth/requestToken"
+               },
+               "tokenEndpoint" : {
+                  "tokenName" : "auth_code",
+                  "url" : "http://petstore.swagger.wordnik.com/oauth/token"
+               }
+            },
+            "implicit" : {
+               "tokenName" : "access_token",
+               "loginEndpoint" : {
+                  "url" : "http://petstore.swagger.wordnik.com/oauth/dialog"
+               }
+            }
+         },
+         "type" : "oauth2"
+      }
+   },
+   "apiVersion" : "1.0.0",
+   "swaggerVersion" : "1.2",
+   "apis" : [
+      {
+         "path" : "/pet",
+         "description" : "Operations about pets"
+      },
+      {
+         "path" : "/user",
+         "description" : "Operations about user"
+      },
+      {
+         "path" : "/store",
+         "description" : "Operations about store"
+      }
+   ]
+}

          
A => test/api-docs_pet.json +438 -0
@@ 0,0 1,438 @@ 
+{
+  "apiVersion": "1.0.0",
+  "swaggerVersion": "1.2",
+  "basePath": "http://petstore.swagger.wordnik.com/api",
+  "resourcePath": "/pet",
+  "produces": [
+    "application/json",
+    "application/xml",
+    "text/plain",
+    "text/html"
+  ],
+  "apis": [
+    {
+      "path": "/pet/{petId}",
+      "operations": [
+        {
+          "method": "DELETE",
+          "summary": "Deletes a pet",
+          "notes": "",
+          "type": "void",
+          "nickname": "deletePet",
+          "authorizations": {
+            "oauth2": [
+              {
+                "scope": "write:pets",
+                "description": "modify pets in your account"
+              }
+            ]
+          },
+          "parameters": [
+            {
+              "name": "petId",
+              "description": "Pet id to delete",
+              "required": true,
+              "type": "string",
+              "paramType": "path",
+              "allowMultiple": false
+            }
+          ],
+          "responseMessages": [
+            {
+              "code": 400,
+              "message": "Invalid pet value"
+            }
+          ]
+        },
+        {
+          "method": "PATCH",
+          "summary": "partial updates to a pet",
+          "notes": "",
+          "type": "array",
+          "items": {
+            "$ref": "Pet"
+          },
+          "nickname": "partialUpdate",
+          "produces": [
+            "application/json",
+            "application/xml"
+          ],
+          "consumes": [
+            "application/json",
+            "application/xml"
+          ],
+          "authorizations": {
+            "oauth2": [
+              {
+                "scope": "write:pets",
+                "description": "modify pets in your account"
+              }
+            ]
+          },
+          "parameters": [
+            {
+              "name": "petId",
+              "description": "ID of pet that needs to be fetched",
+              "required": true,
+              "type": "string",
+              "paramType": "path",
+              "allowMultiple": false
+            },
+            {
+              "name": "body",
+              "description": "Pet object that needs to be added to the store",
+              "required": true,
+              "type": "Pet",
+              "paramType": "body",
+              "allowMultiple": false
+            }
+          ],
+          "responseMessages": [
+            {
+              "code": 400,
+              "message": "Invalid tag value"
+            }
+          ]
+        },
+        {
+          "method": "POST",
+          "summary": "Updates a pet in the store with form data",
+          "notes": "",
+          "type": "void",
+          "nickname": "updatePetWithForm",
+          "consumes": [
+            "application/x-www-form-urlencoded"
+          ],
+          "authorizations": {
+            "oauth2": [
+              {
+                "scope": "write:pets",
+                "description": "modify pets in your account"
+              }
+            ]
+          },
+          "parameters": [
+            {
+              "name": "petId",
+              "description": "ID of pet that needs to be updated",
+              "required": true,
+              "type": "string",
+              "paramType": "path",
+              "allowMultiple": false
+            },
+            {
+              "name": "name",
+              "description": "Updated name of the pet",
+              "required": false,
+              "type": "string",
+              "paramType": "form",
+              "allowMultiple": false
+            },
+            {
+              "name": "status",
+              "description": "Updated status of the pet",
+              "required": false,
+              "type": "string",
+              "paramType": "form",
+              "allowMultiple": false
+            }
+          ],
+          "responseMessages": [
+            {
+              "code": 405,
+              "message": "Invalid input"
+            }
+          ]
+        },
+        {
+          "method": "GET",
+          "summary": "Find pet by ID",
+          "notes": "Returns a pet based on ID",
+          "type": "Pet",
+          "nickname": "getPetById",
+          "authorizations": {},
+          "parameters": [
+            {
+              "name": "petId",
+              "description": "ID of pet that needs to be fetched",
+              "required": true,
+              "type": "integer",
+              "format": "int64",
+              "paramType": "path",
+              "allowMultiple": false,
+              "minimum": "1.0",
+              "maximum": "100000.0"
+            }
+          ],
+          "responseMessages": [
+            {
+              "code": 400,
+              "message": "Invalid ID supplied"
+            },
+            {
+              "code": 404,
+              "message": "Pet not found"
+            }
+          ]
+        }
+      ]
+    },
+    {
+      "path": "/pet",
+      "operations": [
+        {
+          "method": "POST",
+          "summary": "Add a new pet to the store",
+          "notes": "",
+          "type": "void",
+          "nickname": "addPet",
+          "consumes": [
+            "application/json",
+            "application/xml"
+          ],
+          "authorizations": {
+            "oauth2": [
+              {
+                "scope": "write:pets",
+                "description": "modify pets in your account"
+              }
+            ]
+          },
+          "parameters": [
+            {
+              "name": "body",
+              "description": "Pet object that needs to be added to the store",
+              "required": true,
+              "type": "Pet",
+              "paramType": "body",
+              "allowMultiple": false
+            }
+          ],
+          "responseMessages": [
+            {
+              "code": 405,
+              "message": "Invalid input"
+            }
+          ]
+        },
+        {
+          "method": "PUT",
+          "summary": "Update an existing pet",
+          "notes": "",
+          "type": "void",
+          "nickname": "updatePet",
+          "authorizations": {},
+          "parameters": [
+            {
+              "name": "body",
+              "description": "Pet object that needs to be updated in the store",
+              "required": true,
+              "type": "Pet",
+              "paramType": "body",
+              "allowMultiple": false
+            }
+          ],
+          "responseMessages": [
+            {
+              "code": 400,
+              "message": "Invalid ID supplied"
+            },
+            {
+              "code": 404,
+              "message": "Pet not found"
+            },
+            {
+              "code": 405,
+              "message": "Validation exception"
+            }
+          ]
+        }
+      ]
+    },
+    {
+      "path": "/pet/findByStatus",
+      "operations": [
+        {
+          "method": "GET",
+          "summary": "Finds Pets by status",
+          "notes": "Multiple status values can be provided with comma seperated strings",
+          "type": "array",
+          "items": {
+            "$ref": "Pet"
+          },
+          "nickname": "findPetsByStatus",
+          "authorizations": {},
+          "parameters": [
+            {
+              "name": "status",
+              "description": "Status values that need to be considered for filter",
+              "defaultValue": "available",
+              "required": true,
+              "type": "string",
+              "paramType": "query",
+              "allowMultiple": true,
+              "enum": [
+                "available",
+                "pending",
+                "sold"
+              ]
+            }
+          ],
+          "responseMessages": [
+            {
+              "code": 400,
+              "message": "Invalid status value"
+            }
+          ]
+        }
+      ]
+    },
+    {
+      "path": "/pet/findByTags",
+      "operations": [
+        {
+          "method": "GET",
+          "summary": "Finds Pets by tags",
+          "notes": "Muliple tags can be provided with comma seperated strings. Use tag1, tag2, tag3 for testing.",
+          "type": "array",
+          "items": {
+            "$ref": "Pet"
+          },
+          "nickname": "findPetsByTags",
+          "authorizations": {},
+          "parameters": [
+            {
+              "name": "tags",
+              "description": "Tags to filter by",
+              "required": true,
+              "type": "string",
+              "paramType": "query",
+              "allowMultiple": true
+            }
+          ],
+          "responseMessages": [
+            {
+              "code": 400,
+              "message": "Invalid tag value"
+            }
+          ],
+          "deprecated": "true"
+        }
+      ]
+    },
+    {
+      "path": "/pet/uploadImage",
+      "operations": [
+        {
+          "method": "POST",
+          "summary": "uploads an image",
+          "notes": "",
+          "type": "void",
+          "nickname": "uploadFile",
+          "consumes": [
+            "multipart/form-data"
+          ],
+          "authorizations": {
+            "oauth2": [
+              {
+                "scope": "write:pets",
+                "description": "modify pets in your account"
+              },
+              {
+                "scope": "read:pets",
+                "description": "read your pets"
+              }
+            ]
+          },
+          "parameters": [
+            {
+              "name": "additionalMetadata",
+              "description": "Additional data to pass to server",
+              "required": false,
+              "type": "string",
+              "paramType": "form",
+              "allowMultiple": false
+            },
+            {
+              "name": "file",
+              "description": "file to upload",
+              "required": false,
+              "type": "File",
+              "paramType": "body",
+              "allowMultiple": false
+            }
+          ]
+        }
+      ]
+    }
+  ],
+  "models": {
+    "Tag": {
+      "id": "Tag",
+      "properties": {
+        "id": {
+          "type": "integer",
+          "format": "int64"
+        },
+        "name": {
+          "type": "string"
+        }
+      }
+    },
+    "Pet": {
+      "id": "Pet",
+      "required": [
+        "id",
+        "name"
+      ],
+      "properties": {
+        "id": {
+          "type": "integer",
+          "format": "int64",
+          "description": "unique identifier for the pet",
+          "minimum": "0.0",
+          "maximum": "100.0"
+        },
+        "category": {
+          "$ref": "Category"
+        },
+        "name": {
+          "type": "string"
+        },
+        "photoUrls": {
+          "type": "array",
+          "items": {
+            "type": "string"
+          }
+        },
+        "tags": {
+          "type": "array",
+          "items": {
+            "$ref": "Tag"
+          }
+        },
+        "status": {
+          "type": "string",
+          "description": "pet status in the store",
+          "enum": [
+            "available",
+            "pending",
+            "sold"
+          ]
+        }
+      }
+    },
+    "Category": {
+      "id": "Category",
+      "properties": {
+        "id": {
+          "type": "integer",
+          "format": "int64"
+        },
+        "name": {
+          "type": "string"
+        }
+      }
+    }
+  }
+}

          
A => util.go +20 -0
@@ 0,0 1,20 @@ 
+/*
+The sashay package provides primitives for turning Swagger JSON into Go code
+*/
+package sashay
+
+import (
+	"encoding/json"
+)
+
+func ParseResource(j []byte) (ResourceListing, error) {
+	var r ResourceListing
+	err := json.Unmarshal(j, &r)
+	return r, err
+}
+
+func ParseApi(j []byte) (ApiDecl, error) {
+	var r ApiDecl
+	err := json.Unmarshal(j, &r)
+	return r, err
+}