diff --git a/beego.go b/beego.go index 80718604..7b7109d3 100644 --- a/beego.go +++ b/beego.go @@ -383,6 +383,9 @@ func initBeforeHttpRun() { for u, _ := range StaticDir { Get(u+"/*", serverStaticRouter) } + if EnableDocs { + Get("/docs/*", serverDocs) + } } // this function is for test package init diff --git a/config.go b/config.go index aa8dc441..280edc6b 100644 --- a/config.go +++ b/config.go @@ -71,6 +71,7 @@ var ( FlashName string // name of the flash variable found in response header and cookie FlashSeperator string // used to seperate flash key:value AppConfigProvider string // config provider + EnableDocs bool // enable generate docs & server docs API Swagger ) func init() { @@ -361,6 +362,10 @@ func ParseConfig() (err error) { if adminhttpport, err := getConfig("int", "AdminHttpPort"); err == nil { AdminHttpPort = adminhttpport.(int) } + + if enabledocs, err := getConfig("bool", "EnableDocs"); err == nil { + EnableDocs = enabledocs.(bool) + } } return nil } diff --git a/docs.go b/docs.go new file mode 100644 index 00000000..b8e7d193 --- /dev/null +++ b/docs.go @@ -0,0 +1,38 @@ +package beego + +import ( + "encoding/json" + + "github.com/astaxie/beego/context" +) + +var GlobalDocApi map[string]interface{} + +func init() { + if EnableDocs { + GlobalDocApi = make(map[string]interface{}) + } +} + +func serverDocs(ctx *context.Context) { + var obj interface{} + if splat := ctx.Input.Param(":splat"); splat == "" { + obj = GlobalDocApi["Root"] + } else { + if v, ok := GlobalDocApi[splat]; ok { + obj = v + } + } + if obj != nil { + bt, err := json.Marshal(obj) + if err != nil { + ctx.Output.SetStatus(504) + return + } + ctx.Output.Header("Content-Type", "application/json;charset=UTF-8") + ctx.Output.Header("Access-Control-Allow-Origin", "*") + ctx.Output.Body(bt) + return + } + ctx.Output.SetStatus(404) +} diff --git a/docsSpec.go b/docsSpec.go new file mode 100644 index 00000000..ba1870a6 --- /dev/null +++ b/docsSpec.go @@ -0,0 +1,133 @@ +package beego + +const swaggerVersion = "1.2" + +type ResourceListing struct { + ApiVersion string `json:"apiVersion"` + SwaggerVersion string `json:"swaggerVersion"` // e.g 1.2 + // BasePath string `json:"basePath"` obsolete in 1.1 + Apis []ApiRef `json:"apis"` + Infos Infomation `json:"info"` +} + +type ApiRef struct { + Path string `json:"path"` // relative or absolute, must start with / + Description string `json:"description"` +} + +type Infomation struct { + Title string `json:"title,omitempty"` + Description string `json:"description,omitempty"` + Contact string `json:"contact,omitempty"` + TermsOfServiceUrl string `json:"termsOfServiceUrl,omitempty"` + License string `json:"license,omitempty"` + LicenseUrl string `json:"licenseUrl,omitempty"` +} + +// https://github.com/wordnik/swagger-core/blob/scala_2.10-1.3-RC3/schemas/api-declaration-schema.json +type ApiDeclaration struct { + ApiVersion string `json:"apiVersion"` + SwaggerVersion string `json:"swaggerVersion"` + BasePath string `json:"basePath"` + ResourcePath string `json:"resourcePath"` // must start with / + Consumes []string `json:"consumes,omitempty"` + Produces []string `json:"produces,omitempty"` + Apis []Api `json:"apis,omitempty"` + Models map[string]Model `json:"models,omitempty"` +} + +type Api struct { + Path string `json:"path"` // relative or absolute, must start with / + Description string `json:"description"` + Operations []Operation `json:"operations,omitempty"` +} + +type Operation struct { + HttpMethod string `json:"httpMethod"` + Nickname string `json:"nickname"` + Type string `json:"type"` // in 1.1 = DataType + // ResponseClass string `json:"responseClass"` obsolete in 1.2 + Summary string `json:"summary,omitempty"` + Notes string `json:"notes,omitempty"` + Parameters []Parameter `json:"parameters,omitempty"` + ResponseMessages []ResponseMessage `json:"responseMessages,omitempty"` // optional + Consumes []string `json:"consumes,omitempty"` + Produces []string `json:"produces,omitempty"` + Authorizations []Authorization `json:"authorizations,omitempty"` + Protocols []Protocol `json:"protocols,omitempty"` +} + +type Protocol struct { +} + +type ResponseMessage struct { + Code int `json:"code"` + Message string `json:"message"` + ResponseModel string `json:"responseModel"` +} + +type Parameter struct { + ParamType string `json:"paramType"` // path,query,body,header,form + Name string `json:"name"` + Description string `json:"description"` + DataType string `json:"dataType"` // 1.2 needed? + Type string `json:"type"` // integer + Format string `json:"format"` // int64 + AllowMultiple bool `json:"allowMultiple"` + Required bool `json:"required"` + Minimum int `json:"minimum"` + Maximum int `json:"maximum"` +} + +type ErrorResponse struct { + Code int `json:"code"` + Reason string `json:"reason"` +} + +type Model struct { + Id string `json:"id"` + Required []string `json:"required,omitempty"` + Properties map[string]ModelProperty `json:"properties"` +} + +type ModelProperty struct { + Type string `json:"type"` + Description string `json:"description"` + Items map[string]string `json:"items,omitempty"` + Format string `json:"format"` +} + +// https://github.com/wordnik/swagger-core/wiki/authorizations +type Authorization struct { + LocalOAuth OAuth `json:"local-oauth"` + ApiKey ApiKey `json:"apiKey"` +} + +// https://github.com/wordnik/swagger-core/wiki/authorizations +type OAuth struct { + Type string `json:"type"` // e.g. oauth2 + Scopes []string `json:"scopes"` // e.g. PUBLIC + GrantTypes map[string]GrantType `json:"grantTypes"` +} + +// https://github.com/wordnik/swagger-core/wiki/authorizations +type GrantType struct { + LoginEndpoint Endpoint `json:"loginEndpoint"` + TokenName string `json:"tokenName"` // e.g. access_code + TokenRequestEndpoint Endpoint `json:"tokenRequestEndpoint"` + TokenEndpoint Endpoint `json:"tokenEndpoint"` +} + +// https://github.com/wordnik/swagger-core/wiki/authorizations +type Endpoint struct { + Url string `json:"url"` + ClientIdName string `json:"clientIdName"` + ClientSecretName string `json:"clientSecretName"` + TokenName string `json:"tokenName"` +} + +// https://github.com/wordnik/swagger-core/wiki/authorizations +type ApiKey struct { + Type string `json:"type"` // e.g. apiKey + PassAs string `json:"passAs"` // e.g. header +}