Updating go-restful to the latest version

This commit is contained in:
nikhiljindal 2015-03-12 15:13:21 -07:00
parent 07c2035630
commit e11f62cfcf
21 changed files with 305 additions and 103 deletions

4
Godeps/Godeps.json generated
View File

@ -151,8 +151,8 @@
},
{
"ImportPath": "github.com/emicklei/go-restful",
"Comment": "v1.1.2-50-g692a500",
"Rev": "692a50017a7049b26cf7ea4ccfc0d8c77369a793"
"Comment": "v1.1.3-9-g49e08a0",
"Rev": "49e08a07d31e2dae8005f28b5360a96746cd6365"
},
{
"ImportPath": "github.com/evanphx/json-patch",

View File

@ -52,6 +52,7 @@ func (u UserResource) findUser(request *restful.Request, response *restful.Respo
- Automatic CORS request handling (using a filter)
- API declaration for Swagger UI (see swagger package)
- Panic recovery to produce HTTP 500, customizable using RecoverHandler(...)
- Route errors produce HTTP 404/405/406/415 errors, customizable using ServiceErrorHandler(...)
### Resources

View File

@ -22,6 +22,7 @@ type Container struct {
containerFilters []FilterFunction
doNotRecover bool // default is false
recoverHandleFunc RecoverHandleFunction
serviceErrorHandleFunc ServiceErrorHandleFunction
router RouteSelector // default is a RouterJSR311, CurlyRouter is the faster alternative
contentEncodingEnabled bool // default is false
}
@ -35,6 +36,7 @@ func NewContainer() *Container {
containerFilters: []FilterFunction{},
doNotRecover: false,
recoverHandleFunc: logStackOnRecover,
serviceErrorHandleFunc: writeServiceError,
router: RouterJSR311{},
contentEncodingEnabled: false}
}
@ -49,6 +51,16 @@ func (c *Container) RecoverHandler(handler RecoverHandleFunction) {
c.recoverHandleFunc = handler
}
// ServiceErrorHandleFunction declares functions that can be used to handle a service error situation.
// The first argument is the service error. The second must be used to communicate an error response.
type ServiceErrorHandleFunction func(ServiceError, *Response)
// ServiceErrorHandler changes the default function (writeServiceError) to be called
// when a ServiceError is detected.
func (c *Container) ServiceErrorHandler(handler ServiceErrorHandleFunction) {
c.serviceErrorHandleFunc = handler
}
// DoNotRecover controls whether panics will be caught to return HTTP 500.
// If set to true, Route functions are responsible for handling any error situation.
// Default value is false = recover from panics. This has performance implications.
@ -125,6 +137,13 @@ func logStackOnRecover(panicReason interface{}, httpWriter http.ResponseWriter)
httpWriter.Write(buffer.Bytes())
}
// writeServiceError is the default ServiceErrorHandleFunction and is called
// when a ServiceError is returned during route selection. Default implementation
// calls resp.WriteErrorString(err.Code, err.Message)
func writeServiceError(err ServiceError, resp *Response) {
resp.WriteErrorString(err.Code, err.Message)
}
// Dispatch the incoming Http Request to a matching WebService.
func (c *Container) dispatch(httpWriter http.ResponseWriter, httpRequest *http.Request) {
// Instal panic recovery unless told otherwise
@ -172,7 +191,7 @@ func (c *Container) dispatch(httpWriter http.ResponseWriter, httpRequest *http.R
switch err.(type) {
case ServiceError:
ser := err.(ServiceError)
resp.WriteErrorString(ser.Code, ser.Message)
c.serviceErrorHandleFunc(ser, resp)
}
// TODO
}}
@ -217,6 +236,25 @@ func (c Container) Handle(pattern string, handler http.Handler) {
c.ServeMux.Handle(pattern, handler)
}
// HandleWithFilter registers the handler for the given pattern.
// Container's filter chain is applied for handler.
// If a handler already exists for pattern, HandleWithFilter panics.
func (c Container) HandleWithFilter(pattern string, handler http.Handler) {
f := func(httpResponse http.ResponseWriter, httpRequest *http.Request) {
if len(c.containerFilters) == 0 {
handler.ServeHTTP(httpResponse, httpRequest)
return
}
chain := FilterChain{Filters: c.containerFilters, Target: func(req *Request, resp *Response) {
handler.ServeHTTP(httpResponse, httpRequest)
}}
chain.ProcessFilter(NewRequest(httpRequest), NewResponse(httpResponse))
}
c.Handle(pattern, http.HandlerFunc(f))
}
// Filter appends a container FilterFunction. These are called before dispatching
// a http.Request to a WebService from the container
func (c *Container) Filter(filter FilterFunction) {

View File

@ -0,0 +1,21 @@
package restful
import (
"net/http"
"testing"
)
// go test -v -test.run TestContainer_computeAllowedMethods ...restful
func TestContainer_computeAllowedMethods(t *testing.T) {
wc := NewContainer()
ws1 := new(WebService).Path("/users")
ws1.Route(ws1.GET("{i}").To(dummy))
ws1.Route(ws1.POST("{i}").To(dummy))
wc.Add(ws1)
httpRequest, _ := http.NewRequest("GET", "http://api.his.com/users/1", nil)
rreq := Request{Request: httpRequest}
m := wc.computeAllowedMethods(&rreq)
if len(m) != 2 {
t.Errorf("got %d expected 2 methods, %v", len(m), m)
}
}

View File

@ -47,7 +47,7 @@ func (c CrossOriginResourceSharing) Filter(req *Request, resp *Response, chain *
}
if !included {
if trace {
traceLogger.Println("HTTP Origin:%s is not part of %v", origin, c.AllowedDomains)
traceLogger.Printf("HTTP Origin:%s is not part of %v", origin, c.AllowedDomains)
}
chain.ProcessFilter(req, resp)
return
@ -62,6 +62,8 @@ func (c CrossOriginResourceSharing) Filter(req *Request, resp *Response, chain *
c.doPreflightRequest(req, resp)
} else {
c.doActualRequest(req, resp)
chain.ProcessFilter(req, resp)
return
}
}
@ -70,7 +72,7 @@ func (c CrossOriginResourceSharing) doActualRequest(req *Request, resp *Response
// continue processing the response
}
func (c CrossOriginResourceSharing) doPreflightRequest(req *Request, resp *Response) {
func (c *CrossOriginResourceSharing) doPreflightRequest(req *Request, resp *Response) {
if len(c.AllowedMethods) == 0 {
c.AllowedMethods = c.Container.computeAllowedMethods(req)
}

View File

@ -12,7 +12,7 @@ import (
// It uses the httptest.ResponseRecorder to capture output
func getIt(req *restful.Request, resp *restful.Response) {
resp.WriteHeader(404)
resp.WriteHeader(204)
}
func TestCallFunction(t *testing.T) {
@ -20,10 +20,10 @@ func TestCallFunction(t *testing.T) {
req := restful.NewRequest(httpReq)
recorder := new(httptest.ResponseRecorder)
resp := restful.NewResponse(recoder)
resp := restful.NewResponse(recorder)
getIt(req, resp)
if recorder.Code != 404 {
t.Logf("Missing or wrong status code:%d", recorder.Code)
if recorder.Code != 204 {
t.Fatalf("Missing or wrong status code:%d", recorder.Code)
}
}

View File

@ -66,6 +66,14 @@ func TestDetectDispatcher(t *testing.T) {
// Step 2 tests
//
// go test -v -test.run TestISSUE_179 ...restful
func TestISSUE_179(t *testing.T) {
ws1 := new(WebService)
ws1.Route(ws1.GET("/v1/category/{param:*}").To(dummy))
routes := RouterJSR311{}.selectRoutes(ws1, "/v1/category/sub/sub")
t.Logf("%v", routes)
}
// go test -v -test.run TestISSUE_30 ...restful
func TestISSUE_30(t *testing.T) {
ws1 := new(WebService).Path("/users")
@ -181,38 +189,6 @@ func containsRoutePath(routes []Route, path string, t *testing.T) bool {
return false
}
var tempregexs = []struct {
template, regex string
literalCount, varCount int
}{
{"", "^(/.*)?$", 0, 0},
{"/a/{b}/c/", "^/a/([^/]+?)/c(/.*)?$", 2, 1},
{"/{a}/{b}/{c-d-e}/", "^/([^/]+?)/([^/]+?)/([^/]+?)(/.*)?$", 0, 3},
{"/{p}/abcde", "^/([^/]+?)/abcde(/.*)?$", 5, 1},
}
func TestTemplateToRegularExpression(t *testing.T) {
ok := true
for i, fixture := range tempregexs {
actual, lCount, vCount, _ := templateToRegularExpression(fixture.template)
if actual != fixture.regex {
t.Logf("regex mismatch, expected:%v , actual:%v, line:%v\n", fixture.regex, actual, i) // 11 = where the data starts
ok = false
}
if lCount != fixture.literalCount {
t.Logf("literal count mismatch, expected:%v , actual:%v, line:%v\n", fixture.literalCount, lCount, i)
ok = false
}
if vCount != fixture.varCount {
t.Logf("variable count mismatch, expected:%v , actual:%v, line:%v\n", fixture.varCount, vCount, i)
ok = false
}
}
if !ok {
t.Fatal("one or more expression did not match")
}
}
// go test -v -test.run TestSortableRouteCandidates ...restful
func TestSortableRouteCandidates(t *testing.T) {
fixture := &sortableRouteCandidates{}

View File

@ -9,7 +9,7 @@ import "strings"
// OPTIONSFilter is a filter function that inspects the Http Request for the OPTIONS method
// and provides the response with a set of allowed methods for the request URL Path.
// As for any filter, you can also install it for a particular WebService within a Container
func (c Container) OPTIONSFilter(req *Request, resp *Response, chain *FilterChain) {
func (c *Container) OPTIONSFilter(req *Request, resp *Response, chain *FilterChain) {
if "OPTIONS" != req.Request.Method {
chain.ProcessFilter(req, resp)
return

View File

@ -6,6 +6,7 @@ package restful
import (
"bytes"
"fmt"
"regexp"
"strings"
)
@ -43,9 +44,21 @@ func templateToRegularExpression(template string) (expression string, literalCou
}
buffer.WriteString("/")
if strings.HasPrefix(each, "{") {
// ignore var spec
// check for regular expression in variable
colon := strings.Index(each, ":")
if colon != -1 {
// extract expression
paramExpr := strings.TrimSpace(each[colon+1 : len(each)-1])
if paramExpr == "*" { // special case
buffer.WriteString("(.*)")
} else {
buffer.WriteString(fmt.Sprintf("(%s)", paramExpr)) // between colon and closing moustache
}
} else {
// plain var
buffer.WriteString("([^/]+?)")
}
varCount += 1
buffer.WriteString("([^/]+?)")
} else {
literalCount += len(each)
encoded := each // TODO URI encode

View File

@ -0,0 +1,37 @@
package restful
import "testing"
var tempregexs = []struct {
template, regex string
literalCount, varCount int
}{
{"", "^(/.*)?$", 0, 0},
{"/a/{b}/c/", "^/a/([^/]+?)/c(/.*)?$", 2, 1},
{"/{a}/{b}/{c-d-e}/", "^/([^/]+?)/([^/]+?)/([^/]+?)(/.*)?$", 0, 3},
{"/{p}/abcde", "^/([^/]+?)/abcde(/.*)?$", 5, 1},
{"/a/{b:*}", "^/a/(.*)(/.*)?$", 1, 1},
{"/a/{b:[a-z]+}", "^/a/([a-z]+)(/.*)?$", 1, 1},
}
func TestTemplateToRegularExpression(t *testing.T) {
ok := true
for i, fixture := range tempregexs {
actual, lCount, vCount, _ := templateToRegularExpression(fixture.template)
if actual != fixture.regex {
t.Logf("regex mismatch, expected:%v , actual:%v, line:%v\n", fixture.regex, actual, i) // 11 = where the data starts
ok = false
}
if lCount != fixture.literalCount {
t.Logf("literal count mismatch, expected:%v , actual:%v, line:%v\n", fixture.literalCount, lCount, i)
ok = false
}
if vCount != fixture.varCount {
t.Logf("variable count mismatch, expected:%v , actual:%v, line:%v\n", fixture.varCount, vCount, i)
ok = false
}
}
if !ok {
t.Fatal("one or more expression did not match")
}
}

View File

@ -29,6 +29,7 @@ type Route struct {
// documentation
Doc string
Notes string
Operation string
ParameterDocs []*Parameter
ResponseErrors map[int]ResponseError

View File

@ -21,6 +21,7 @@ type RouteBuilder struct {
filters []FilterFunction
// documentation
doc string
notes string
operation string
readSample, writeSample interface{}
parameters []*Parameter
@ -79,6 +80,12 @@ func (b *RouteBuilder) Doc(documentation string) *RouteBuilder {
return b
}
// A verbose explanation of the operation behavior. Optional.
func (b *RouteBuilder) Notes(notes string) *RouteBuilder {
b.notes = notes
return b
}
// Reads tells what resource type will be read from the request payload. Optional.
// A parameter of type "body" is added ,required is set to true and the dataType is set to the qualified name of the sample's type.
func (b *RouteBuilder) Reads(sample interface{}) *RouteBuilder {
@ -194,6 +201,7 @@ func (b *RouteBuilder) Build() Route {
relativePath: b.currentPath,
pathExpr: pathExpr,
Doc: b.doc,
Notes: b.notes,
Operation: b.operation,
ParameterDocs: b.parameters,
ResponseErrors: b.errorMap,

View File

@ -22,4 +22,6 @@ type Config struct {
StaticHandler http.Handler
// [optional] on default CORS (Cross-Origin-Resource-Sharing) is enabled.
DisableCORS bool
// Top-level API version. Is reflected in the resource listing.
ApiVersion string
}

View File

@ -168,8 +168,11 @@ func (b modelBuilder) buildArrayTypeProperty(field reflect.StructField, jsonName
var pType = "array"
prop.Type = &pType
elemName := b.getElementTypeName(modelName, jsonName, fieldType.Elem())
prop.Items = []Item{Item{Ref: &elemName}}
prop.Items = &Item{Ref: &elemName}
// add|overwrite model for element type
if fieldType.Elem().Kind() == reflect.Ptr {
fieldType = fieldType.Elem()
}
b.addModel(fieldType.Elem(), elemName)
return jsonName, prop
}
@ -182,7 +185,7 @@ func (b modelBuilder) buildPointerTypeProperty(field reflect.StructField, jsonNa
var pType = "array"
prop.Type = &pType
elemName := b.getElementTypeName(modelName, jsonName, fieldType.Elem().Elem())
prop.Items = []Item{Item{Ref: &elemName}}
prop.Items = &Item{Ref: &elemName}
// add|overwrite model for element type
b.addModel(fieldType.Elem().Elem(), elemName)
} else {
@ -200,6 +203,9 @@ func (b modelBuilder) buildPointerTypeProperty(field reflect.StructField, jsonNa
}
func (b modelBuilder) getElementTypeName(modelName, jsonName string, t reflect.Type) string {
if t.Kind() == reflect.Ptr {
return t.String()[1:]
}
if t.Name() == "" {
return modelName + "." + jsonName
}

View File

@ -95,11 +95,9 @@ func TestS2(t *testing.T) {
"properties": {
"Ids": {
"type": "array",
"items": [
{
"$ref": "string"
}
]
"items": {
"$ref": "string"
}
}
}
}
@ -177,11 +175,9 @@ func TestSampleToModelAsJson(t *testing.T) {
},
"items": {
"type": "array",
"items": [
{
"$ref": "swagger.item"
}
]
"items": {
"$ref": "swagger.item"
}
},
"root": {
"type": "swagger.item",
@ -361,11 +357,9 @@ func TestAnonymousArrayStruct(t *testing.T) {
"properties": {
"A": {
"type": "array",
"items": [
{
"$ref": "swagger.X.A"
}
]
"items": {
"$ref": "swagger.X.A"
}
}
}
},
@ -402,11 +396,9 @@ func TestAnonymousPtrArrayStruct(t *testing.T) {
"properties": {
"A": {
"type": "array",
"items": [
{
"$ref": "swagger.X.A"
}
]
"items": {
"$ref": "swagger.X.A"
}
}
}
},
@ -467,11 +459,9 @@ func TestIssue85(t *testing.T) {
"properties": {
"Datasets": {
"type": "array",
"items": [
{
"$ref": "swagger.Dataset"
}
]
"items": {
"$ref": "swagger.Dataset"
}
}
}
},
@ -483,11 +473,9 @@ func TestIssue85(t *testing.T) {
"properties": {
"Names": {
"type": "array",
"items": [
{
"$ref": "string"
}
]
"items": {
"$ref": "string"
}
}
}
}
@ -511,25 +499,17 @@ func TestRecursiveStructure(t *testing.T) {
"properties": {
"History": {
"type": "array",
"items": [
{
"$ref": "swagger.File"
}
]
"items": {
"$ref": "swagger.File"
}
},
"HistoryPtrs": {
"type": "array",
"items": [
{
"$ref": "swagger.File.HistoryPtrs"
}
]
"items": {
"$ref": "swagger.File"
}
}
}
},
"swagger.File.HistoryPtrs": {
"id": "swagger.File.HistoryPtrs",
"properties": {}
}
}`)
}
@ -669,11 +649,9 @@ func TestRegion_Issue113(t *testing.T) {
"properties": {
"id": {
"type": "array",
"items": [
{
"$ref": "integer"
}
]
"items": {
"$ref": "integer"
}
},
"name": {
"type": "string"
@ -727,3 +705,53 @@ func TestIssue158(t *testing.T) {
}`
testJsonFromStruct(t, Customer{}, expected)
}
func TestSlices(t *testing.T) {
type Address struct {
Country string `json:"country,omitempty"`
}
expected := `{
"swagger.Address": {
"id": "swagger.Address",
"properties": {
"country": {
"type": "string"
}
}
},
"swagger.Customer": {
"id": "swagger.Customer",
"required": [
"name",
"addresses"
],
"properties": {
"addresses": {
"type": "array",
"items": {
"$ref": "swagger.Address"
}
},
"name": {
"type": "string"
}
}
}
}`
// both slices (with pointer value and with type value) should have equal swagger representation
{
type Customer struct {
Name string `json:"name"`
Addresses []Address `json:"addresses"`
}
testJsonFromStruct(t, Customer{}, expected)
}
{
type Customer struct {
Name string `json:"name"`
Addresses []*Address `json:"addresses"`
}
testJsonFromStruct(t, Customer{}, expected)
}
}

View File

@ -0,0 +1,19 @@
package swagger
// Copyright 2014 Ernest Micklei. All rights reserved.
// Use of this source code is governed by a license
// that can be found in the LICENSE file.
type ResourceSorter []Resource
func (s ResourceSorter) Len() int {
return len(s)
}
func (s ResourceSorter) Swap(i, j int) {
s[i], s[j] = s[j], s[i]
}
func (s ResourceSorter) Less(i, j int) bool {
return s[i].Path < s[j].Path
}

View File

@ -13,7 +13,7 @@ type DataTypeFields struct {
Enum []string `json:"enum,omitempty"`
Minimum string `json:"minimum,omitempty"`
Maximum string `json:"maximum,omitempty"`
Items []Item `json:"items,omitempty"`
Items *Item `json:"items,omitempty"`
UniqueItems *bool `json:"uniqueItems,omitempty"`
}

View File

@ -103,10 +103,10 @@ func TestIssue78(t *testing.T) {
t.Fatal("wrong items type:" + *items.Type)
}
items_items := items.Items
if len(items_items) == 0 {
if items_items == nil {
t.Fatal("missing items->items")
}
ref := items_items[0].Ref
ref := items_items.Ref
if ref == nil {
t.Fatal("missing $ref")
}

View File

@ -2,6 +2,7 @@ package swagger
import (
"fmt"
"github.com/emicklei/go-restful"
// "github.com/emicklei/hopwatch"
"log"
@ -128,7 +129,7 @@ func enableCORS(req *restful.Request, resp *restful.Response, chain *restful.Fil
}
func (sws SwaggerService) getListing(req *restful.Request, resp *restful.Response) {
listing := ResourceListing{SwaggerVersion: swaggerVersion}
listing := ResourceListing{SwaggerVersion: swaggerVersion, ApiVersion: sws.config.ApiVersion}
for k, v := range sws.apiDeclarationMap {
ref := Resource{Path: k}
if len(v.Apis) > 0 { // use description of first (could still be empty)
@ -136,6 +137,7 @@ func (sws SwaggerService) getListing(req *restful.Request, resp *restful.Respons
}
listing.Apis = append(listing.Apis, ref)
}
sort.Sort(ResourceSorter(listing.Apis))
resp.WriteAsJson(listing)
}
@ -145,7 +147,21 @@ func (sws SwaggerService) getDeclarations(req *restful.Request, resp *restful.Re
if len(sws.config.WebServicesUrl) == 0 {
// update base path from the actual request
// TODO how to detect https? assume http for now
(&decl).BasePath = fmt.Sprintf("http://%s", req.Request.Host)
var host string
// X-Forwarded-Host or Host or Request.Host
hostvalues, ok := req.Request.Header["X-Forwarded-Host"] // apache specific?
if !ok || len(hostvalues) == 0 {
forwarded, ok := req.Request.Header["Host"] // without reverse-proxy
if !ok || len(forwarded) == 0 {
// fallback to Host field
host = req.Request.Host
} else {
host = forwarded[0]
}
} else {
host = hostvalues[0]
}
(&decl).BasePath = fmt.Sprintf("http://%s", host)
}
resp.WriteAsJson(decl)
}
@ -177,6 +193,7 @@ func (sws SwaggerService) composeDeclaration(ws *restful.WebService, pathPrefix
operation := Operation{
Method: route.Method,
Summary: route.Doc,
Notes: route.Notes,
Type: asDataType(route.WriteSample),
Parameters: []Parameter{},
Nickname: route.Operation,

View File

@ -33,15 +33,18 @@ func compareJson(t *testing.T, flatCompare bool, value interface{}, expectedJson
return
}
actual := string(output)
if actual != expectedJsonAsString {
t.Errorf("First mismatch JSON doc at line:%d", indexOfNonMatchingLine(actual, expectedJsonAsString))
// Use simple fmt to create a pastable output :-)
var actualMap map[string]interface{}
var expectedMap map[string]interface{}
json.Unmarshal(output, &actualMap)
json.Unmarshal([]byte(expectedJsonAsString), &expectedMap)
if !reflect.DeepEqual(actualMap, expectedMap) {
fmt.Println("---- expected -----")
fmt.Println(withLineNumbers(expectedJsonAsString))
fmt.Println("---- actual -----")
fmt.Println(withLineNumbers(actual))
fmt.Println("---- raw -----")
fmt.Println(actual)
t.Error("there are differences")
}
}

View File

@ -60,6 +60,12 @@ func (w *WebService) Param(parameter *Parameter) *WebService {
// PathParameter creates a new Parameter of kind Path for documentation purposes.
// It is initialized as required with string as its DataType.
func (w *WebService) PathParameter(name, description string) *Parameter {
return PathParameter(name, description)
}
// PathParameter creates a new Parameter of kind Path for documentation purposes.
// It is initialized as required with string as its DataType.
func PathParameter(name, description string) *Parameter {
p := &Parameter{&ParameterData{Name: name, Description: description, Required: true, DataType: "string"}}
p.bePath()
return p
@ -68,6 +74,12 @@ func (w *WebService) PathParameter(name, description string) *Parameter {
// QueryParameter creates a new Parameter of kind Query for documentation purposes.
// It is initialized as not required with string as its DataType.
func (w *WebService) QueryParameter(name, description string) *Parameter {
return QueryParameter(name, description)
}
// QueryParameter creates a new Parameter of kind Query for documentation purposes.
// It is initialized as not required with string as its DataType.
func QueryParameter(name, description string) *Parameter {
p := &Parameter{&ParameterData{Name: name, Description: description, Required: false, DataType: "string"}}
p.beQuery()
return p
@ -76,6 +88,12 @@ func (w *WebService) QueryParameter(name, description string) *Parameter {
// BodyParameter creates a new Parameter of kind Body for documentation purposes.
// It is initialized as required without a DataType.
func (w *WebService) BodyParameter(name, description string) *Parameter {
return BodyParameter(name, description)
}
// BodyParameter creates a new Parameter of kind Body for documentation purposes.
// It is initialized as required without a DataType.
func BodyParameter(name, description string) *Parameter {
p := &Parameter{&ParameterData{Name: name, Description: description, Required: true}}
p.beBody()
return p
@ -84,6 +102,12 @@ func (w *WebService) BodyParameter(name, description string) *Parameter {
// HeaderParameter creates a new Parameter of kind (Http) Header for documentation purposes.
// It is initialized as not required with string as its DataType.
func (w *WebService) HeaderParameter(name, description string) *Parameter {
return HeaderParameter(name, description)
}
// HeaderParameter creates a new Parameter of kind (Http) Header for documentation purposes.
// It is initialized as not required with string as its DataType.
func HeaderParameter(name, description string) *Parameter {
p := &Parameter{&ParameterData{Name: name, Description: description, Required: false, DataType: "string"}}
p.beHeader()
return p
@ -92,6 +116,12 @@ func (w *WebService) HeaderParameter(name, description string) *Parameter {
// FormParameter creates a new Parameter of kind Form (using application/x-www-form-urlencoded) for documentation purposes.
// It is initialized as required with string as its DataType.
func (w *WebService) FormParameter(name, description string) *Parameter {
return FormParameter(name, description)
}
// FormParameter creates a new Parameter of kind Form (using application/x-www-form-urlencoded) for documentation purposes.
// It is initialized as required with string as its DataType.
func FormParameter(name, description string) *Parameter {
p := &Parameter{&ParameterData{Name: name, Description: description, Required: false, DataType: "string"}}
p.beForm()
return p