mirror of
				https://gitea.com/Lydanne/buildx.git
				synced 2025-11-04 10:03:42 +08:00 
			
		
		
		
	vendor: bump k8s to v0.25.4
Signed-off-by: CrazyMax <crazy-max@users.noreply.github.com>
This commit is contained in:
		
							
								
								
									
										71
									
								
								vendor/github.com/emicklei/go-restful/v3/.gitignore
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										71
									
								
								vendor/github.com/emicklei/go-restful/v3/.gitignore
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,71 @@
 | 
			
		||||
# Compiled Object files, Static and Dynamic libs (Shared Objects)
 | 
			
		||||
*.o
 | 
			
		||||
*.a
 | 
			
		||||
*.so
 | 
			
		||||
 | 
			
		||||
# Folders
 | 
			
		||||
_obj
 | 
			
		||||
_test
 | 
			
		||||
 | 
			
		||||
# Architecture specific extensions/prefixes
 | 
			
		||||
*.[568vq]
 | 
			
		||||
[568vq].out
 | 
			
		||||
 | 
			
		||||
*.cgo1.go
 | 
			
		||||
*.cgo2.c
 | 
			
		||||
_cgo_defun.c
 | 
			
		||||
_cgo_gotypes.go
 | 
			
		||||
_cgo_export.*
 | 
			
		||||
 | 
			
		||||
_testmain.go
 | 
			
		||||
 | 
			
		||||
*.exe
 | 
			
		||||
 | 
			
		||||
restful.html
 | 
			
		||||
 | 
			
		||||
*.out
 | 
			
		||||
 | 
			
		||||
tmp.prof
 | 
			
		||||
 | 
			
		||||
go-restful.test
 | 
			
		||||
 | 
			
		||||
examples/restful-basic-authentication
 | 
			
		||||
 | 
			
		||||
examples/restful-encoding-filter
 | 
			
		||||
 | 
			
		||||
examples/restful-filters
 | 
			
		||||
 | 
			
		||||
examples/restful-hello-world
 | 
			
		||||
 | 
			
		||||
examples/restful-resource-functions
 | 
			
		||||
 | 
			
		||||
examples/restful-serve-static
 | 
			
		||||
 | 
			
		||||
examples/restful-user-service
 | 
			
		||||
 | 
			
		||||
*.DS_Store
 | 
			
		||||
examples/restful-user-resource
 | 
			
		||||
 | 
			
		||||
examples/restful-multi-containers
 | 
			
		||||
 | 
			
		||||
examples/restful-form-handling
 | 
			
		||||
 | 
			
		||||
examples/restful-CORS-filter
 | 
			
		||||
 | 
			
		||||
examples/restful-options-filter
 | 
			
		||||
 | 
			
		||||
examples/restful-curly-router
 | 
			
		||||
 | 
			
		||||
examples/restful-cpuprofiler-service
 | 
			
		||||
 | 
			
		||||
examples/restful-pre-post-filters
 | 
			
		||||
 | 
			
		||||
curly.prof
 | 
			
		||||
 | 
			
		||||
examples/restful-NCSA-logging
 | 
			
		||||
 | 
			
		||||
examples/restful-html-template
 | 
			
		||||
 | 
			
		||||
s.html
 | 
			
		||||
restful-path-tail
 | 
			
		||||
.idea
 | 
			
		||||
							
								
								
									
										1
									
								
								vendor/github.com/emicklei/go-restful/v3/.goconvey
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								vendor/github.com/emicklei/go-restful/v3/.goconvey
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1 @@
 | 
			
		||||
ignore
 | 
			
		||||
							
								
								
									
										13
									
								
								vendor/github.com/emicklei/go-restful/v3/.travis.yml
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								vendor/github.com/emicklei/go-restful/v3/.travis.yml
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,13 @@
 | 
			
		||||
language: go
 | 
			
		||||
 | 
			
		||||
go:
 | 
			
		||||
  - 1.x
 | 
			
		||||
 | 
			
		||||
before_install:
 | 
			
		||||
  - go test -v
 | 
			
		||||
 | 
			
		||||
script:
 | 
			
		||||
  - go test -race -coverprofile=coverage.txt -covermode=atomic
 | 
			
		||||
 | 
			
		||||
after_success:
 | 
			
		||||
  - bash <(curl -s https://codecov.io/bash)
 | 
			
		||||
							
								
								
									
										372
									
								
								vendor/github.com/emicklei/go-restful/v3/CHANGES.md
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										372
									
								
								vendor/github.com/emicklei/go-restful/v3/CHANGES.md
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,372 @@
 | 
			
		||||
# Change history of go-restful
 | 
			
		||||
 | 
			
		||||
## [v3.8.0] - 20221-06-06
 | 
			
		||||
 | 
			
		||||
- use exact matching of allowed domain entries, issue #489 (#493)
 | 
			
		||||
	- this changes fixes [security] Authorization Bypass Through User-Controlled Key
 | 
			
		||||
	  by changing the behaviour of the AllowedDomains setting in the CORS filter.
 | 
			
		||||
	  To support the previous behaviour, the CORS filter type now has a AllowedDomainFunc
 | 
			
		||||
	  callback mechanism which is called when a simple domain match fails. 
 | 
			
		||||
- add test and fix for POST without body and Content-type, issue #492 (#496)
 | 
			
		||||
- [Minor] Bad practice to have a mix of Receiver types. (#491)
 | 
			
		||||
 | 
			
		||||
## [v3.7.2] - 2021-11-24
 | 
			
		||||
 | 
			
		||||
- restored FilterChain (#482 by SVilgelm)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
## [v3.7.1] - 2021-10-04
 | 
			
		||||
 | 
			
		||||
- fix problem with contentEncodingEnabled setting (#479)
 | 
			
		||||
 | 
			
		||||
## [v3.7.0] - 2021-09-24
 | 
			
		||||
 | 
			
		||||
- feat(parameter): adds additional openapi mappings (#478)
 | 
			
		||||
 | 
			
		||||
## [v3.6.0] - 2021-09-18
 | 
			
		||||
 | 
			
		||||
- add support for vendor extensions (#477 thx erraggy)
 | 
			
		||||
 | 
			
		||||
## [v3.5.2] - 2021-07-14
 | 
			
		||||
 | 
			
		||||
- fix removing absent route from webservice (#472)
 | 
			
		||||
 | 
			
		||||
## [v3.5.1] - 2021-04-12
 | 
			
		||||
 | 
			
		||||
- fix handling no match access selected path
 | 
			
		||||
- remove obsolete field
 | 
			
		||||
 | 
			
		||||
## [v3.5.0] - 2021-04-10
 | 
			
		||||
 | 
			
		||||
- add check for wildcard (#463) in CORS
 | 
			
		||||
- add access to Route from Request, issue #459 (#462)
 | 
			
		||||
 | 
			
		||||
## [v3.4.0] - 2020-11-10
 | 
			
		||||
 | 
			
		||||
- Added OPTIONS to WebService
 | 
			
		||||
 | 
			
		||||
## [v3.3.2] - 2020-01-23
 | 
			
		||||
 | 
			
		||||
- Fixed duplicate compression in dispatch. #449
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
## [v3.3.1] - 2020-08-31
 | 
			
		||||
 | 
			
		||||
- Added check on writer to prevent compression of response twice. #447
 | 
			
		||||
 | 
			
		||||
## [v3.3.0] - 2020-08-19
 | 
			
		||||
 | 
			
		||||
- Enable content encoding on Handle and ServeHTTP (#446)
 | 
			
		||||
- List available representations in 406 body (#437)
 | 
			
		||||
- Convert to string using rune() (#443)
 | 
			
		||||
 | 
			
		||||
## [v3.2.0] - 2020-06-21
 | 
			
		||||
 | 
			
		||||
- 405 Method Not Allowed must have Allow header (#436) (thx Bracken <abdawson@gmail.com>)
 | 
			
		||||
- add field allowedMethodsWithoutContentType (#424)
 | 
			
		||||
 | 
			
		||||
## [v3.1.0]
 | 
			
		||||
 | 
			
		||||
- support describing response headers (#426)
 | 
			
		||||
- fix openapi examples (#425)
 | 
			
		||||
 | 
			
		||||
v3.0.0
 | 
			
		||||
 | 
			
		||||
- fix: use request/response resulting from filter chain
 | 
			
		||||
- add Go module
 | 
			
		||||
  Module consumer should use github.com/emicklei/go-restful/v3 as import path
 | 
			
		||||
 | 
			
		||||
v2.10.0
 | 
			
		||||
 | 
			
		||||
- support for Custom Verbs (thanks Vinci Xu <277040271@qq.com>)
 | 
			
		||||
- fixed static example (thanks Arthur <yang_yapo@126.com>)
 | 
			
		||||
- simplify code (thanks Christian Muehlhaeuser <muesli@gmail.com>)
 | 
			
		||||
- added JWT HMAC with SHA-512 authentication code example (thanks Amim Knabben <amim.knabben@gmail.com>)
 | 
			
		||||
 | 
			
		||||
v2.9.6
 | 
			
		||||
 | 
			
		||||
- small optimization in filter code
 | 
			
		||||
 | 
			
		||||
v2.11.1
 | 
			
		||||
 | 
			
		||||
- fix WriteError return value (#415)
 | 
			
		||||
 | 
			
		||||
v2.11.0 
 | 
			
		||||
 | 
			
		||||
- allow prefix and suffix in path variable expression (#414)
 | 
			
		||||
 | 
			
		||||
v2.9.6
 | 
			
		||||
 | 
			
		||||
- support google custome verb (#413)
 | 
			
		||||
 | 
			
		||||
v2.9.5
 | 
			
		||||
 | 
			
		||||
- fix panic in Response.WriteError if err == nil
 | 
			
		||||
 | 
			
		||||
v2.9.4
 | 
			
		||||
 | 
			
		||||
- fix issue #400 , parsing mime type quality
 | 
			
		||||
- Route Builder added option for contentEncodingEnabled (#398)
 | 
			
		||||
 | 
			
		||||
v2.9.3
 | 
			
		||||
 | 
			
		||||
- Avoid return of 415 Unsupported Media Type when request body is empty (#396)
 | 
			
		||||
 | 
			
		||||
v2.9.2
 | 
			
		||||
 | 
			
		||||
- Reduce allocations in per-request methods to improve performance (#395)
 | 
			
		||||
 | 
			
		||||
v2.9.1
 | 
			
		||||
 | 
			
		||||
- Fix issue with default responses and invalid status code 0. (#393)
 | 
			
		||||
 | 
			
		||||
v2.9.0
 | 
			
		||||
 | 
			
		||||
- add per Route content encoding setting (overrides container setting)
 | 
			
		||||
 | 
			
		||||
v2.8.0
 | 
			
		||||
 | 
			
		||||
- add Request.QueryParameters()
 | 
			
		||||
- add json-iterator (via build tag)
 | 
			
		||||
- disable vgo module (until log is moved)
 | 
			
		||||
 | 
			
		||||
v2.7.1
 | 
			
		||||
 | 
			
		||||
- add vgo module
 | 
			
		||||
 | 
			
		||||
v2.6.1
 | 
			
		||||
 | 
			
		||||
- add JSONNewDecoderFunc to allow custom JSON Decoder usage (go 1.10+)
 | 
			
		||||
 | 
			
		||||
v2.6.0
 | 
			
		||||
 | 
			
		||||
- Make JSR 311 routing and path param processing consistent
 | 
			
		||||
- Adding description to RouteBuilder.Reads()
 | 
			
		||||
- Update example for Swagger12 and OpenAPI
 | 
			
		||||
 | 
			
		||||
2017-09-13
 | 
			
		||||
 | 
			
		||||
- added route condition functions using `.If(func)` in route building.
 | 
			
		||||
 | 
			
		||||
2017-02-16
 | 
			
		||||
 | 
			
		||||
- solved issue #304, make operation names unique
 | 
			
		||||
 | 
			
		||||
2017-01-30
 | 
			
		||||
 
 | 
			
		||||
	[IMPORTANT] For swagger users, change your import statement to:	
 | 
			
		||||
	swagger "github.com/emicklei/go-restful-swagger12"
 | 
			
		||||
 | 
			
		||||
- moved swagger 1.2 code to go-restful-swagger12
 | 
			
		||||
- created TAG 2.0.0
 | 
			
		||||
 | 
			
		||||
2017-01-27
 | 
			
		||||
 | 
			
		||||
- remove defer request body close
 | 
			
		||||
- expose Dispatch for testing filters and Routefunctions
 | 
			
		||||
- swagger response model cannot be array 
 | 
			
		||||
- created TAG 1.0.0
 | 
			
		||||
 | 
			
		||||
2016-12-22
 | 
			
		||||
 | 
			
		||||
- (API change) Remove code related to caching request content. Removes SetCacheReadEntity(doCache bool)
 | 
			
		||||
 | 
			
		||||
2016-11-26
 | 
			
		||||
 | 
			
		||||
- Default change! now use CurlyRouter (was RouterJSR311)
 | 
			
		||||
- Default change! no more caching of request content
 | 
			
		||||
- Default change! do not recover from panics
 | 
			
		||||
 | 
			
		||||
2016-09-22
 | 
			
		||||
 | 
			
		||||
- fix the DefaultRequestContentType feature
 | 
			
		||||
 | 
			
		||||
2016-02-14
 | 
			
		||||
 | 
			
		||||
- take the qualify factor of the Accept header mediatype into account when deciding the contentype of the response
 | 
			
		||||
- add constructors for custom entity accessors for xml and json 
 | 
			
		||||
 | 
			
		||||
2015-09-27
 | 
			
		||||
 | 
			
		||||
- rename new WriteStatusAnd... to WriteHeaderAnd... for consistency
 | 
			
		||||
 | 
			
		||||
2015-09-25
 | 
			
		||||
 | 
			
		||||
- fixed problem with changing Header after WriteHeader (issue 235)
 | 
			
		||||
 | 
			
		||||
2015-09-14
 | 
			
		||||
 | 
			
		||||
- changed behavior of WriteHeader (immediate write) and WriteEntity (no status write)
 | 
			
		||||
- added support for custom EntityReaderWriters.
 | 
			
		||||
 | 
			
		||||
2015-08-06
 | 
			
		||||
 | 
			
		||||
- add support for reading entities from compressed request content
 | 
			
		||||
- use sync.Pool for compressors of http response and request body
 | 
			
		||||
- add Description to Parameter for documentation in Swagger UI
 | 
			
		||||
 | 
			
		||||
2015-03-20
 | 
			
		||||
 | 
			
		||||
- add configurable logging
 | 
			
		||||
 | 
			
		||||
2015-03-18
 | 
			
		||||
 | 
			
		||||
- if not specified, the Operation is derived from the Route function
 | 
			
		||||
 | 
			
		||||
2015-03-17
 | 
			
		||||
 | 
			
		||||
- expose Parameter creation functions
 | 
			
		||||
- make trace logger an interface
 | 
			
		||||
- fix OPTIONSFilter
 | 
			
		||||
- customize rendering of ServiceError
 | 
			
		||||
- JSR311 router now handles wildcards
 | 
			
		||||
- add Notes to Route
 | 
			
		||||
 | 
			
		||||
2014-11-27
 | 
			
		||||
 | 
			
		||||
- (api add) PrettyPrint per response. (as proposed in #167)
 | 
			
		||||
 | 
			
		||||
2014-11-12
 | 
			
		||||
 | 
			
		||||
- (api add) ApiVersion(.) for documentation in Swagger UI
 | 
			
		||||
 | 
			
		||||
2014-11-10
 | 
			
		||||
 | 
			
		||||
- (api change) struct fields tagged with "description" show up in Swagger UI
 | 
			
		||||
 | 
			
		||||
2014-10-31
 | 
			
		||||
 | 
			
		||||
- (api change) ReturnsError -> Returns
 | 
			
		||||
- (api add)    RouteBuilder.Do(aBuilder) for DRY use of RouteBuilder
 | 
			
		||||
- fix swagger nested structs
 | 
			
		||||
- sort Swagger response messages by code
 | 
			
		||||
 | 
			
		||||
2014-10-23
 | 
			
		||||
 | 
			
		||||
- (api add) ReturnsError allows you to document Http codes in swagger
 | 
			
		||||
- fixed problem with greedy CurlyRouter
 | 
			
		||||
- (api add) Access-Control-Max-Age in CORS
 | 
			
		||||
- add tracing functionality (injectable) for debugging purposes
 | 
			
		||||
- support JSON parse 64bit int 
 | 
			
		||||
- fix empty parameters for swagger
 | 
			
		||||
- WebServicesUrl is now optional for swagger
 | 
			
		||||
- fixed duplicate AccessControlAllowOrigin in CORS
 | 
			
		||||
- (api change) expose ServeMux in container
 | 
			
		||||
- (api add) added AllowedDomains in CORS
 | 
			
		||||
- (api add) ParameterNamed for detailed documentation
 | 
			
		||||
 | 
			
		||||
2014-04-16
 | 
			
		||||
 | 
			
		||||
- (api add) expose constructor of Request for testing.
 | 
			
		||||
 | 
			
		||||
2014-06-27
 | 
			
		||||
 | 
			
		||||
- (api add) ParameterNamed gives access to a Parameter definition and its data (for further specification).
 | 
			
		||||
- (api add) SetCacheReadEntity allow scontrol over whether or not the request body is being cached (default true for compatibility reasons).
 | 
			
		||||
 | 
			
		||||
2014-07-03
 | 
			
		||||
 | 
			
		||||
- (api add) CORS can be configured with a list of allowed domains
 | 
			
		||||
 | 
			
		||||
2014-03-12
 | 
			
		||||
 | 
			
		||||
- (api add) Route path parameters can use wildcard or regular expressions. (requires CurlyRouter)
 | 
			
		||||
 | 
			
		||||
2014-02-26
 | 
			
		||||
 | 
			
		||||
- (api add) Request now provides information about the matched Route, see method SelectedRoutePath 
 | 
			
		||||
 | 
			
		||||
2014-02-17
 | 
			
		||||
 | 
			
		||||
- (api change) renamed parameter constants (go-lint checks)
 | 
			
		||||
 | 
			
		||||
2014-01-10
 | 
			
		||||
 | 
			
		||||
- (api add) support for CloseNotify, see http://golang.org/pkg/net/http/#CloseNotifier
 | 
			
		||||
 | 
			
		||||
2014-01-07
 | 
			
		||||
 | 
			
		||||
- (api change) Write* methods in Response now return the error or nil.
 | 
			
		||||
- added example of serving HTML from a Go template.
 | 
			
		||||
- fixed comparing Allowed headers in CORS (is now case-insensitive)
 | 
			
		||||
 | 
			
		||||
2013-11-13
 | 
			
		||||
 | 
			
		||||
- (api add) Response knows how many bytes are written to the response body.
 | 
			
		||||
 | 
			
		||||
2013-10-29
 | 
			
		||||
 | 
			
		||||
- (api add) RecoverHandler(handler RecoverHandleFunction) to change how panic recovery is handled. Default behavior is to log and return a stacktrace. This may be a security issue as it exposes sourcecode information.
 | 
			
		||||
 | 
			
		||||
2013-10-04
 | 
			
		||||
 | 
			
		||||
- (api add) Response knows what HTTP status has been written
 | 
			
		||||
- (api add) Request can have attributes (map of string->interface, also called request-scoped variables
 | 
			
		||||
 | 
			
		||||
2013-09-12
 | 
			
		||||
 | 
			
		||||
- (api change) Router interface simplified
 | 
			
		||||
- Implemented CurlyRouter, a Router that does not use|allow regular expressions in paths
 | 
			
		||||
 | 
			
		||||
2013-08-05
 | 
			
		||||
 - add OPTIONS support
 | 
			
		||||
 - add CORS support
 | 
			
		||||
 | 
			
		||||
2013-08-27
 | 
			
		||||
 | 
			
		||||
- fixed some reported issues (see github)
 | 
			
		||||
- (api change) deprecated use of WriteError; use WriteErrorString instead
 | 
			
		||||
 | 
			
		||||
2014-04-15
 | 
			
		||||
 | 
			
		||||
- (fix) v1.0.1 tag: fix Issue 111: WriteErrorString
 | 
			
		||||
 | 
			
		||||
2013-08-08
 | 
			
		||||
 | 
			
		||||
- (api add) Added implementation Container: a WebServices collection with its own http.ServeMux allowing multiple endpoints per program. Existing uses of go-restful will register their services to the DefaultContainer.
 | 
			
		||||
- (api add) the swagger package has be extended to have a UI per container.
 | 
			
		||||
- if panic is detected then a small stack trace is printed (thanks to runner-mei)
 | 
			
		||||
- (api add) WriteErrorString to Response
 | 
			
		||||
 | 
			
		||||
Important API changes:
 | 
			
		||||
 | 
			
		||||
- (api remove) package variable DoNotRecover no longer works ; use restful.DefaultContainer.DoNotRecover(true) instead.
 | 
			
		||||
- (api remove) package variable EnableContentEncoding no longer works ; use restful.DefaultContainer.EnableContentEncoding(true) instead.
 | 
			
		||||
 
 | 
			
		||||
 
 | 
			
		||||
2013-07-06
 | 
			
		||||
 | 
			
		||||
- (api add) Added support for response encoding (gzip and deflate(zlib)). This feature is disabled on default (for backwards compatibility). Use restful.EnableContentEncoding = true in your initialization to enable this feature.
 | 
			
		||||
 | 
			
		||||
2013-06-19
 | 
			
		||||
 | 
			
		||||
- (improve) DoNotRecover option, moved request body closer, improved ReadEntity
 | 
			
		||||
 | 
			
		||||
2013-06-03
 | 
			
		||||
 | 
			
		||||
- (api change) removed Dispatcher interface, hide PathExpression
 | 
			
		||||
- changed receiver names of type functions to be more idiomatic Go
 | 
			
		||||
 | 
			
		||||
2013-06-02
 | 
			
		||||
 | 
			
		||||
- (optimize) Cache the RegExp compilation of Paths.
 | 
			
		||||
 | 
			
		||||
2013-05-22
 | 
			
		||||
	
 | 
			
		||||
- (api add) Added support for request/response filter functions
 | 
			
		||||
 | 
			
		||||
2013-05-18
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
- (api add) Added feature to change the default Http Request Dispatch function (travis cline)
 | 
			
		||||
- (api change) Moved Swagger Webservice to swagger package (see example restful-user)
 | 
			
		||||
 | 
			
		||||
[2012-11-14 .. 2013-05-18>
 | 
			
		||||
 
 | 
			
		||||
- See https://github.com/emicklei/go-restful/commits
 | 
			
		||||
 | 
			
		||||
2012-11-14
 | 
			
		||||
 | 
			
		||||
- Initial commit
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										22
									
								
								vendor/github.com/emicklei/go-restful/v3/LICENSE
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								vendor/github.com/emicklei/go-restful/v3/LICENSE
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,22 @@
 | 
			
		||||
Copyright (c) 2012,2013 Ernest Micklei
 | 
			
		||||
 | 
			
		||||
MIT License
 | 
			
		||||
 | 
			
		||||
Permission is hereby granted, free of charge, to any person obtaining
 | 
			
		||||
a copy of this software and associated documentation files (the
 | 
			
		||||
"Software"), to deal in the Software without restriction, including
 | 
			
		||||
without limitation the rights to use, copy, modify, merge, publish,
 | 
			
		||||
distribute, sublicense, and/or sell copies of the Software, and to
 | 
			
		||||
permit persons to whom the Software is furnished to do so, subject to
 | 
			
		||||
the following conditions:
 | 
			
		||||
 | 
			
		||||
The above copyright notice and this permission notice shall be
 | 
			
		||||
included in all copies or substantial portions of the Software.
 | 
			
		||||
 | 
			
		||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 | 
			
		||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 | 
			
		||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 | 
			
		||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
 | 
			
		||||
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
 | 
			
		||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 | 
			
		||||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 | 
			
		||||
							
								
								
									
										8
									
								
								vendor/github.com/emicklei/go-restful/v3/Makefile
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								vendor/github.com/emicklei/go-restful/v3/Makefile
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,8 @@
 | 
			
		||||
all: test
 | 
			
		||||
 | 
			
		||||
test:
 | 
			
		||||
	go vet .
 | 
			
		||||
	go test -cover -v .
 | 
			
		||||
 | 
			
		||||
ex:
 | 
			
		||||
	find ./examples -type f -name "*.go" | xargs -I {} go build -o /tmp/ignore {}
 | 
			
		||||
							
								
								
									
										110
									
								
								vendor/github.com/emicklei/go-restful/v3/README.md
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										110
									
								
								vendor/github.com/emicklei/go-restful/v3/README.md
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,110 @@
 | 
			
		||||
go-restful
 | 
			
		||||
==========
 | 
			
		||||
package for building REST-style Web Services using Google Go
 | 
			
		||||
 | 
			
		||||
[](https://travis-ci.org/emicklei/go-restful)
 | 
			
		||||
[](https://goreportcard.com/report/github.com/emicklei/go-restful)
 | 
			
		||||
[](https://pkg.go.dev/github.com/emicklei/go-restful)
 | 
			
		||||
[](https://codecov.io/gh/emicklei/go-restful)
 | 
			
		||||
 | 
			
		||||
- [Code examples use v3](https://github.com/emicklei/go-restful/tree/v3/examples)
 | 
			
		||||
 | 
			
		||||
REST asks developers to use HTTP methods explicitly and in a way that's consistent with the protocol definition. This basic REST design principle establishes a one-to-one mapping between create, read, update, and delete (CRUD) operations and HTTP methods. According to this mapping:
 | 
			
		||||
 | 
			
		||||
- GET = Retrieve a representation of a resource
 | 
			
		||||
- POST = Create if you are sending content to the server to create a subordinate of the specified resource collection, using some server-side algorithm.
 | 
			
		||||
- PUT = Create if you are sending the full content of the specified resource (URI).
 | 
			
		||||
- PUT = Update if you are updating the full content of the specified resource.
 | 
			
		||||
- DELETE = Delete if you are requesting the server to delete the resource
 | 
			
		||||
- PATCH = Update partial content of a resource
 | 
			
		||||
- OPTIONS = Get information about the communication options for the request URI
 | 
			
		||||
    
 | 
			
		||||
### Usage
 | 
			
		||||
 | 
			
		||||
#### Without Go Modules
 | 
			
		||||
 | 
			
		||||
All versions up to `v2.*.*` (on the master) are not supporting Go modules.
 | 
			
		||||
 | 
			
		||||
```
 | 
			
		||||
import (
 | 
			
		||||
	restful "github.com/emicklei/go-restful"
 | 
			
		||||
)
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
#### Using Go Modules
 | 
			
		||||
 | 
			
		||||
As of version `v3.0.0` (on the v3 branch), this package supports Go modules.
 | 
			
		||||
 | 
			
		||||
```
 | 
			
		||||
import (
 | 
			
		||||
	restful "github.com/emicklei/go-restful/v3"
 | 
			
		||||
)
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
### Example
 | 
			
		||||
 | 
			
		||||
```Go
 | 
			
		||||
ws := new(restful.WebService)
 | 
			
		||||
ws.
 | 
			
		||||
	Path("/users").
 | 
			
		||||
	Consumes(restful.MIME_XML, restful.MIME_JSON).
 | 
			
		||||
	Produces(restful.MIME_JSON, restful.MIME_XML)
 | 
			
		||||
 | 
			
		||||
ws.Route(ws.GET("/{user-id}").To(u.findUser).
 | 
			
		||||
	Doc("get a user").
 | 
			
		||||
	Param(ws.PathParameter("user-id", "identifier of the user").DataType("string")).
 | 
			
		||||
	Writes(User{}))		
 | 
			
		||||
...
 | 
			
		||||
	
 | 
			
		||||
func (u UserResource) findUser(request *restful.Request, response *restful.Response) {
 | 
			
		||||
	id := request.PathParameter("user-id")
 | 
			
		||||
	...
 | 
			
		||||
}
 | 
			
		||||
```
 | 
			
		||||
	
 | 
			
		||||
[Full API of a UserResource](https://github.com/emicklei/go-restful/blob/v3/examples/user-resource/restful-user-resource.go) 
 | 
			
		||||
		
 | 
			
		||||
### Features
 | 
			
		||||
 | 
			
		||||
- Routes for request → function mapping with path parameter (e.g. {id} but also prefix_{var} and {var}_suffix) support
 | 
			
		||||
- Configurable router:
 | 
			
		||||
	- (default) Fast routing algorithm that allows static elements, [google custom method](https://cloud.google.com/apis/design/custom_methods), regular expressions and dynamic parameters in the URL path (e.g. /resource/name:customVerb, /meetings/{id} or /static/{subpath:*})
 | 
			
		||||
	- Routing algorithm after [JSR311](http://jsr311.java.net/nonav/releases/1.1/spec/spec.html) that is implemented using (but does **not** accept) regular expressions
 | 
			
		||||
- Request API for reading structs from JSON/XML and accessing parameters (path,query,header)
 | 
			
		||||
- Response API for writing structs to JSON/XML and setting headers
 | 
			
		||||
- Customizable encoding using EntityReaderWriter registration
 | 
			
		||||
- Filters for intercepting the request → response flow on Service or Route level
 | 
			
		||||
- Request-scoped variables using attributes
 | 
			
		||||
- Containers for WebServices on different HTTP endpoints
 | 
			
		||||
- Content encoding (gzip,deflate) of request and response payloads
 | 
			
		||||
- Automatic responses on OPTIONS (using a filter)
 | 
			
		||||
- Automatic CORS request handling (using a filter)
 | 
			
		||||
- API declaration for Swagger UI ([go-restful-openapi](https://github.com/emicklei/go-restful-openapi), see [go-restful-swagger12](https://github.com/emicklei/go-restful-swagger12))
 | 
			
		||||
- Panic recovery to produce HTTP 500, customizable using RecoverHandler(...)
 | 
			
		||||
- Route errors produce HTTP 404/405/406/415 errors, customizable using ServiceErrorHandler(...)
 | 
			
		||||
- Configurable (trace) logging
 | 
			
		||||
- Customizable gzip/deflate readers and writers using CompressorProvider registration
 | 
			
		||||
 | 
			
		||||
## How to customize
 | 
			
		||||
There are several hooks to customize the behavior of the go-restful package.
 | 
			
		||||
 | 
			
		||||
- Router algorithm
 | 
			
		||||
- Panic recovery
 | 
			
		||||
- JSON decoder
 | 
			
		||||
- Trace logging
 | 
			
		||||
- Compression
 | 
			
		||||
- Encoders for other serializers
 | 
			
		||||
- Use [jsoniter](https://github.com/json-iterator/go) by build this package using a tag, e.g. `go build -tags=jsoniter .` 
 | 
			
		||||
 | 
			
		||||
## Resources
 | 
			
		||||
 | 
			
		||||
- [Example programs](./examples)
 | 
			
		||||
- [Example posted on blog](http://ernestmicklei.com/2012/11/go-restful-first-working-example/)
 | 
			
		||||
- [Design explained on blog](http://ernestmicklei.com/2012/11/go-restful-api-design/)
 | 
			
		||||
- [sourcegraph](https://sourcegraph.com/github.com/emicklei/go-restful)
 | 
			
		||||
- [showcase: Zazkia - tcp proxy for testing resiliency](https://github.com/emicklei/zazkia)
 | 
			
		||||
- [showcase: Mora - MongoDB REST Api server](https://github.com/emicklei/mora)
 | 
			
		||||
 | 
			
		||||
Type ```git shortlog -s``` for a full list of contributors.
 | 
			
		||||
 | 
			
		||||
© 2012 - 2022, http://ernestmicklei.com. MIT License. Contributions are welcome.
 | 
			
		||||
							
								
								
									
										13
									
								
								vendor/github.com/emicklei/go-restful/v3/SECURITY.md
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								vendor/github.com/emicklei/go-restful/v3/SECURITY.md
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,13 @@
 | 
			
		||||
# Security Policy
 | 
			
		||||
 | 
			
		||||
## Supported Versions
 | 
			
		||||
 | 
			
		||||
| Version | Supported          |
 | 
			
		||||
| ------- | ------------------ |
 | 
			
		||||
| v3.7.x     | :white_check_mark: |
 | 
			
		||||
| < v3.0.1   | :x:                |
 | 
			
		||||
 | 
			
		||||
## Reporting a Vulnerability
 | 
			
		||||
 | 
			
		||||
Create an Issue and put the label `[security]` in the title of the issue.
 | 
			
		||||
Valid reported security issues are expected to be solved within a week.
 | 
			
		||||
							
								
								
									
										1
									
								
								vendor/github.com/emicklei/go-restful/v3/Srcfile
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								vendor/github.com/emicklei/go-restful/v3/Srcfile
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1 @@
 | 
			
		||||
{"SkipDirs": ["examples"]}
 | 
			
		||||
							
								
								
									
										10
									
								
								vendor/github.com/emicklei/go-restful/v3/bench_test.sh
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								vendor/github.com/emicklei/go-restful/v3/bench_test.sh
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,10 @@
 | 
			
		||||
#go test -run=none -file bench_test.go -test.bench . -cpuprofile=bench_test.out
 | 
			
		||||
 | 
			
		||||
go test -c
 | 
			
		||||
./go-restful.test -test.run=none -test.cpuprofile=tmp.prof -test.bench=BenchmarkMany
 | 
			
		||||
./go-restful.test -test.run=none -test.cpuprofile=curly.prof -test.bench=BenchmarkManyCurly
 | 
			
		||||
 | 
			
		||||
#go tool pprof go-restful.test tmp.prof
 | 
			
		||||
go tool pprof go-restful.test curly.prof
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										127
									
								
								vendor/github.com/emicklei/go-restful/v3/compress.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										127
									
								
								vendor/github.com/emicklei/go-restful/v3/compress.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,127 @@
 | 
			
		||||
package restful
 | 
			
		||||
 | 
			
		||||
// Copyright 2013 Ernest Micklei. All rights reserved.
 | 
			
		||||
// Use of this source code is governed by a license
 | 
			
		||||
// that can be found in the LICENSE file.
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"bufio"
 | 
			
		||||
	"compress/gzip"
 | 
			
		||||
	"compress/zlib"
 | 
			
		||||
	"errors"
 | 
			
		||||
	"io"
 | 
			
		||||
	"net"
 | 
			
		||||
	"net/http"
 | 
			
		||||
	"strings"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// OBSOLETE : use restful.DefaultContainer.EnableContentEncoding(true) to change this setting.
 | 
			
		||||
var EnableContentEncoding = false
 | 
			
		||||
 | 
			
		||||
// CompressingResponseWriter is a http.ResponseWriter that can perform content encoding (gzip and zlib)
 | 
			
		||||
type CompressingResponseWriter struct {
 | 
			
		||||
	writer     http.ResponseWriter
 | 
			
		||||
	compressor io.WriteCloser
 | 
			
		||||
	encoding   string
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Header is part of http.ResponseWriter interface
 | 
			
		||||
func (c *CompressingResponseWriter) Header() http.Header {
 | 
			
		||||
	return c.writer.Header()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// WriteHeader is part of http.ResponseWriter interface
 | 
			
		||||
func (c *CompressingResponseWriter) WriteHeader(status int) {
 | 
			
		||||
	c.writer.WriteHeader(status)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Write is part of http.ResponseWriter interface
 | 
			
		||||
// It is passed through the compressor
 | 
			
		||||
func (c *CompressingResponseWriter) Write(bytes []byte) (int, error) {
 | 
			
		||||
	if c.isCompressorClosed() {
 | 
			
		||||
		return -1, errors.New("Compressing error: tried to write data using closed compressor")
 | 
			
		||||
	}
 | 
			
		||||
	return c.compressor.Write(bytes)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// CloseNotify is part of http.CloseNotifier interface
 | 
			
		||||
func (c *CompressingResponseWriter) CloseNotify() <-chan bool {
 | 
			
		||||
	return c.writer.(http.CloseNotifier).CloseNotify()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Close the underlying compressor
 | 
			
		||||
func (c *CompressingResponseWriter) Close() error {
 | 
			
		||||
	if c.isCompressorClosed() {
 | 
			
		||||
		return errors.New("Compressing error: tried to close already closed compressor")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	c.compressor.Close()
 | 
			
		||||
	if ENCODING_GZIP == c.encoding {
 | 
			
		||||
		currentCompressorProvider.ReleaseGzipWriter(c.compressor.(*gzip.Writer))
 | 
			
		||||
	}
 | 
			
		||||
	if ENCODING_DEFLATE == c.encoding {
 | 
			
		||||
		currentCompressorProvider.ReleaseZlibWriter(c.compressor.(*zlib.Writer))
 | 
			
		||||
	}
 | 
			
		||||
	// gc hint needed?
 | 
			
		||||
	c.compressor = nil
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (c *CompressingResponseWriter) isCompressorClosed() bool {
 | 
			
		||||
	return nil == c.compressor
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Hijack implements the Hijacker interface
 | 
			
		||||
// This is especially useful when combining Container.EnabledContentEncoding
 | 
			
		||||
// in combination with websockets (for instance gorilla/websocket)
 | 
			
		||||
func (c *CompressingResponseWriter) Hijack() (net.Conn, *bufio.ReadWriter, error) {
 | 
			
		||||
	hijacker, ok := c.writer.(http.Hijacker)
 | 
			
		||||
	if !ok {
 | 
			
		||||
		return nil, nil, errors.New("ResponseWriter doesn't support Hijacker interface")
 | 
			
		||||
	}
 | 
			
		||||
	return hijacker.Hijack()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// WantsCompressedResponse reads the Accept-Encoding header to see if and which encoding is requested.
 | 
			
		||||
// It also inspects the httpWriter whether its content-encoding is already set (non-empty).
 | 
			
		||||
func wantsCompressedResponse(httpRequest *http.Request, httpWriter http.ResponseWriter) (bool, string) {
 | 
			
		||||
	if contentEncoding := httpWriter.Header().Get(HEADER_ContentEncoding); contentEncoding != "" {
 | 
			
		||||
		return false, ""
 | 
			
		||||
	}
 | 
			
		||||
	header := httpRequest.Header.Get(HEADER_AcceptEncoding)
 | 
			
		||||
	gi := strings.Index(header, ENCODING_GZIP)
 | 
			
		||||
	zi := strings.Index(header, ENCODING_DEFLATE)
 | 
			
		||||
	// use in order of appearance
 | 
			
		||||
	if gi == -1 {
 | 
			
		||||
		return zi != -1, ENCODING_DEFLATE
 | 
			
		||||
	} else if zi == -1 {
 | 
			
		||||
		return gi != -1, ENCODING_GZIP
 | 
			
		||||
	} else {
 | 
			
		||||
		if gi < zi {
 | 
			
		||||
			return true, ENCODING_GZIP
 | 
			
		||||
		}
 | 
			
		||||
		return true, ENCODING_DEFLATE
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// NewCompressingResponseWriter create a CompressingResponseWriter for a known encoding = {gzip,deflate}
 | 
			
		||||
func NewCompressingResponseWriter(httpWriter http.ResponseWriter, encoding string) (*CompressingResponseWriter, error) {
 | 
			
		||||
	httpWriter.Header().Set(HEADER_ContentEncoding, encoding)
 | 
			
		||||
	c := new(CompressingResponseWriter)
 | 
			
		||||
	c.writer = httpWriter
 | 
			
		||||
	var err error
 | 
			
		||||
	if ENCODING_GZIP == encoding {
 | 
			
		||||
		w := currentCompressorProvider.AcquireGzipWriter()
 | 
			
		||||
		w.Reset(httpWriter)
 | 
			
		||||
		c.compressor = w
 | 
			
		||||
		c.encoding = ENCODING_GZIP
 | 
			
		||||
	} else if ENCODING_DEFLATE == encoding {
 | 
			
		||||
		w := currentCompressorProvider.AcquireZlibWriter()
 | 
			
		||||
		w.Reset(httpWriter)
 | 
			
		||||
		c.compressor = w
 | 
			
		||||
		c.encoding = ENCODING_DEFLATE
 | 
			
		||||
	} else {
 | 
			
		||||
		return nil, errors.New("Unknown encoding:" + encoding)
 | 
			
		||||
	}
 | 
			
		||||
	return c, err
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										103
									
								
								vendor/github.com/emicklei/go-restful/v3/compressor_cache.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										103
									
								
								vendor/github.com/emicklei/go-restful/v3/compressor_cache.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,103 @@
 | 
			
		||||
package restful
 | 
			
		||||
 | 
			
		||||
// Copyright 2015 Ernest Micklei. All rights reserved.
 | 
			
		||||
// Use of this source code is governed by a license
 | 
			
		||||
// that can be found in the LICENSE file.
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"compress/gzip"
 | 
			
		||||
	"compress/zlib"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// BoundedCachedCompressors is a CompressorProvider that uses a cache with a fixed amount
 | 
			
		||||
// of writers and readers (resources).
 | 
			
		||||
// If a new resource is acquired and all are in use, it will return a new unmanaged resource.
 | 
			
		||||
type BoundedCachedCompressors struct {
 | 
			
		||||
	gzipWriters     chan *gzip.Writer
 | 
			
		||||
	gzipReaders     chan *gzip.Reader
 | 
			
		||||
	zlibWriters     chan *zlib.Writer
 | 
			
		||||
	writersCapacity int
 | 
			
		||||
	readersCapacity int
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// NewBoundedCachedCompressors returns a new, with filled cache,  BoundedCachedCompressors.
 | 
			
		||||
func NewBoundedCachedCompressors(writersCapacity, readersCapacity int) *BoundedCachedCompressors {
 | 
			
		||||
	b := &BoundedCachedCompressors{
 | 
			
		||||
		gzipWriters:     make(chan *gzip.Writer, writersCapacity),
 | 
			
		||||
		gzipReaders:     make(chan *gzip.Reader, readersCapacity),
 | 
			
		||||
		zlibWriters:     make(chan *zlib.Writer, writersCapacity),
 | 
			
		||||
		writersCapacity: writersCapacity,
 | 
			
		||||
		readersCapacity: readersCapacity,
 | 
			
		||||
	}
 | 
			
		||||
	for ix := 0; ix < writersCapacity; ix++ {
 | 
			
		||||
		b.gzipWriters <- newGzipWriter()
 | 
			
		||||
		b.zlibWriters <- newZlibWriter()
 | 
			
		||||
	}
 | 
			
		||||
	for ix := 0; ix < readersCapacity; ix++ {
 | 
			
		||||
		b.gzipReaders <- newGzipReader()
 | 
			
		||||
	}
 | 
			
		||||
	return b
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// AcquireGzipWriter returns an resettable *gzip.Writer. Needs to be released.
 | 
			
		||||
func (b *BoundedCachedCompressors) AcquireGzipWriter() *gzip.Writer {
 | 
			
		||||
	var writer *gzip.Writer
 | 
			
		||||
	select {
 | 
			
		||||
	case writer, _ = <-b.gzipWriters:
 | 
			
		||||
	default:
 | 
			
		||||
		// return a new unmanaged one
 | 
			
		||||
		writer = newGzipWriter()
 | 
			
		||||
	}
 | 
			
		||||
	return writer
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ReleaseGzipWriter accepts a writer (does not have to be one that was cached)
 | 
			
		||||
// only when the cache has room for it. It will ignore it otherwise.
 | 
			
		||||
func (b *BoundedCachedCompressors) ReleaseGzipWriter(w *gzip.Writer) {
 | 
			
		||||
	// forget the unmanaged ones
 | 
			
		||||
	if len(b.gzipWriters) < b.writersCapacity {
 | 
			
		||||
		b.gzipWriters <- w
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// AcquireGzipReader returns a *gzip.Reader. Needs to be released.
 | 
			
		||||
func (b *BoundedCachedCompressors) AcquireGzipReader() *gzip.Reader {
 | 
			
		||||
	var reader *gzip.Reader
 | 
			
		||||
	select {
 | 
			
		||||
	case reader, _ = <-b.gzipReaders:
 | 
			
		||||
	default:
 | 
			
		||||
		// return a new unmanaged one
 | 
			
		||||
		reader = newGzipReader()
 | 
			
		||||
	}
 | 
			
		||||
	return reader
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ReleaseGzipReader accepts a reader (does not have to be one that was cached)
 | 
			
		||||
// only when the cache has room for it. It will ignore it otherwise.
 | 
			
		||||
func (b *BoundedCachedCompressors) ReleaseGzipReader(r *gzip.Reader) {
 | 
			
		||||
	// forget the unmanaged ones
 | 
			
		||||
	if len(b.gzipReaders) < b.readersCapacity {
 | 
			
		||||
		b.gzipReaders <- r
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// AcquireZlibWriter returns an resettable *zlib.Writer. Needs to be released.
 | 
			
		||||
func (b *BoundedCachedCompressors) AcquireZlibWriter() *zlib.Writer {
 | 
			
		||||
	var writer *zlib.Writer
 | 
			
		||||
	select {
 | 
			
		||||
	case writer, _ = <-b.zlibWriters:
 | 
			
		||||
	default:
 | 
			
		||||
		// return a new unmanaged one
 | 
			
		||||
		writer = newZlibWriter()
 | 
			
		||||
	}
 | 
			
		||||
	return writer
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ReleaseZlibWriter accepts a writer (does not have to be one that was cached)
 | 
			
		||||
// only when the cache has room for it. It will ignore it otherwise.
 | 
			
		||||
func (b *BoundedCachedCompressors) ReleaseZlibWriter(w *zlib.Writer) {
 | 
			
		||||
	// forget the unmanaged ones
 | 
			
		||||
	if len(b.zlibWriters) < b.writersCapacity {
 | 
			
		||||
		b.zlibWriters <- w
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										91
									
								
								vendor/github.com/emicklei/go-restful/v3/compressor_pools.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										91
									
								
								vendor/github.com/emicklei/go-restful/v3/compressor_pools.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,91 @@
 | 
			
		||||
package restful
 | 
			
		||||
 | 
			
		||||
// Copyright 2015 Ernest Micklei. All rights reserved.
 | 
			
		||||
// Use of this source code is governed by a license
 | 
			
		||||
// that can be found in the LICENSE file.
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"bytes"
 | 
			
		||||
	"compress/gzip"
 | 
			
		||||
	"compress/zlib"
 | 
			
		||||
	"sync"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// SyncPoolCompessors is a CompressorProvider that use the standard sync.Pool.
 | 
			
		||||
type SyncPoolCompessors struct {
 | 
			
		||||
	GzipWriterPool *sync.Pool
 | 
			
		||||
	GzipReaderPool *sync.Pool
 | 
			
		||||
	ZlibWriterPool *sync.Pool
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// NewSyncPoolCompessors returns a new ("empty") SyncPoolCompessors.
 | 
			
		||||
func NewSyncPoolCompessors() *SyncPoolCompessors {
 | 
			
		||||
	return &SyncPoolCompessors{
 | 
			
		||||
		GzipWriterPool: &sync.Pool{
 | 
			
		||||
			New: func() interface{} { return newGzipWriter() },
 | 
			
		||||
		},
 | 
			
		||||
		GzipReaderPool: &sync.Pool{
 | 
			
		||||
			New: func() interface{} { return newGzipReader() },
 | 
			
		||||
		},
 | 
			
		||||
		ZlibWriterPool: &sync.Pool{
 | 
			
		||||
			New: func() interface{} { return newZlibWriter() },
 | 
			
		||||
		},
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (s *SyncPoolCompessors) AcquireGzipWriter() *gzip.Writer {
 | 
			
		||||
	return s.GzipWriterPool.Get().(*gzip.Writer)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (s *SyncPoolCompessors) ReleaseGzipWriter(w *gzip.Writer) {
 | 
			
		||||
	s.GzipWriterPool.Put(w)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (s *SyncPoolCompessors) AcquireGzipReader() *gzip.Reader {
 | 
			
		||||
	return s.GzipReaderPool.Get().(*gzip.Reader)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (s *SyncPoolCompessors) ReleaseGzipReader(r *gzip.Reader) {
 | 
			
		||||
	s.GzipReaderPool.Put(r)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (s *SyncPoolCompessors) AcquireZlibWriter() *zlib.Writer {
 | 
			
		||||
	return s.ZlibWriterPool.Get().(*zlib.Writer)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (s *SyncPoolCompessors) ReleaseZlibWriter(w *zlib.Writer) {
 | 
			
		||||
	s.ZlibWriterPool.Put(w)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func newGzipWriter() *gzip.Writer {
 | 
			
		||||
	// create with an empty bytes writer; it will be replaced before using the gzipWriter
 | 
			
		||||
	writer, err := gzip.NewWriterLevel(new(bytes.Buffer), gzip.BestSpeed)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		panic(err.Error())
 | 
			
		||||
	}
 | 
			
		||||
	return writer
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func newGzipReader() *gzip.Reader {
 | 
			
		||||
	// create with an empty reader (but with GZIP header); it will be replaced before using the gzipReader
 | 
			
		||||
	// we can safely use currentCompressProvider because it is set on package initialization.
 | 
			
		||||
	w := currentCompressorProvider.AcquireGzipWriter()
 | 
			
		||||
	defer currentCompressorProvider.ReleaseGzipWriter(w)
 | 
			
		||||
	b := new(bytes.Buffer)
 | 
			
		||||
	w.Reset(b)
 | 
			
		||||
	w.Flush()
 | 
			
		||||
	w.Close()
 | 
			
		||||
	reader, err := gzip.NewReader(bytes.NewReader(b.Bytes()))
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		panic(err.Error())
 | 
			
		||||
	}
 | 
			
		||||
	return reader
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func newZlibWriter() *zlib.Writer {
 | 
			
		||||
	writer, err := zlib.NewWriterLevel(new(bytes.Buffer), gzip.BestSpeed)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		panic(err.Error())
 | 
			
		||||
	}
 | 
			
		||||
	return writer
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										54
									
								
								vendor/github.com/emicklei/go-restful/v3/compressors.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										54
									
								
								vendor/github.com/emicklei/go-restful/v3/compressors.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,54 @@
 | 
			
		||||
package restful
 | 
			
		||||
 | 
			
		||||
// Copyright 2015 Ernest Micklei. All rights reserved.
 | 
			
		||||
// Use of this source code is governed by a license
 | 
			
		||||
// that can be found in the LICENSE file.
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"compress/gzip"
 | 
			
		||||
	"compress/zlib"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// CompressorProvider describes a component that can provider compressors for the std methods.
 | 
			
		||||
type CompressorProvider interface {
 | 
			
		||||
	// Returns a *gzip.Writer which needs to be released later.
 | 
			
		||||
	// Before using it, call Reset().
 | 
			
		||||
	AcquireGzipWriter() *gzip.Writer
 | 
			
		||||
 | 
			
		||||
	// Releases an acquired *gzip.Writer.
 | 
			
		||||
	ReleaseGzipWriter(w *gzip.Writer)
 | 
			
		||||
 | 
			
		||||
	// Returns a *gzip.Reader which needs to be released later.
 | 
			
		||||
	AcquireGzipReader() *gzip.Reader
 | 
			
		||||
 | 
			
		||||
	// Releases an acquired *gzip.Reader.
 | 
			
		||||
	ReleaseGzipReader(w *gzip.Reader)
 | 
			
		||||
 | 
			
		||||
	// Returns a *zlib.Writer which needs to be released later.
 | 
			
		||||
	// Before using it, call Reset().
 | 
			
		||||
	AcquireZlibWriter() *zlib.Writer
 | 
			
		||||
 | 
			
		||||
	// Releases an acquired *zlib.Writer.
 | 
			
		||||
	ReleaseZlibWriter(w *zlib.Writer)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// DefaultCompressorProvider is the actual provider of compressors (zlib or gzip).
 | 
			
		||||
var currentCompressorProvider CompressorProvider
 | 
			
		||||
 | 
			
		||||
func init() {
 | 
			
		||||
	currentCompressorProvider = NewSyncPoolCompessors()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// CurrentCompressorProvider returns the current CompressorProvider.
 | 
			
		||||
// It is initialized using a SyncPoolCompessors.
 | 
			
		||||
func CurrentCompressorProvider() CompressorProvider {
 | 
			
		||||
	return currentCompressorProvider
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// SetCompressorProvider sets the actual provider of compressors (zlib or gzip).
 | 
			
		||||
func SetCompressorProvider(p CompressorProvider) {
 | 
			
		||||
	if p == nil {
 | 
			
		||||
		panic("cannot set compressor provider to nil")
 | 
			
		||||
	}
 | 
			
		||||
	currentCompressorProvider = p
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										30
									
								
								vendor/github.com/emicklei/go-restful/v3/constants.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										30
									
								
								vendor/github.com/emicklei/go-restful/v3/constants.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,30 @@
 | 
			
		||||
package restful
 | 
			
		||||
 | 
			
		||||
// Copyright 2013 Ernest Micklei. All rights reserved.
 | 
			
		||||
// Use of this source code is governed by a license
 | 
			
		||||
// that can be found in the LICENSE file.
 | 
			
		||||
 | 
			
		||||
const (
 | 
			
		||||
	MIME_XML   = "application/xml"          // Accept or Content-Type used in Consumes() and/or Produces()
 | 
			
		||||
	MIME_JSON  = "application/json"         // Accept or Content-Type used in Consumes() and/or Produces()
 | 
			
		||||
	MIME_OCTET = "application/octet-stream" // If Content-Type is not present in request, use the default
 | 
			
		||||
 | 
			
		||||
	HEADER_Allow                         = "Allow"
 | 
			
		||||
	HEADER_Accept                        = "Accept"
 | 
			
		||||
	HEADER_Origin                        = "Origin"
 | 
			
		||||
	HEADER_ContentType                   = "Content-Type"
 | 
			
		||||
	HEADER_LastModified                  = "Last-Modified"
 | 
			
		||||
	HEADER_AcceptEncoding                = "Accept-Encoding"
 | 
			
		||||
	HEADER_ContentEncoding               = "Content-Encoding"
 | 
			
		||||
	HEADER_AccessControlExposeHeaders    = "Access-Control-Expose-Headers"
 | 
			
		||||
	HEADER_AccessControlRequestMethod    = "Access-Control-Request-Method"
 | 
			
		||||
	HEADER_AccessControlRequestHeaders   = "Access-Control-Request-Headers"
 | 
			
		||||
	HEADER_AccessControlAllowMethods     = "Access-Control-Allow-Methods"
 | 
			
		||||
	HEADER_AccessControlAllowOrigin      = "Access-Control-Allow-Origin"
 | 
			
		||||
	HEADER_AccessControlAllowCredentials = "Access-Control-Allow-Credentials"
 | 
			
		||||
	HEADER_AccessControlAllowHeaders     = "Access-Control-Allow-Headers"
 | 
			
		||||
	HEADER_AccessControlMaxAge           = "Access-Control-Max-Age"
 | 
			
		||||
 | 
			
		||||
	ENCODING_GZIP    = "gzip"
 | 
			
		||||
	ENCODING_DEFLATE = "deflate"
 | 
			
		||||
)
 | 
			
		||||
							
								
								
									
										450
									
								
								vendor/github.com/emicklei/go-restful/v3/container.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										450
									
								
								vendor/github.com/emicklei/go-restful/v3/container.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,450 @@
 | 
			
		||||
package restful
 | 
			
		||||
 | 
			
		||||
// Copyright 2013 Ernest Micklei. All rights reserved.
 | 
			
		||||
// Use of this source code is governed by a license
 | 
			
		||||
// that can be found in the LICENSE file.
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"bytes"
 | 
			
		||||
	"errors"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"net/http"
 | 
			
		||||
	"os"
 | 
			
		||||
	"runtime"
 | 
			
		||||
	"strings"
 | 
			
		||||
	"sync"
 | 
			
		||||
 | 
			
		||||
	"github.com/emicklei/go-restful/v3/log"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// Container holds a collection of WebServices and a http.ServeMux to dispatch http requests.
 | 
			
		||||
// The requests are further dispatched to routes of WebServices using a RouteSelector
 | 
			
		||||
type Container struct {
 | 
			
		||||
	webServicesLock        sync.RWMutex
 | 
			
		||||
	webServices            []*WebService
 | 
			
		||||
	ServeMux               *http.ServeMux
 | 
			
		||||
	isRegisteredOnRoot     bool
 | 
			
		||||
	containerFilters       []FilterFunction
 | 
			
		||||
	doNotRecover           bool // default is true
 | 
			
		||||
	recoverHandleFunc      RecoverHandleFunction
 | 
			
		||||
	serviceErrorHandleFunc ServiceErrorHandleFunction
 | 
			
		||||
	router                 RouteSelector // default is a CurlyRouter (RouterJSR311 is a slower alternative)
 | 
			
		||||
	contentEncodingEnabled bool          // default is false
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// NewContainer creates a new Container using a new ServeMux and default router (CurlyRouter)
 | 
			
		||||
func NewContainer() *Container {
 | 
			
		||||
	return &Container{
 | 
			
		||||
		webServices:            []*WebService{},
 | 
			
		||||
		ServeMux:               http.NewServeMux(),
 | 
			
		||||
		isRegisteredOnRoot:     false,
 | 
			
		||||
		containerFilters:       []FilterFunction{},
 | 
			
		||||
		doNotRecover:           true,
 | 
			
		||||
		recoverHandleFunc:      logStackOnRecover,
 | 
			
		||||
		serviceErrorHandleFunc: writeServiceError,
 | 
			
		||||
		router:                 CurlyRouter{},
 | 
			
		||||
		contentEncodingEnabled: false}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// RecoverHandleFunction declares functions that can be used to handle a panic situation.
 | 
			
		||||
// The first argument is what recover() returns. The second must be used to communicate an error response.
 | 
			
		||||
type RecoverHandleFunction func(interface{}, http.ResponseWriter)
 | 
			
		||||
 | 
			
		||||
// RecoverHandler changes the default function (logStackOnRecover) to be called
 | 
			
		||||
// when a panic is detected. DoNotRecover must be have its default value (=false).
 | 
			
		||||
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 is the request that resulted in the error and
 | 
			
		||||
// the third must be used to communicate an error response.
 | 
			
		||||
type ServiceErrorHandleFunction func(ServiceError, *Request, *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 true.
 | 
			
		||||
func (c *Container) DoNotRecover(doNot bool) {
 | 
			
		||||
	c.doNotRecover = doNot
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Router changes the default Router (currently CurlyRouter)
 | 
			
		||||
func (c *Container) Router(aRouter RouteSelector) {
 | 
			
		||||
	c.router = aRouter
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// EnableContentEncoding (default=false) allows for GZIP or DEFLATE encoding of responses.
 | 
			
		||||
func (c *Container) EnableContentEncoding(enabled bool) {
 | 
			
		||||
	c.contentEncodingEnabled = enabled
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Add a WebService to the Container. It will detect duplicate root paths and exit in that case.
 | 
			
		||||
func (c *Container) Add(service *WebService) *Container {
 | 
			
		||||
	c.webServicesLock.Lock()
 | 
			
		||||
	defer c.webServicesLock.Unlock()
 | 
			
		||||
 | 
			
		||||
	// if rootPath was not set then lazy initialize it
 | 
			
		||||
	if len(service.rootPath) == 0 {
 | 
			
		||||
		service.Path("/")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// cannot have duplicate root paths
 | 
			
		||||
	for _, each := range c.webServices {
 | 
			
		||||
		if each.RootPath() == service.RootPath() {
 | 
			
		||||
			log.Printf("WebService with duplicate root path detected:['%v']", each)
 | 
			
		||||
			os.Exit(1)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// If not registered on root then add specific mapping
 | 
			
		||||
	if !c.isRegisteredOnRoot {
 | 
			
		||||
		c.isRegisteredOnRoot = c.addHandler(service, c.ServeMux)
 | 
			
		||||
	}
 | 
			
		||||
	c.webServices = append(c.webServices, service)
 | 
			
		||||
	return c
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// addHandler may set a new HandleFunc for the serveMux
 | 
			
		||||
// this function must run inside the critical region protected by the webServicesLock.
 | 
			
		||||
// returns true if the function was registered on root ("/")
 | 
			
		||||
func (c *Container) addHandler(service *WebService, serveMux *http.ServeMux) bool {
 | 
			
		||||
	pattern := fixedPrefixPath(service.RootPath())
 | 
			
		||||
	// check if root path registration is needed
 | 
			
		||||
	if "/" == pattern || "" == pattern {
 | 
			
		||||
		serveMux.HandleFunc("/", c.dispatch)
 | 
			
		||||
		return true
 | 
			
		||||
	}
 | 
			
		||||
	// detect if registration already exists
 | 
			
		||||
	alreadyMapped := false
 | 
			
		||||
	for _, each := range c.webServices {
 | 
			
		||||
		if each.RootPath() == service.RootPath() {
 | 
			
		||||
			alreadyMapped = true
 | 
			
		||||
			break
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	if !alreadyMapped {
 | 
			
		||||
		serveMux.HandleFunc(pattern, c.dispatch)
 | 
			
		||||
		if !strings.HasSuffix(pattern, "/") {
 | 
			
		||||
			serveMux.HandleFunc(pattern+"/", c.dispatch)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return false
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (c *Container) Remove(ws *WebService) error {
 | 
			
		||||
	if c.ServeMux == http.DefaultServeMux {
 | 
			
		||||
		errMsg := fmt.Sprintf("cannot remove a WebService from a Container using the DefaultServeMux: ['%v']", ws)
 | 
			
		||||
		log.Print(errMsg)
 | 
			
		||||
		return errors.New(errMsg)
 | 
			
		||||
	}
 | 
			
		||||
	c.webServicesLock.Lock()
 | 
			
		||||
	defer c.webServicesLock.Unlock()
 | 
			
		||||
	// build a new ServeMux and re-register all WebServices
 | 
			
		||||
	newServeMux := http.NewServeMux()
 | 
			
		||||
	newServices := []*WebService{}
 | 
			
		||||
	newIsRegisteredOnRoot := false
 | 
			
		||||
	for _, each := range c.webServices {
 | 
			
		||||
		if each.rootPath != ws.rootPath {
 | 
			
		||||
			// If not registered on root then add specific mapping
 | 
			
		||||
			if !newIsRegisteredOnRoot {
 | 
			
		||||
				newIsRegisteredOnRoot = c.addHandler(each, newServeMux)
 | 
			
		||||
			}
 | 
			
		||||
			newServices = append(newServices, each)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	c.webServices, c.ServeMux, c.isRegisteredOnRoot = newServices, newServeMux, newIsRegisteredOnRoot
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// logStackOnRecover is the default RecoverHandleFunction and is called
 | 
			
		||||
// when DoNotRecover is false and the recoverHandleFunc is not set for the container.
 | 
			
		||||
// Default implementation logs the stacktrace and writes the stacktrace on the response.
 | 
			
		||||
// This may be a security issue as it exposes sourcecode information.
 | 
			
		||||
func logStackOnRecover(panicReason interface{}, httpWriter http.ResponseWriter) {
 | 
			
		||||
	var buffer bytes.Buffer
 | 
			
		||||
	buffer.WriteString(fmt.Sprintf("recover from panic situation: - %v\r\n", panicReason))
 | 
			
		||||
	for i := 2; ; i += 1 {
 | 
			
		||||
		_, file, line, ok := runtime.Caller(i)
 | 
			
		||||
		if !ok {
 | 
			
		||||
			break
 | 
			
		||||
		}
 | 
			
		||||
		buffer.WriteString(fmt.Sprintf("    %s:%d\r\n", file, line))
 | 
			
		||||
	}
 | 
			
		||||
	log.Print(buffer.String())
 | 
			
		||||
	httpWriter.WriteHeader(http.StatusInternalServerError)
 | 
			
		||||
	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, req *Request, resp *Response) {
 | 
			
		||||
	for header, values := range err.Header {
 | 
			
		||||
		for _, value := range values {
 | 
			
		||||
			resp.Header().Add(header, value)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	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) {
 | 
			
		||||
	if httpWriter == nil {
 | 
			
		||||
		panic("httpWriter cannot be nil")
 | 
			
		||||
	}
 | 
			
		||||
	if httpRequest == nil {
 | 
			
		||||
		panic("httpRequest cannot be nil")
 | 
			
		||||
	}
 | 
			
		||||
	c.dispatch(httpWriter, httpRequest)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Dispatch the incoming Http Request to a matching WebService.
 | 
			
		||||
func (c *Container) dispatch(httpWriter http.ResponseWriter, httpRequest *http.Request) {
 | 
			
		||||
	// so we can assign a compressing one later
 | 
			
		||||
	writer := httpWriter
 | 
			
		||||
 | 
			
		||||
	// CompressingResponseWriter should be closed after all operations are done
 | 
			
		||||
	defer func() {
 | 
			
		||||
		if compressWriter, ok := writer.(*CompressingResponseWriter); ok {
 | 
			
		||||
			compressWriter.Close()
 | 
			
		||||
		}
 | 
			
		||||
	}()
 | 
			
		||||
 | 
			
		||||
	// Instal panic recovery unless told otherwise
 | 
			
		||||
	if !c.doNotRecover { // catch all for 500 response
 | 
			
		||||
		defer func() {
 | 
			
		||||
			if r := recover(); r != nil {
 | 
			
		||||
				c.recoverHandleFunc(r, writer)
 | 
			
		||||
				return
 | 
			
		||||
			}
 | 
			
		||||
		}()
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Find best match Route ; err is non nil if no match was found
 | 
			
		||||
	var webService *WebService
 | 
			
		||||
	var route *Route
 | 
			
		||||
	var err error
 | 
			
		||||
	func() {
 | 
			
		||||
		c.webServicesLock.RLock()
 | 
			
		||||
		defer c.webServicesLock.RUnlock()
 | 
			
		||||
		webService, route, err = c.router.SelectRoute(
 | 
			
		||||
			c.webServices,
 | 
			
		||||
			httpRequest)
 | 
			
		||||
	}()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		// a non-200 response (may be compressed) has already been written
 | 
			
		||||
		// run container filters anyway ; they should not touch the response...
 | 
			
		||||
		chain := FilterChain{Filters: c.containerFilters, Target: func(req *Request, resp *Response) {
 | 
			
		||||
			switch err.(type) {
 | 
			
		||||
			case ServiceError:
 | 
			
		||||
				ser := err.(ServiceError)
 | 
			
		||||
				c.serviceErrorHandleFunc(ser, req, resp)
 | 
			
		||||
			}
 | 
			
		||||
			// TODO
 | 
			
		||||
		}}
 | 
			
		||||
		chain.ProcessFilter(NewRequest(httpRequest), NewResponse(writer))
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Unless httpWriter is already an CompressingResponseWriter see if we need to install one
 | 
			
		||||
	if _, isCompressing := httpWriter.(*CompressingResponseWriter); !isCompressing {
 | 
			
		||||
		// Detect if compression is needed
 | 
			
		||||
		// assume without compression, test for override
 | 
			
		||||
		contentEncodingEnabled := c.contentEncodingEnabled
 | 
			
		||||
		if route != nil && route.contentEncodingEnabled != nil {
 | 
			
		||||
			contentEncodingEnabled = *route.contentEncodingEnabled
 | 
			
		||||
		}
 | 
			
		||||
		if contentEncodingEnabled {
 | 
			
		||||
			doCompress, encoding := wantsCompressedResponse(httpRequest, httpWriter)
 | 
			
		||||
			if doCompress {
 | 
			
		||||
				var err error
 | 
			
		||||
				writer, err = NewCompressingResponseWriter(httpWriter, encoding)
 | 
			
		||||
				if err != nil {
 | 
			
		||||
					log.Print("unable to install compressor: ", err)
 | 
			
		||||
					httpWriter.WriteHeader(http.StatusInternalServerError)
 | 
			
		||||
					return
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	pathProcessor, routerProcessesPath := c.router.(PathProcessor)
 | 
			
		||||
	if !routerProcessesPath {
 | 
			
		||||
		pathProcessor = defaultPathProcessor{}
 | 
			
		||||
	}
 | 
			
		||||
	pathParams := pathProcessor.ExtractParameters(route, webService, httpRequest.URL.Path)
 | 
			
		||||
	wrappedRequest, wrappedResponse := route.wrapRequestResponse(writer, httpRequest, pathParams)
 | 
			
		||||
	// pass through filters (if any)
 | 
			
		||||
	if size := len(c.containerFilters) + len(webService.filters) + len(route.Filters); size > 0 {
 | 
			
		||||
		// compose filter chain
 | 
			
		||||
		allFilters := make([]FilterFunction, 0, size)
 | 
			
		||||
		allFilters = append(allFilters, c.containerFilters...)
 | 
			
		||||
		allFilters = append(allFilters, webService.filters...)
 | 
			
		||||
		allFilters = append(allFilters, route.Filters...)
 | 
			
		||||
		chain := FilterChain{
 | 
			
		||||
			Filters:       allFilters,
 | 
			
		||||
			Target:        route.Function,
 | 
			
		||||
			ParameterDocs: route.ParameterDocs,
 | 
			
		||||
			Operation:     route.Operation,
 | 
			
		||||
		}
 | 
			
		||||
		chain.ProcessFilter(wrappedRequest, wrappedResponse)
 | 
			
		||||
	} else {
 | 
			
		||||
		// no filters, handle request by route
 | 
			
		||||
		route.Function(wrappedRequest, wrappedResponse)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// fixedPrefixPath returns the fixed part of the partspec ; it may include template vars {}
 | 
			
		||||
func fixedPrefixPath(pathspec string) string {
 | 
			
		||||
	varBegin := strings.Index(pathspec, "{")
 | 
			
		||||
	if -1 == varBegin {
 | 
			
		||||
		return pathspec
 | 
			
		||||
	}
 | 
			
		||||
	return pathspec[:varBegin]
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ServeHTTP implements net/http.Handler therefore a Container can be a Handler in a http.Server
 | 
			
		||||
func (c *Container) ServeHTTP(httpWriter http.ResponseWriter, httpRequest *http.Request) {
 | 
			
		||||
	// Skip, if content encoding is disabled
 | 
			
		||||
	if !c.contentEncodingEnabled {
 | 
			
		||||
		c.ServeMux.ServeHTTP(httpWriter, httpRequest)
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	// content encoding is enabled
 | 
			
		||||
 | 
			
		||||
	// Skip, if httpWriter is already an CompressingResponseWriter
 | 
			
		||||
	if _, ok := httpWriter.(*CompressingResponseWriter); ok {
 | 
			
		||||
		c.ServeMux.ServeHTTP(httpWriter, httpRequest)
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	writer := httpWriter
 | 
			
		||||
	// CompressingResponseWriter should be closed after all operations are done
 | 
			
		||||
	defer func() {
 | 
			
		||||
		if compressWriter, ok := writer.(*CompressingResponseWriter); ok {
 | 
			
		||||
			compressWriter.Close()
 | 
			
		||||
		}
 | 
			
		||||
	}()
 | 
			
		||||
 | 
			
		||||
	doCompress, encoding := wantsCompressedResponse(httpRequest, httpWriter)
 | 
			
		||||
	if doCompress {
 | 
			
		||||
		var err error
 | 
			
		||||
		writer, err = NewCompressingResponseWriter(httpWriter, encoding)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			log.Print("unable to install compressor: ", err)
 | 
			
		||||
			httpWriter.WriteHeader(http.StatusInternalServerError)
 | 
			
		||||
			return
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	c.ServeMux.ServeHTTP(writer, httpRequest)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Handle registers the handler for the given pattern. If a handler already exists for pattern, Handle panics.
 | 
			
		||||
func (c *Container) Handle(pattern string, handler http.Handler) {
 | 
			
		||||
	c.ServeMux.Handle(pattern, http.HandlerFunc(func(httpWriter http.ResponseWriter, httpRequest *http.Request) {
 | 
			
		||||
		// Skip, if httpWriter is already an CompressingResponseWriter
 | 
			
		||||
		if _, ok := httpWriter.(*CompressingResponseWriter); ok {
 | 
			
		||||
			handler.ServeHTTP(httpWriter, httpRequest)
 | 
			
		||||
			return
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		writer := httpWriter
 | 
			
		||||
 | 
			
		||||
		// CompressingResponseWriter should be closed after all operations are done
 | 
			
		||||
		defer func() {
 | 
			
		||||
			if compressWriter, ok := writer.(*CompressingResponseWriter); ok {
 | 
			
		||||
				compressWriter.Close()
 | 
			
		||||
			}
 | 
			
		||||
		}()
 | 
			
		||||
 | 
			
		||||
		if c.contentEncodingEnabled {
 | 
			
		||||
			doCompress, encoding := wantsCompressedResponse(httpRequest, httpWriter)
 | 
			
		||||
			if doCompress {
 | 
			
		||||
				var err error
 | 
			
		||||
				writer, err = NewCompressingResponseWriter(httpWriter, encoding)
 | 
			
		||||
				if err != nil {
 | 
			
		||||
					log.Print("unable to install compressor: ", err)
 | 
			
		||||
					httpWriter.WriteHeader(http.StatusInternalServerError)
 | 
			
		||||
					return
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		handler.ServeHTTP(writer, httpRequest)
 | 
			
		||||
	}))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 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(resp, req.Request)
 | 
			
		||||
		}}
 | 
			
		||||
		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) {
 | 
			
		||||
	c.containerFilters = append(c.containerFilters, filter)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// RegisteredWebServices returns the collections of added WebServices
 | 
			
		||||
func (c *Container) RegisteredWebServices() []*WebService {
 | 
			
		||||
	c.webServicesLock.RLock()
 | 
			
		||||
	defer c.webServicesLock.RUnlock()
 | 
			
		||||
	result := make([]*WebService, len(c.webServices))
 | 
			
		||||
	for ix := range c.webServices {
 | 
			
		||||
		result[ix] = c.webServices[ix]
 | 
			
		||||
	}
 | 
			
		||||
	return result
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// computeAllowedMethods returns a list of HTTP methods that are valid for a Request
 | 
			
		||||
func (c *Container) computeAllowedMethods(req *Request) []string {
 | 
			
		||||
	// Go through all RegisteredWebServices() and all its Routes to collect the options
 | 
			
		||||
	methods := []string{}
 | 
			
		||||
	requestPath := req.Request.URL.Path
 | 
			
		||||
	for _, ws := range c.RegisteredWebServices() {
 | 
			
		||||
		matches := ws.pathExpr.Matcher.FindStringSubmatch(requestPath)
 | 
			
		||||
		if matches != nil {
 | 
			
		||||
			finalMatch := matches[len(matches)-1]
 | 
			
		||||
			for _, rt := range ws.Routes() {
 | 
			
		||||
				matches := rt.pathExpr.Matcher.FindStringSubmatch(finalMatch)
 | 
			
		||||
				if matches != nil {
 | 
			
		||||
					lastMatch := matches[len(matches)-1]
 | 
			
		||||
					if lastMatch == "" || lastMatch == "/" { // do not include if value is neither empty nor ‘/’.
 | 
			
		||||
						methods = append(methods, rt.Method)
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	// methods = append(methods, "OPTIONS")  not sure about this
 | 
			
		||||
	return methods
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// newBasicRequestResponse creates a pair of Request,Response from its http versions.
 | 
			
		||||
// It is basic because no parameter or (produces) content-type information is given.
 | 
			
		||||
func newBasicRequestResponse(httpWriter http.ResponseWriter, httpRequest *http.Request) (*Request, *Response) {
 | 
			
		||||
	resp := NewResponse(httpWriter)
 | 
			
		||||
	resp.requestAccept = httpRequest.Header.Get(HEADER_Accept)
 | 
			
		||||
	return NewRequest(httpRequest), resp
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										193
									
								
								vendor/github.com/emicklei/go-restful/v3/cors_filter.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										193
									
								
								vendor/github.com/emicklei/go-restful/v3/cors_filter.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,193 @@
 | 
			
		||||
package restful
 | 
			
		||||
 | 
			
		||||
// Copyright 2013 Ernest Micklei. All rights reserved.
 | 
			
		||||
// Use of this source code is governed by a license
 | 
			
		||||
// that can be found in the LICENSE file.
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"regexp"
 | 
			
		||||
	"strconv"
 | 
			
		||||
	"strings"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// CrossOriginResourceSharing is used to create a Container Filter that implements CORS.
 | 
			
		||||
// Cross-origin resource sharing (CORS) is a mechanism that allows JavaScript on a web page
 | 
			
		||||
// to make XMLHttpRequests to another domain, not the domain the JavaScript originated from.
 | 
			
		||||
//
 | 
			
		||||
// http://en.wikipedia.org/wiki/Cross-origin_resource_sharing
 | 
			
		||||
// http://enable-cors.org/server.html
 | 
			
		||||
// http://www.html5rocks.com/en/tutorials/cors/#toc-handling-a-not-so-simple-request
 | 
			
		||||
type CrossOriginResourceSharing struct {
 | 
			
		||||
	ExposeHeaders []string // list of Header names
 | 
			
		||||
 | 
			
		||||
	// AllowedHeaders is alist of Header names. Checking is case-insensitive.
 | 
			
		||||
	// The list may contain the special wildcard string ".*" ; all is allowed
 | 
			
		||||
	AllowedHeaders []string
 | 
			
		||||
 | 
			
		||||
	// AllowedDomains is a list of allowed values for Http Origin.
 | 
			
		||||
	// The list may contain the special wildcard string ".*" ; all is allowed
 | 
			
		||||
	// If empty all are allowed.
 | 
			
		||||
	AllowedDomains []string
 | 
			
		||||
 | 
			
		||||
	// AllowedDomainFunc is optional and is a function that will do the check
 | 
			
		||||
	// when the origin is not part of the AllowedDomains and it does not contain the wildcard ".*".
 | 
			
		||||
	AllowedDomainFunc func(origin string) bool
 | 
			
		||||
 | 
			
		||||
	// AllowedMethods is either empty or has a list of http methods names. Checking is case-insensitive.
 | 
			
		||||
	AllowedMethods []string
 | 
			
		||||
	MaxAge         int // number of seconds before requiring new Options request
 | 
			
		||||
	CookiesAllowed bool
 | 
			
		||||
	Container      *Container
 | 
			
		||||
 | 
			
		||||
	allowedOriginPatterns []*regexp.Regexp // internal field for origin regexp check.
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Filter is a filter function that implements the CORS flow as documented on http://enable-cors.org/server.html
 | 
			
		||||
// and http://www.html5rocks.com/static/images/cors_server_flowchart.png
 | 
			
		||||
func (c CrossOriginResourceSharing) Filter(req *Request, resp *Response, chain *FilterChain) {
 | 
			
		||||
	origin := req.Request.Header.Get(HEADER_Origin)
 | 
			
		||||
	if len(origin) == 0 {
 | 
			
		||||
		if trace {
 | 
			
		||||
			traceLogger.Print("no Http header Origin set")
 | 
			
		||||
		}
 | 
			
		||||
		chain.ProcessFilter(req, resp)
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	if !c.isOriginAllowed(origin) { // check whether this origin is allowed
 | 
			
		||||
		if trace {
 | 
			
		||||
			traceLogger.Printf("HTTP Origin:%s is not part of %v, neither matches any part of %v", origin, c.AllowedDomains, c.allowedOriginPatterns)
 | 
			
		||||
		}
 | 
			
		||||
		chain.ProcessFilter(req, resp)
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	if req.Request.Method != "OPTIONS" {
 | 
			
		||||
		c.doActualRequest(req, resp)
 | 
			
		||||
		chain.ProcessFilter(req, resp)
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	if acrm := req.Request.Header.Get(HEADER_AccessControlRequestMethod); acrm != "" {
 | 
			
		||||
		c.doPreflightRequest(req, resp)
 | 
			
		||||
	} else {
 | 
			
		||||
		c.doActualRequest(req, resp)
 | 
			
		||||
		chain.ProcessFilter(req, resp)
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (c CrossOriginResourceSharing) doActualRequest(req *Request, resp *Response) {
 | 
			
		||||
	c.setOptionsHeaders(req, resp)
 | 
			
		||||
	// continue processing the response
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (c *CrossOriginResourceSharing) doPreflightRequest(req *Request, resp *Response) {
 | 
			
		||||
	if len(c.AllowedMethods) == 0 {
 | 
			
		||||
		if c.Container == nil {
 | 
			
		||||
			c.AllowedMethods = DefaultContainer.computeAllowedMethods(req)
 | 
			
		||||
		} else {
 | 
			
		||||
			c.AllowedMethods = c.Container.computeAllowedMethods(req)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	acrm := req.Request.Header.Get(HEADER_AccessControlRequestMethod)
 | 
			
		||||
	if !c.isValidAccessControlRequestMethod(acrm, c.AllowedMethods) {
 | 
			
		||||
		if trace {
 | 
			
		||||
			traceLogger.Printf("Http header %s:%s is not in %v",
 | 
			
		||||
				HEADER_AccessControlRequestMethod,
 | 
			
		||||
				acrm,
 | 
			
		||||
				c.AllowedMethods)
 | 
			
		||||
		}
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	acrhs := req.Request.Header.Get(HEADER_AccessControlRequestHeaders)
 | 
			
		||||
	if len(acrhs) > 0 {
 | 
			
		||||
		for _, each := range strings.Split(acrhs, ",") {
 | 
			
		||||
			if !c.isValidAccessControlRequestHeader(strings.Trim(each, " ")) {
 | 
			
		||||
				if trace {
 | 
			
		||||
					traceLogger.Printf("Http header %s:%s is not in %v",
 | 
			
		||||
						HEADER_AccessControlRequestHeaders,
 | 
			
		||||
						acrhs,
 | 
			
		||||
						c.AllowedHeaders)
 | 
			
		||||
				}
 | 
			
		||||
				return
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	resp.AddHeader(HEADER_AccessControlAllowMethods, strings.Join(c.AllowedMethods, ","))
 | 
			
		||||
	resp.AddHeader(HEADER_AccessControlAllowHeaders, acrhs)
 | 
			
		||||
	c.setOptionsHeaders(req, resp)
 | 
			
		||||
 | 
			
		||||
	// return http 200 response, no body
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (c CrossOriginResourceSharing) setOptionsHeaders(req *Request, resp *Response) {
 | 
			
		||||
	c.checkAndSetExposeHeaders(resp)
 | 
			
		||||
	c.setAllowOriginHeader(req, resp)
 | 
			
		||||
	c.checkAndSetAllowCredentials(resp)
 | 
			
		||||
	if c.MaxAge > 0 {
 | 
			
		||||
		resp.AddHeader(HEADER_AccessControlMaxAge, strconv.Itoa(c.MaxAge))
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (c CrossOriginResourceSharing) isOriginAllowed(origin string) bool {
 | 
			
		||||
	if len(origin) == 0 {
 | 
			
		||||
		return false
 | 
			
		||||
	}
 | 
			
		||||
	lowerOrigin := strings.ToLower(origin)
 | 
			
		||||
	if len(c.AllowedDomains) == 0 {
 | 
			
		||||
		if c.AllowedDomainFunc != nil {
 | 
			
		||||
			return c.AllowedDomainFunc(lowerOrigin)
 | 
			
		||||
		}
 | 
			
		||||
		return true
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// exact match on each allowed domain
 | 
			
		||||
	for _, domain := range c.AllowedDomains {
 | 
			
		||||
		if domain == ".*" || strings.ToLower(domain) == lowerOrigin {
 | 
			
		||||
			return true
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	if c.AllowedDomainFunc != nil {
 | 
			
		||||
		return c.AllowedDomainFunc(origin)
 | 
			
		||||
	}
 | 
			
		||||
	return false
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (c CrossOriginResourceSharing) setAllowOriginHeader(req *Request, resp *Response) {
 | 
			
		||||
	origin := req.Request.Header.Get(HEADER_Origin)
 | 
			
		||||
	if c.isOriginAllowed(origin) {
 | 
			
		||||
		resp.AddHeader(HEADER_AccessControlAllowOrigin, origin)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (c CrossOriginResourceSharing) checkAndSetExposeHeaders(resp *Response) {
 | 
			
		||||
	if len(c.ExposeHeaders) > 0 {
 | 
			
		||||
		resp.AddHeader(HEADER_AccessControlExposeHeaders, strings.Join(c.ExposeHeaders, ","))
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (c CrossOriginResourceSharing) checkAndSetAllowCredentials(resp *Response) {
 | 
			
		||||
	if c.CookiesAllowed {
 | 
			
		||||
		resp.AddHeader(HEADER_AccessControlAllowCredentials, "true")
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (c CrossOriginResourceSharing) isValidAccessControlRequestMethod(method string, allowedMethods []string) bool {
 | 
			
		||||
	for _, each := range allowedMethods {
 | 
			
		||||
		if each == method {
 | 
			
		||||
			return true
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return false
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (c CrossOriginResourceSharing) isValidAccessControlRequestHeader(header string) bool {
 | 
			
		||||
	for _, each := range c.AllowedHeaders {
 | 
			
		||||
		if strings.ToLower(each) == strings.ToLower(header) {
 | 
			
		||||
			return true
 | 
			
		||||
		}
 | 
			
		||||
		if each == "*" {
 | 
			
		||||
			return true
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return false
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										2
									
								
								vendor/github.com/emicklei/go-restful/v3/coverage.sh
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								vendor/github.com/emicklei/go-restful/v3/coverage.sh
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,2 @@
 | 
			
		||||
go test -coverprofile=coverage.out
 | 
			
		||||
go tool cover -html=coverage.out
 | 
			
		||||
							
								
								
									
										173
									
								
								vendor/github.com/emicklei/go-restful/v3/curly.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										173
									
								
								vendor/github.com/emicklei/go-restful/v3/curly.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,173 @@
 | 
			
		||||
package restful
 | 
			
		||||
 | 
			
		||||
// Copyright 2013 Ernest Micklei. All rights reserved.
 | 
			
		||||
// Use of this source code is governed by a license
 | 
			
		||||
// that can be found in the LICENSE file.
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"net/http"
 | 
			
		||||
	"regexp"
 | 
			
		||||
	"sort"
 | 
			
		||||
	"strings"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// CurlyRouter expects Routes with paths that contain zero or more parameters in curly brackets.
 | 
			
		||||
type CurlyRouter struct{}
 | 
			
		||||
 | 
			
		||||
// SelectRoute is part of the Router interface and returns the best match
 | 
			
		||||
// for the WebService and its Route for the given Request.
 | 
			
		||||
func (c CurlyRouter) SelectRoute(
 | 
			
		||||
	webServices []*WebService,
 | 
			
		||||
	httpRequest *http.Request) (selectedService *WebService, selected *Route, err error) {
 | 
			
		||||
 | 
			
		||||
	requestTokens := tokenizePath(httpRequest.URL.Path)
 | 
			
		||||
 | 
			
		||||
	detectedService := c.detectWebService(requestTokens, webServices)
 | 
			
		||||
	if detectedService == nil {
 | 
			
		||||
		if trace {
 | 
			
		||||
			traceLogger.Printf("no WebService was found to match URL path:%s\n", httpRequest.URL.Path)
 | 
			
		||||
		}
 | 
			
		||||
		return nil, nil, NewError(http.StatusNotFound, "404: Page Not Found")
 | 
			
		||||
	}
 | 
			
		||||
	candidateRoutes := c.selectRoutes(detectedService, requestTokens)
 | 
			
		||||
	if len(candidateRoutes) == 0 {
 | 
			
		||||
		if trace {
 | 
			
		||||
			traceLogger.Printf("no Route in WebService with path %s was found to match URL path:%s\n", detectedService.rootPath, httpRequest.URL.Path)
 | 
			
		||||
		}
 | 
			
		||||
		return detectedService, nil, NewError(http.StatusNotFound, "404: Page Not Found")
 | 
			
		||||
	}
 | 
			
		||||
	selectedRoute, err := c.detectRoute(candidateRoutes, httpRequest)
 | 
			
		||||
	if selectedRoute == nil {
 | 
			
		||||
		return detectedService, nil, err
 | 
			
		||||
	}
 | 
			
		||||
	return detectedService, selectedRoute, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// selectRoutes return a collection of Route from a WebService that matches the path tokens from the request.
 | 
			
		||||
func (c CurlyRouter) selectRoutes(ws *WebService, requestTokens []string) sortableCurlyRoutes {
 | 
			
		||||
	candidates := make(sortableCurlyRoutes, 0, 8)
 | 
			
		||||
	for _, each := range ws.routes {
 | 
			
		||||
		matches, paramCount, staticCount := c.matchesRouteByPathTokens(each.pathParts, requestTokens, each.hasCustomVerb)
 | 
			
		||||
		if matches {
 | 
			
		||||
			candidates.add(curlyRoute{each, paramCount, staticCount}) // TODO make sure Routes() return pointers?
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	sort.Sort(candidates)
 | 
			
		||||
	return candidates
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// matchesRouteByPathTokens computes whether it matches, howmany parameters do match and what the number of static path elements are.
 | 
			
		||||
func (c CurlyRouter) matchesRouteByPathTokens(routeTokens, requestTokens []string, routeHasCustomVerb bool) (matches bool, paramCount int, staticCount int) {
 | 
			
		||||
	if len(routeTokens) < len(requestTokens) {
 | 
			
		||||
		// proceed in matching only if last routeToken is wildcard
 | 
			
		||||
		count := len(routeTokens)
 | 
			
		||||
		if count == 0 || !strings.HasSuffix(routeTokens[count-1], "*}") {
 | 
			
		||||
			return false, 0, 0
 | 
			
		||||
		}
 | 
			
		||||
		// proceed
 | 
			
		||||
	}
 | 
			
		||||
	for i, routeToken := range routeTokens {
 | 
			
		||||
		if i == len(requestTokens) {
 | 
			
		||||
			// reached end of request path
 | 
			
		||||
			return false, 0, 0
 | 
			
		||||
		}
 | 
			
		||||
		requestToken := requestTokens[i]
 | 
			
		||||
		if routeHasCustomVerb && hasCustomVerb(routeToken){
 | 
			
		||||
			if !isMatchCustomVerb(routeToken, requestToken) {
 | 
			
		||||
				return false, 0, 0
 | 
			
		||||
			}
 | 
			
		||||
			staticCount++
 | 
			
		||||
			requestToken = removeCustomVerb(requestToken)
 | 
			
		||||
			routeToken = removeCustomVerb(routeToken)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if strings.HasPrefix(routeToken, "{") {
 | 
			
		||||
			paramCount++
 | 
			
		||||
			if colon := strings.Index(routeToken, ":"); colon != -1 {
 | 
			
		||||
				// match by regex
 | 
			
		||||
				matchesToken, matchesRemainder := c.regularMatchesPathToken(routeToken, colon, requestToken)
 | 
			
		||||
				if !matchesToken {
 | 
			
		||||
					return false, 0, 0
 | 
			
		||||
				}
 | 
			
		||||
				if matchesRemainder {
 | 
			
		||||
					break
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		} else { // no { prefix
 | 
			
		||||
			if requestToken != routeToken {
 | 
			
		||||
				return false, 0, 0
 | 
			
		||||
			}
 | 
			
		||||
			staticCount++
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return true, paramCount, staticCount
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// regularMatchesPathToken tests whether the regular expression part of routeToken matches the requestToken or all remaining tokens
 | 
			
		||||
// format routeToken is {someVar:someExpression}, e.g. {zipcode:[\d][\d][\d][\d][A-Z][A-Z]}
 | 
			
		||||
func (c CurlyRouter) regularMatchesPathToken(routeToken string, colon int, requestToken string) (matchesToken bool, matchesRemainder bool) {
 | 
			
		||||
	regPart := routeToken[colon+1 : len(routeToken)-1]
 | 
			
		||||
	if regPart == "*" {
 | 
			
		||||
		if trace {
 | 
			
		||||
			traceLogger.Printf("wildcard parameter detected in route token %s that matches %s\n", routeToken, requestToken)
 | 
			
		||||
		}
 | 
			
		||||
		return true, true
 | 
			
		||||
	}
 | 
			
		||||
	matched, err := regexp.MatchString(regPart, requestToken)
 | 
			
		||||
	return (matched && err == nil), false
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
var jsr311Router = RouterJSR311{}
 | 
			
		||||
 | 
			
		||||
// detectRoute selectes from a list of Route the first match by inspecting both the Accept and Content-Type
 | 
			
		||||
// headers of the Request. See also RouterJSR311 in jsr311.go
 | 
			
		||||
func (c CurlyRouter) detectRoute(candidateRoutes sortableCurlyRoutes, httpRequest *http.Request) (*Route, error) {
 | 
			
		||||
	// tracing is done inside detectRoute
 | 
			
		||||
	return jsr311Router.detectRoute(candidateRoutes.routes(), httpRequest)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// detectWebService returns the best matching webService given the list of path tokens.
 | 
			
		||||
// see also computeWebserviceScore
 | 
			
		||||
func (c CurlyRouter) detectWebService(requestTokens []string, webServices []*WebService) *WebService {
 | 
			
		||||
	var best *WebService
 | 
			
		||||
	score := -1
 | 
			
		||||
	for _, each := range webServices {
 | 
			
		||||
		matches, eachScore := c.computeWebserviceScore(requestTokens, each.pathExpr.tokens)
 | 
			
		||||
		if matches && (eachScore > score) {
 | 
			
		||||
			best = each
 | 
			
		||||
			score = eachScore
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return best
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// computeWebserviceScore returns whether tokens match and
 | 
			
		||||
// the weighted score of the longest matching consecutive tokens from the beginning.
 | 
			
		||||
func (c CurlyRouter) computeWebserviceScore(requestTokens []string, tokens []string) (bool, int) {
 | 
			
		||||
	if len(tokens) > len(requestTokens) {
 | 
			
		||||
		return false, 0
 | 
			
		||||
	}
 | 
			
		||||
	score := 0
 | 
			
		||||
	for i := 0; i < len(tokens); i++ {
 | 
			
		||||
		each := requestTokens[i]
 | 
			
		||||
		other := tokens[i]
 | 
			
		||||
		if len(each) == 0 && len(other) == 0 {
 | 
			
		||||
			score++
 | 
			
		||||
			continue
 | 
			
		||||
		}
 | 
			
		||||
		if len(other) > 0 && strings.HasPrefix(other, "{") {
 | 
			
		||||
			// no empty match
 | 
			
		||||
			if len(each) == 0 {
 | 
			
		||||
				return false, score
 | 
			
		||||
			}
 | 
			
		||||
			score += 1
 | 
			
		||||
		} else {
 | 
			
		||||
			// not a parameter
 | 
			
		||||
			if each != other {
 | 
			
		||||
				return false, score
 | 
			
		||||
			}
 | 
			
		||||
			score += (len(tokens) - i) * 10 //fuzzy
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return true, score
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										54
									
								
								vendor/github.com/emicklei/go-restful/v3/curly_route.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										54
									
								
								vendor/github.com/emicklei/go-restful/v3/curly_route.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,54 @@
 | 
			
		||||
package restful
 | 
			
		||||
 | 
			
		||||
// Copyright 2013 Ernest Micklei. All rights reserved.
 | 
			
		||||
// Use of this source code is governed by a license
 | 
			
		||||
// that can be found in the LICENSE file.
 | 
			
		||||
 | 
			
		||||
// curlyRoute exits for sorting Routes by the CurlyRouter based on number of parameters and number of static path elements.
 | 
			
		||||
type curlyRoute struct {
 | 
			
		||||
	route       Route
 | 
			
		||||
	paramCount  int
 | 
			
		||||
	staticCount int
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// sortableCurlyRoutes orders by most parameters and path elements first.
 | 
			
		||||
type sortableCurlyRoutes []curlyRoute
 | 
			
		||||
 | 
			
		||||
func (s *sortableCurlyRoutes) add(route curlyRoute) {
 | 
			
		||||
	*s = append(*s, route)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (s sortableCurlyRoutes) routes() (routes []Route) {
 | 
			
		||||
	routes = make([]Route, 0, len(s))
 | 
			
		||||
	for _, each := range s {
 | 
			
		||||
		routes = append(routes, each.route) // TODO change return type
 | 
			
		||||
	}
 | 
			
		||||
	return routes
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (s sortableCurlyRoutes) Len() int {
 | 
			
		||||
	return len(s)
 | 
			
		||||
}
 | 
			
		||||
func (s sortableCurlyRoutes) Swap(i, j int) {
 | 
			
		||||
	s[i], s[j] = s[j], s[i]
 | 
			
		||||
}
 | 
			
		||||
func (s sortableCurlyRoutes) Less(i, j int) bool {
 | 
			
		||||
	a := s[j]
 | 
			
		||||
	b := s[i]
 | 
			
		||||
 | 
			
		||||
	// primary key
 | 
			
		||||
	if a.staticCount < b.staticCount {
 | 
			
		||||
		return true
 | 
			
		||||
	}
 | 
			
		||||
	if a.staticCount > b.staticCount {
 | 
			
		||||
		return false
 | 
			
		||||
	}
 | 
			
		||||
	// secundary key
 | 
			
		||||
	if a.paramCount < b.paramCount {
 | 
			
		||||
		return true
 | 
			
		||||
	}
 | 
			
		||||
	if a.paramCount > b.paramCount {
 | 
			
		||||
		return false
 | 
			
		||||
	}
 | 
			
		||||
	return a.route.Path < b.route.Path
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										29
									
								
								vendor/github.com/emicklei/go-restful/v3/custom_verb.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								vendor/github.com/emicklei/go-restful/v3/custom_verb.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,29 @@
 | 
			
		||||
package restful
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"regexp"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
var (
 | 
			
		||||
	customVerbReg = regexp.MustCompile(":([A-Za-z]+)$")
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func hasCustomVerb(routeToken string) bool {
 | 
			
		||||
	return customVerbReg.MatchString(routeToken)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func isMatchCustomVerb(routeToken string, pathToken string) bool {
 | 
			
		||||
	rs := customVerbReg.FindStringSubmatch(routeToken)
 | 
			
		||||
	if len(rs) < 2 {
 | 
			
		||||
		return false
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	customVerb := rs[1]
 | 
			
		||||
	specificVerbReg := regexp.MustCompile(fmt.Sprintf(":%s$", customVerb))
 | 
			
		||||
	return specificVerbReg.MatchString(pathToken)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func removeCustomVerb(str string) string {
 | 
			
		||||
	return customVerbReg.ReplaceAllString(str, "")
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										185
									
								
								vendor/github.com/emicklei/go-restful/v3/doc.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										185
									
								
								vendor/github.com/emicklei/go-restful/v3/doc.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,185 @@
 | 
			
		||||
/*
 | 
			
		||||
Package restful , a lean package for creating REST-style WebServices without magic.
 | 
			
		||||
 | 
			
		||||
WebServices and Routes
 | 
			
		||||
 | 
			
		||||
A WebService has a collection of Route objects that dispatch incoming Http Requests to a function calls.
 | 
			
		||||
Typically, a WebService has a root path (e.g. /users) and defines common MIME types for its routes.
 | 
			
		||||
WebServices must be added to a container (see below) in order to handler Http requests from a server.
 | 
			
		||||
 | 
			
		||||
A Route is defined by a HTTP method, an URL path and (optionally) the MIME types it consumes (Content-Type) and produces (Accept).
 | 
			
		||||
This package has the logic to find the best matching Route and if found, call its Function.
 | 
			
		||||
 | 
			
		||||
	ws := new(restful.WebService)
 | 
			
		||||
	ws.
 | 
			
		||||
		Path("/users").
 | 
			
		||||
		Consumes(restful.MIME_JSON, restful.MIME_XML).
 | 
			
		||||
		Produces(restful.MIME_JSON, restful.MIME_XML)
 | 
			
		||||
 | 
			
		||||
	ws.Route(ws.GET("/{user-id}").To(u.findUser))  // u is a UserResource
 | 
			
		||||
 | 
			
		||||
	...
 | 
			
		||||
 | 
			
		||||
	// GET http://localhost:8080/users/1
 | 
			
		||||
	func (u UserResource) findUser(request *restful.Request, response *restful.Response) {
 | 
			
		||||
		id := request.PathParameter("user-id")
 | 
			
		||||
		...
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
The (*Request, *Response) arguments provide functions for reading information from the request and writing information back to the response.
 | 
			
		||||
 | 
			
		||||
See the example https://github.com/emicklei/go-restful/blob/v3/examples/user-resource/restful-user-resource.go with a full implementation.
 | 
			
		||||
 | 
			
		||||
Regular expression matching Routes
 | 
			
		||||
 | 
			
		||||
A Route parameter can be specified using the format "uri/{var[:regexp]}" or the special version "uri/{var:*}" for matching the tail of the path.
 | 
			
		||||
For example, /persons/{name:[A-Z][A-Z]} can be used to restrict values for the parameter "name" to only contain capital alphabetic characters.
 | 
			
		||||
Regular expressions must use the standard Go syntax as described in the regexp package. (https://code.google.com/p/re2/wiki/Syntax)
 | 
			
		||||
This feature requires the use of a CurlyRouter.
 | 
			
		||||
 | 
			
		||||
Containers
 | 
			
		||||
 | 
			
		||||
A Container holds a collection of WebServices, Filters and a http.ServeMux for multiplexing http requests.
 | 
			
		||||
Using the statements "restful.Add(...) and restful.Filter(...)" will register WebServices and Filters to the Default Container.
 | 
			
		||||
The Default container of go-restful uses the http.DefaultServeMux.
 | 
			
		||||
You can create your own Container and create a new http.Server for that particular container.
 | 
			
		||||
 | 
			
		||||
	container := restful.NewContainer()
 | 
			
		||||
	server := &http.Server{Addr: ":8081", Handler: container}
 | 
			
		||||
 | 
			
		||||
Filters
 | 
			
		||||
 | 
			
		||||
A filter dynamically intercepts requests and responses to transform or use the information contained in the requests or responses.
 | 
			
		||||
You can use filters to perform generic logging, measurement, authentication, redirect, set response headers etc.
 | 
			
		||||
In the restful package there are three hooks into the request,response flow where filters can be added.
 | 
			
		||||
Each filter must define a FilterFunction:
 | 
			
		||||
 | 
			
		||||
	func (req *restful.Request, resp *restful.Response, chain *restful.FilterChain)
 | 
			
		||||
 | 
			
		||||
Use the following statement to pass the request,response pair to the next filter or RouteFunction
 | 
			
		||||
 | 
			
		||||
	chain.ProcessFilter(req, resp)
 | 
			
		||||
 | 
			
		||||
Container Filters
 | 
			
		||||
 | 
			
		||||
These are processed before any registered WebService.
 | 
			
		||||
 | 
			
		||||
	// install a (global) filter for the default container (processed before any webservice)
 | 
			
		||||
	restful.Filter(globalLogging)
 | 
			
		||||
 | 
			
		||||
WebService Filters
 | 
			
		||||
 | 
			
		||||
These are processed before any Route of a WebService.
 | 
			
		||||
 | 
			
		||||
	// install a webservice filter (processed before any route)
 | 
			
		||||
	ws.Filter(webserviceLogging).Filter(measureTime)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
Route Filters
 | 
			
		||||
 | 
			
		||||
These are processed before calling the function associated with the Route.
 | 
			
		||||
 | 
			
		||||
	// install 2 chained route filters (processed before calling findUser)
 | 
			
		||||
	ws.Route(ws.GET("/{user-id}").Filter(routeLogging).Filter(NewCountFilter().routeCounter).To(findUser))
 | 
			
		||||
 | 
			
		||||
See the example https://github.com/emicklei/go-restful/blob/v3/examples/filters/restful-filters.go with full implementations.
 | 
			
		||||
 | 
			
		||||
Response Encoding
 | 
			
		||||
 | 
			
		||||
Two encodings are supported: gzip and deflate. To enable this for all responses:
 | 
			
		||||
 | 
			
		||||
	restful.DefaultContainer.EnableContentEncoding(true)
 | 
			
		||||
 | 
			
		||||
If a Http request includes the Accept-Encoding header then the response content will be compressed using the specified encoding.
 | 
			
		||||
Alternatively, you can create a Filter that performs the encoding and install it per WebService or Route.
 | 
			
		||||
 | 
			
		||||
See the example https://github.com/emicklei/go-restful/blob/v3/examples/encoding/restful-encoding-filter.go
 | 
			
		||||
 | 
			
		||||
OPTIONS support
 | 
			
		||||
 | 
			
		||||
By installing a pre-defined container filter, your Webservice(s) can respond to the OPTIONS Http request.
 | 
			
		||||
 | 
			
		||||
	Filter(OPTIONSFilter())
 | 
			
		||||
 | 
			
		||||
CORS
 | 
			
		||||
 | 
			
		||||
By installing the filter of a CrossOriginResourceSharing (CORS), your WebService(s) can handle CORS requests.
 | 
			
		||||
 | 
			
		||||
	cors := CrossOriginResourceSharing{ExposeHeaders: []string{"X-My-Header"}, CookiesAllowed: false, Container: DefaultContainer}
 | 
			
		||||
	Filter(cors.Filter)
 | 
			
		||||
 | 
			
		||||
Error Handling
 | 
			
		||||
 | 
			
		||||
Unexpected things happen. If a request cannot be processed because of a failure, your service needs to tell via the response what happened and why.
 | 
			
		||||
For this reason HTTP status codes exist and it is important to use the correct code in every exceptional situation.
 | 
			
		||||
 | 
			
		||||
	400: Bad Request
 | 
			
		||||
 | 
			
		||||
If path or query parameters are not valid (content or type) then use http.StatusBadRequest.
 | 
			
		||||
 | 
			
		||||
	404: Not Found
 | 
			
		||||
 | 
			
		||||
Despite a valid URI, the resource requested may not be available
 | 
			
		||||
 | 
			
		||||
	500: Internal Server Error
 | 
			
		||||
 | 
			
		||||
If the application logic could not process the request (or write the response) then use http.StatusInternalServerError.
 | 
			
		||||
 | 
			
		||||
	405: Method Not Allowed
 | 
			
		||||
 | 
			
		||||
The request has a valid URL but the method (GET,PUT,POST,...) is not allowed.
 | 
			
		||||
 | 
			
		||||
	406: Not Acceptable
 | 
			
		||||
 | 
			
		||||
The request does not have or has an unknown Accept Header set for this operation.
 | 
			
		||||
 | 
			
		||||
	415: Unsupported Media Type
 | 
			
		||||
 | 
			
		||||
The request does not have or has an unknown Content-Type Header set for this operation.
 | 
			
		||||
 | 
			
		||||
ServiceError
 | 
			
		||||
 | 
			
		||||
In addition to setting the correct (error) Http status code, you can choose to write a ServiceError message on the response.
 | 
			
		||||
 | 
			
		||||
Performance options
 | 
			
		||||
 | 
			
		||||
This package has several options that affect the performance of your service. It is important to understand them and how you can change it.
 | 
			
		||||
 | 
			
		||||
	restful.DefaultContainer.DoNotRecover(false)
 | 
			
		||||
 | 
			
		||||
DoNotRecover controls whether panics will be caught to return HTTP 500.
 | 
			
		||||
If set to false, the container will recover from panics.
 | 
			
		||||
Default value is true
 | 
			
		||||
 | 
			
		||||
	restful.SetCompressorProvider(NewBoundedCachedCompressors(20, 20))
 | 
			
		||||
 | 
			
		||||
If content encoding is enabled then the default strategy for getting new gzip/zlib writers and readers is to use a sync.Pool.
 | 
			
		||||
Because writers are expensive structures, performance is even more improved when using a preloaded cache. You can also inject your own implementation.
 | 
			
		||||
 | 
			
		||||
Trouble shooting
 | 
			
		||||
 | 
			
		||||
This package has the means to produce detail logging of the complete Http request matching process and filter invocation.
 | 
			
		||||
Enabling this feature requires you to set an implementation of restful.StdLogger (e.g. log.Logger) instance such as:
 | 
			
		||||
 | 
			
		||||
	restful.TraceLogger(log.New(os.Stdout, "[restful] ", log.LstdFlags|log.Lshortfile))
 | 
			
		||||
 | 
			
		||||
Logging
 | 
			
		||||
 | 
			
		||||
The restful.SetLogger() method allows you to override the logger used by the package. By default restful
 | 
			
		||||
uses the standard library `log` package and logs to stdout. Different logging packages are supported as
 | 
			
		||||
long as they conform to `StdLogger` interface defined in the `log` sub-package, writing an adapter for your
 | 
			
		||||
preferred package is simple.
 | 
			
		||||
 | 
			
		||||
Resources
 | 
			
		||||
 | 
			
		||||
[project]: https://github.com/emicklei/go-restful
 | 
			
		||||
 | 
			
		||||
[examples]: https://github.com/emicklei/go-restful/blob/master/examples
 | 
			
		||||
 | 
			
		||||
[design]:  http://ernestmicklei.com/2012/11/11/go-restful-api-design/
 | 
			
		||||
 | 
			
		||||
[showcases]: https://github.com/emicklei/mora, https://github.com/emicklei/landskape
 | 
			
		||||
 | 
			
		||||
(c) 2012-2015, http://ernestmicklei.com. MIT License
 | 
			
		||||
*/
 | 
			
		||||
package restful
 | 
			
		||||
							
								
								
									
										162
									
								
								vendor/github.com/emicklei/go-restful/v3/entity_accessors.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										162
									
								
								vendor/github.com/emicklei/go-restful/v3/entity_accessors.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,162 @@
 | 
			
		||||
package restful
 | 
			
		||||
 | 
			
		||||
// Copyright 2015 Ernest Micklei. All rights reserved.
 | 
			
		||||
// Use of this source code is governed by a license
 | 
			
		||||
// that can be found in the LICENSE file.
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"encoding/xml"
 | 
			
		||||
	"strings"
 | 
			
		||||
	"sync"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// EntityReaderWriter can read and write values using an encoding such as JSON,XML.
 | 
			
		||||
type EntityReaderWriter interface {
 | 
			
		||||
	// Read a serialized version of the value from the request.
 | 
			
		||||
	// The Request may have a decompressing reader. Depends on Content-Encoding.
 | 
			
		||||
	Read(req *Request, v interface{}) error
 | 
			
		||||
 | 
			
		||||
	// Write a serialized version of the value on the response.
 | 
			
		||||
	// The Response may have a compressing writer. Depends on Accept-Encoding.
 | 
			
		||||
	// status should be a valid Http Status code
 | 
			
		||||
	Write(resp *Response, status int, v interface{}) error
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// entityAccessRegistry is a singleton
 | 
			
		||||
var entityAccessRegistry = &entityReaderWriters{
 | 
			
		||||
	protection: new(sync.RWMutex),
 | 
			
		||||
	accessors:  map[string]EntityReaderWriter{},
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// entityReaderWriters associates MIME to an EntityReaderWriter
 | 
			
		||||
type entityReaderWriters struct {
 | 
			
		||||
	protection *sync.RWMutex
 | 
			
		||||
	accessors  map[string]EntityReaderWriter
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func init() {
 | 
			
		||||
	RegisterEntityAccessor(MIME_JSON, NewEntityAccessorJSON(MIME_JSON))
 | 
			
		||||
	RegisterEntityAccessor(MIME_XML, NewEntityAccessorXML(MIME_XML))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// RegisterEntityAccessor add/overrides the ReaderWriter for encoding content with this MIME type.
 | 
			
		||||
func RegisterEntityAccessor(mime string, erw EntityReaderWriter) {
 | 
			
		||||
	entityAccessRegistry.protection.Lock()
 | 
			
		||||
	defer entityAccessRegistry.protection.Unlock()
 | 
			
		||||
	entityAccessRegistry.accessors[mime] = erw
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// NewEntityAccessorJSON returns a new EntityReaderWriter for accessing JSON content.
 | 
			
		||||
// This package is already initialized with such an accessor using the MIME_JSON contentType.
 | 
			
		||||
func NewEntityAccessorJSON(contentType string) EntityReaderWriter {
 | 
			
		||||
	return entityJSONAccess{ContentType: contentType}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// NewEntityAccessorXML returns a new EntityReaderWriter for accessing XML content.
 | 
			
		||||
// This package is already initialized with such an accessor using the MIME_XML contentType.
 | 
			
		||||
func NewEntityAccessorXML(contentType string) EntityReaderWriter {
 | 
			
		||||
	return entityXMLAccess{ContentType: contentType}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// accessorAt returns the registered ReaderWriter for this MIME type.
 | 
			
		||||
func (r *entityReaderWriters) accessorAt(mime string) (EntityReaderWriter, bool) {
 | 
			
		||||
	r.protection.RLock()
 | 
			
		||||
	defer r.protection.RUnlock()
 | 
			
		||||
	er, ok := r.accessors[mime]
 | 
			
		||||
	if !ok {
 | 
			
		||||
		// retry with reverse lookup
 | 
			
		||||
		// more expensive but we are in an exceptional situation anyway
 | 
			
		||||
		for k, v := range r.accessors {
 | 
			
		||||
			if strings.Contains(mime, k) {
 | 
			
		||||
				return v, true
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return er, ok
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// entityXMLAccess is a EntityReaderWriter for XML encoding
 | 
			
		||||
type entityXMLAccess struct {
 | 
			
		||||
	// This is used for setting the Content-Type header when writing
 | 
			
		||||
	ContentType string
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Read unmarshalls the value from XML
 | 
			
		||||
func (e entityXMLAccess) Read(req *Request, v interface{}) error {
 | 
			
		||||
	return xml.NewDecoder(req.Request.Body).Decode(v)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Write marshalls the value to JSON and set the Content-Type Header.
 | 
			
		||||
func (e entityXMLAccess) Write(resp *Response, status int, v interface{}) error {
 | 
			
		||||
	return writeXML(resp, status, e.ContentType, v)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// writeXML marshalls the value to JSON and set the Content-Type Header.
 | 
			
		||||
func writeXML(resp *Response, status int, contentType string, v interface{}) error {
 | 
			
		||||
	if v == nil {
 | 
			
		||||
		resp.WriteHeader(status)
 | 
			
		||||
		// do not write a nil representation
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
	if resp.prettyPrint {
 | 
			
		||||
		// pretty output must be created and written explicitly
 | 
			
		||||
		output, err := xml.MarshalIndent(v, " ", " ")
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
		resp.Header().Set(HEADER_ContentType, contentType)
 | 
			
		||||
		resp.WriteHeader(status)
 | 
			
		||||
		_, err = resp.Write([]byte(xml.Header))
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
		_, err = resp.Write(output)
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	// not-so-pretty
 | 
			
		||||
	resp.Header().Set(HEADER_ContentType, contentType)
 | 
			
		||||
	resp.WriteHeader(status)
 | 
			
		||||
	return xml.NewEncoder(resp).Encode(v)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// entityJSONAccess is a EntityReaderWriter for JSON encoding
 | 
			
		||||
type entityJSONAccess struct {
 | 
			
		||||
	// This is used for setting the Content-Type header when writing
 | 
			
		||||
	ContentType string
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Read unmarshalls the value from JSON
 | 
			
		||||
func (e entityJSONAccess) Read(req *Request, v interface{}) error {
 | 
			
		||||
	decoder := NewDecoder(req.Request.Body)
 | 
			
		||||
	decoder.UseNumber()
 | 
			
		||||
	return decoder.Decode(v)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Write marshalls the value to JSON and set the Content-Type Header.
 | 
			
		||||
func (e entityJSONAccess) Write(resp *Response, status int, v interface{}) error {
 | 
			
		||||
	return writeJSON(resp, status, e.ContentType, v)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// write marshalls the value to JSON and set the Content-Type Header.
 | 
			
		||||
func writeJSON(resp *Response, status int, contentType string, v interface{}) error {
 | 
			
		||||
	if v == nil {
 | 
			
		||||
		resp.WriteHeader(status)
 | 
			
		||||
		// do not write a nil representation
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
	if resp.prettyPrint {
 | 
			
		||||
		// pretty output must be created and written explicitly
 | 
			
		||||
		output, err := MarshalIndent(v, "", " ")
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
		resp.Header().Set(HEADER_ContentType, contentType)
 | 
			
		||||
		resp.WriteHeader(status)
 | 
			
		||||
		_, err = resp.Write(output)
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	// not-so-pretty
 | 
			
		||||
	resp.Header().Set(HEADER_ContentType, contentType)
 | 
			
		||||
	resp.WriteHeader(status)
 | 
			
		||||
	return NewEncoder(resp).Encode(v)
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										21
									
								
								vendor/github.com/emicklei/go-restful/v3/extensions.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								vendor/github.com/emicklei/go-restful/v3/extensions.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,21 @@
 | 
			
		||||
package restful
 | 
			
		||||
 | 
			
		||||
// Copyright 2021 Ernest Micklei. All rights reserved.
 | 
			
		||||
// Use of this source code is governed by a license
 | 
			
		||||
// that can be found in the LICENSE file.
 | 
			
		||||
 | 
			
		||||
// ExtensionProperties provides storage of vendor extensions for entities
 | 
			
		||||
type ExtensionProperties struct {
 | 
			
		||||
	// Extensions vendor extensions used to describe extra functionality
 | 
			
		||||
	// (https://swagger.io/docs/specification/2-0/swagger-extensions/)
 | 
			
		||||
	Extensions map[string]interface{}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// AddExtension adds or updates a key=value pair to the extension map.
 | 
			
		||||
func (ep *ExtensionProperties) AddExtension(key string, value interface{}) {
 | 
			
		||||
	if ep.Extensions == nil {
 | 
			
		||||
		ep.Extensions = map[string]interface{}{key: value}
 | 
			
		||||
	} else {
 | 
			
		||||
		ep.Extensions[key] = value
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										37
									
								
								vendor/github.com/emicklei/go-restful/v3/filter.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										37
									
								
								vendor/github.com/emicklei/go-restful/v3/filter.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,37 @@
 | 
			
		||||
package restful
 | 
			
		||||
 | 
			
		||||
// Copyright 2013 Ernest Micklei. All rights reserved.
 | 
			
		||||
// Use of this source code is governed by a license
 | 
			
		||||
// that can be found in the LICENSE file.
 | 
			
		||||
 | 
			
		||||
// FilterChain is a request scoped object to process one or more filters before calling the target RouteFunction.
 | 
			
		||||
type FilterChain struct {
 | 
			
		||||
	Filters       []FilterFunction // ordered list of FilterFunction
 | 
			
		||||
	Index         int              // index into filters that is currently in progress
 | 
			
		||||
	Target        RouteFunction    // function to call after passing all filters
 | 
			
		||||
	ParameterDocs []*Parameter     // the parameter docs for the route
 | 
			
		||||
	Operation     string           // the name of the operation
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ProcessFilter passes the request,response pair through the next of Filters.
 | 
			
		||||
// Each filter can decide to proceed to the next Filter or handle the Response itself.
 | 
			
		||||
func (f *FilterChain) ProcessFilter(request *Request, response *Response) {
 | 
			
		||||
	if f.Index < len(f.Filters) {
 | 
			
		||||
		f.Index++
 | 
			
		||||
		f.Filters[f.Index-1](request, response, f)
 | 
			
		||||
	} else {
 | 
			
		||||
		f.Target(request, response)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// FilterFunction definitions must call ProcessFilter on the FilterChain to pass on the control and eventually call the RouteFunction
 | 
			
		||||
type FilterFunction func(*Request, *Response, *FilterChain)
 | 
			
		||||
 | 
			
		||||
// NoBrowserCacheFilter is a filter function to set HTTP headers that disable browser caching
 | 
			
		||||
// See examples/restful-no-cache-filter.go for usage
 | 
			
		||||
func NoBrowserCacheFilter(req *Request, resp *Response, chain *FilterChain) {
 | 
			
		||||
	resp.Header().Set("Cache-Control", "no-cache, no-store, must-revalidate") // HTTP 1.1.
 | 
			
		||||
	resp.Header().Set("Pragma", "no-cache")                                   // HTTP 1.0.
 | 
			
		||||
	resp.Header().Set("Expires", "0")                                         // Proxies.
 | 
			
		||||
	chain.ProcessFilter(req, resp)
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										11
									
								
								vendor/github.com/emicklei/go-restful/v3/json.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								vendor/github.com/emicklei/go-restful/v3/json.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,11 @@
 | 
			
		||||
// +build !jsoniter
 | 
			
		||||
 | 
			
		||||
package restful
 | 
			
		||||
 | 
			
		||||
import "encoding/json"
 | 
			
		||||
 | 
			
		||||
var (
 | 
			
		||||
	MarshalIndent = json.MarshalIndent
 | 
			
		||||
	NewDecoder    = json.NewDecoder
 | 
			
		||||
	NewEncoder    = json.NewEncoder
 | 
			
		||||
)
 | 
			
		||||
							
								
								
									
										12
									
								
								vendor/github.com/emicklei/go-restful/v3/jsoniter.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								vendor/github.com/emicklei/go-restful/v3/jsoniter.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,12 @@
 | 
			
		||||
// +build jsoniter
 | 
			
		||||
 | 
			
		||||
package restful
 | 
			
		||||
 | 
			
		||||
import "github.com/json-iterator/go"
 | 
			
		||||
 | 
			
		||||
var (
 | 
			
		||||
	json          = jsoniter.ConfigCompatibleWithStandardLibrary
 | 
			
		||||
	MarshalIndent = json.MarshalIndent
 | 
			
		||||
	NewDecoder    = json.NewDecoder
 | 
			
		||||
	NewEncoder    = json.NewEncoder
 | 
			
		||||
)
 | 
			
		||||
							
								
								
									
										326
									
								
								vendor/github.com/emicklei/go-restful/v3/jsr311.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										326
									
								
								vendor/github.com/emicklei/go-restful/v3/jsr311.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,326 @@
 | 
			
		||||
package restful
 | 
			
		||||
 | 
			
		||||
// Copyright 2013 Ernest Micklei. All rights reserved.
 | 
			
		||||
// Use of this source code is governed by a license
 | 
			
		||||
// that can be found in the LICENSE file.
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"errors"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"net/http"
 | 
			
		||||
	"sort"
 | 
			
		||||
	"strings"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// RouterJSR311 implements the flow for matching Requests to Routes (and consequently Resource Functions)
 | 
			
		||||
// as specified by the JSR311 http://jsr311.java.net/nonav/releases/1.1/spec/spec.html.
 | 
			
		||||
// RouterJSR311 implements the Router interface.
 | 
			
		||||
// Concept of locators is not implemented.
 | 
			
		||||
type RouterJSR311 struct{}
 | 
			
		||||
 | 
			
		||||
// SelectRoute is part of the Router interface and returns the best match
 | 
			
		||||
// for the WebService and its Route for the given Request.
 | 
			
		||||
func (r RouterJSR311) SelectRoute(
 | 
			
		||||
	webServices []*WebService,
 | 
			
		||||
	httpRequest *http.Request) (selectedService *WebService, selectedRoute *Route, err error) {
 | 
			
		||||
 | 
			
		||||
	// Identify the root resource class (WebService)
 | 
			
		||||
	dispatcher, finalMatch, err := r.detectDispatcher(httpRequest.URL.Path, webServices)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, nil, NewError(http.StatusNotFound, "")
 | 
			
		||||
	}
 | 
			
		||||
	// Obtain the set of candidate methods (Routes)
 | 
			
		||||
	routes := r.selectRoutes(dispatcher, finalMatch)
 | 
			
		||||
	if len(routes) == 0 {
 | 
			
		||||
		return dispatcher, nil, NewError(http.StatusNotFound, "404: Page Not Found")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Identify the method (Route) that will handle the request
 | 
			
		||||
	route, ok := r.detectRoute(routes, httpRequest)
 | 
			
		||||
	return dispatcher, route, ok
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ExtractParameters is used to obtain the path parameters from the route using the same matching
 | 
			
		||||
// engine as the JSR 311 router.
 | 
			
		||||
func (r RouterJSR311) ExtractParameters(route *Route, webService *WebService, urlPath string) map[string]string {
 | 
			
		||||
	webServiceExpr := webService.pathExpr
 | 
			
		||||
	webServiceMatches := webServiceExpr.Matcher.FindStringSubmatch(urlPath)
 | 
			
		||||
	pathParameters := r.extractParams(webServiceExpr, webServiceMatches)
 | 
			
		||||
	routeExpr := route.pathExpr
 | 
			
		||||
	routeMatches := routeExpr.Matcher.FindStringSubmatch(webServiceMatches[len(webServiceMatches)-1])
 | 
			
		||||
	routeParams := r.extractParams(routeExpr, routeMatches)
 | 
			
		||||
	for key, value := range routeParams {
 | 
			
		||||
		pathParameters[key] = value
 | 
			
		||||
	}
 | 
			
		||||
	return pathParameters
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (RouterJSR311) extractParams(pathExpr *pathExpression, matches []string) map[string]string {
 | 
			
		||||
	params := map[string]string{}
 | 
			
		||||
	for i := 1; i < len(matches); i++ {
 | 
			
		||||
		if len(pathExpr.VarNames) >= i {
 | 
			
		||||
			params[pathExpr.VarNames[i-1]] = matches[i]
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return params
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// http://jsr311.java.net/nonav/releases/1.1/spec/spec3.html#x3-360003.7.2
 | 
			
		||||
func (r RouterJSR311) detectRoute(routes []Route, httpRequest *http.Request) (*Route, error) {
 | 
			
		||||
	candidates := make([]*Route, 0, 8)
 | 
			
		||||
	for i, each := range routes {
 | 
			
		||||
		ok := true
 | 
			
		||||
		for _, fn := range each.If {
 | 
			
		||||
			if !fn(httpRequest) {
 | 
			
		||||
				ok = false
 | 
			
		||||
				break
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		if ok {
 | 
			
		||||
			candidates = append(candidates, &routes[i])
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	if len(candidates) == 0 {
 | 
			
		||||
		if trace {
 | 
			
		||||
			traceLogger.Printf("no Route found (from %d) that passes conditional checks", len(routes))
 | 
			
		||||
		}
 | 
			
		||||
		return nil, NewError(http.StatusNotFound, "404: Not Found")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// http method
 | 
			
		||||
	previous := candidates
 | 
			
		||||
	candidates = candidates[:0]
 | 
			
		||||
	for _, each := range previous {
 | 
			
		||||
		if httpRequest.Method == each.Method {
 | 
			
		||||
			candidates = append(candidates, each)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	if len(candidates) == 0 {
 | 
			
		||||
		if trace {
 | 
			
		||||
			traceLogger.Printf("no Route found (in %d routes) that matches HTTP method %s\n", len(previous), httpRequest.Method)
 | 
			
		||||
		}
 | 
			
		||||
		allowed := []string{}
 | 
			
		||||
	allowedLoop:
 | 
			
		||||
		for _, candidate := range previous {
 | 
			
		||||
			for _, method := range allowed {
 | 
			
		||||
				if method == candidate.Method {
 | 
			
		||||
					continue allowedLoop
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
			allowed = append(allowed, candidate.Method)
 | 
			
		||||
		}
 | 
			
		||||
		header := http.Header{"Allow": []string{strings.Join(allowed, ", ")}}
 | 
			
		||||
		return nil, NewErrorWithHeader(http.StatusMethodNotAllowed, "405: Method Not Allowed", header)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// content-type
 | 
			
		||||
	contentType := httpRequest.Header.Get(HEADER_ContentType)
 | 
			
		||||
	previous = candidates
 | 
			
		||||
	candidates = candidates[:0]
 | 
			
		||||
	for _, each := range previous {
 | 
			
		||||
		if each.matchesContentType(contentType) {
 | 
			
		||||
			candidates = append(candidates, each)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	if len(candidates) == 0 {
 | 
			
		||||
		if trace {
 | 
			
		||||
			traceLogger.Printf("no Route found (from %d) that matches HTTP Content-Type: %s\n", len(previous), contentType)
 | 
			
		||||
		}
 | 
			
		||||
		if httpRequest.ContentLength > 0 {
 | 
			
		||||
			return nil, NewError(http.StatusUnsupportedMediaType, "415: Unsupported Media Type")
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// accept
 | 
			
		||||
	previous = candidates
 | 
			
		||||
	candidates = candidates[:0]
 | 
			
		||||
	accept := httpRequest.Header.Get(HEADER_Accept)
 | 
			
		||||
	if len(accept) == 0 {
 | 
			
		||||
		accept = "*/*"
 | 
			
		||||
	}
 | 
			
		||||
	for _, each := range previous {
 | 
			
		||||
		if each.matchesAccept(accept) {
 | 
			
		||||
			candidates = append(candidates, each)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	if len(candidates) == 0 {
 | 
			
		||||
		if trace {
 | 
			
		||||
			traceLogger.Printf("no Route found (from %d) that matches HTTP Accept: %s\n", len(previous), accept)
 | 
			
		||||
		}
 | 
			
		||||
		available := []string{}
 | 
			
		||||
		for _, candidate := range previous {
 | 
			
		||||
			available = append(available, candidate.Produces...)
 | 
			
		||||
		}
 | 
			
		||||
		// if POST,PUT,PATCH without body
 | 
			
		||||
		method, length := httpRequest.Method, httpRequest.Header.Get("Content-Length")
 | 
			
		||||
		if (method == http.MethodPost ||
 | 
			
		||||
			method == http.MethodPut ||
 | 
			
		||||
			method == http.MethodPatch) && length == "" {
 | 
			
		||||
			return nil, NewError(
 | 
			
		||||
				http.StatusUnsupportedMediaType,
 | 
			
		||||
				fmt.Sprintf("415: Unsupported Media Type\n\nAvailable representations: %s", strings.Join(available, ", ")),
 | 
			
		||||
			)
 | 
			
		||||
		}
 | 
			
		||||
		return nil, NewError(
 | 
			
		||||
			http.StatusNotAcceptable,
 | 
			
		||||
			fmt.Sprintf("406: Not Acceptable\n\nAvailable representations: %s", strings.Join(available, ", ")),
 | 
			
		||||
		)
 | 
			
		||||
	}
 | 
			
		||||
	// return r.bestMatchByMedia(outputMediaOk, contentType, accept), nil
 | 
			
		||||
	return candidates[0], nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// http://jsr311.java.net/nonav/releases/1.1/spec/spec3.html#x3-360003.7.2
 | 
			
		||||
// n/m > n/* > */*
 | 
			
		||||
func (r RouterJSR311) bestMatchByMedia(routes []Route, contentType string, accept string) *Route {
 | 
			
		||||
	// TODO
 | 
			
		||||
	return &routes[0]
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// http://jsr311.java.net/nonav/releases/1.1/spec/spec3.html#x3-360003.7.2  (step 2)
 | 
			
		||||
func (r RouterJSR311) selectRoutes(dispatcher *WebService, pathRemainder string) []Route {
 | 
			
		||||
	filtered := &sortableRouteCandidates{}
 | 
			
		||||
	for _, each := range dispatcher.Routes() {
 | 
			
		||||
		pathExpr := each.pathExpr
 | 
			
		||||
		matches := pathExpr.Matcher.FindStringSubmatch(pathRemainder)
 | 
			
		||||
		if matches != nil {
 | 
			
		||||
			lastMatch := matches[len(matches)-1]
 | 
			
		||||
			if len(lastMatch) == 0 || lastMatch == "/" { // do not include if value is neither empty nor ‘/’.
 | 
			
		||||
				filtered.candidates = append(filtered.candidates,
 | 
			
		||||
					routeCandidate{each, len(matches) - 1, pathExpr.LiteralCount, pathExpr.VarCount})
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	if len(filtered.candidates) == 0 {
 | 
			
		||||
		if trace {
 | 
			
		||||
			traceLogger.Printf("WebService on path %s has no routes that match URL path remainder:%s\n", dispatcher.rootPath, pathRemainder)
 | 
			
		||||
		}
 | 
			
		||||
		return []Route{}
 | 
			
		||||
	}
 | 
			
		||||
	sort.Sort(sort.Reverse(filtered))
 | 
			
		||||
 | 
			
		||||
	// select other routes from candidates whoes expression matches rmatch
 | 
			
		||||
	matchingRoutes := []Route{filtered.candidates[0].route}
 | 
			
		||||
	for c := 1; c < len(filtered.candidates); c++ {
 | 
			
		||||
		each := filtered.candidates[c]
 | 
			
		||||
		if each.route.pathExpr.Matcher.MatchString(pathRemainder) {
 | 
			
		||||
			matchingRoutes = append(matchingRoutes, each.route)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return matchingRoutes
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// http://jsr311.java.net/nonav/releases/1.1/spec/spec3.html#x3-360003.7.2 (step 1)
 | 
			
		||||
func (r RouterJSR311) detectDispatcher(requestPath string, dispatchers []*WebService) (*WebService, string, error) {
 | 
			
		||||
	filtered := &sortableDispatcherCandidates{}
 | 
			
		||||
	for _, each := range dispatchers {
 | 
			
		||||
		matches := each.pathExpr.Matcher.FindStringSubmatch(requestPath)
 | 
			
		||||
		if matches != nil {
 | 
			
		||||
			filtered.candidates = append(filtered.candidates,
 | 
			
		||||
				dispatcherCandidate{each, matches[len(matches)-1], len(matches), each.pathExpr.LiteralCount, each.pathExpr.VarCount})
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	if len(filtered.candidates) == 0 {
 | 
			
		||||
		if trace {
 | 
			
		||||
			traceLogger.Printf("no WebService was found to match URL path:%s\n", requestPath)
 | 
			
		||||
		}
 | 
			
		||||
		return nil, "", errors.New("not found")
 | 
			
		||||
	}
 | 
			
		||||
	sort.Sort(sort.Reverse(filtered))
 | 
			
		||||
	return filtered.candidates[0].dispatcher, filtered.candidates[0].finalMatch, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Types and functions to support the sorting of Routes
 | 
			
		||||
 | 
			
		||||
type routeCandidate struct {
 | 
			
		||||
	route           Route
 | 
			
		||||
	matchesCount    int // the number of capturing groups
 | 
			
		||||
	literalCount    int // the number of literal characters (means those not resulting from template variable substitution)
 | 
			
		||||
	nonDefaultCount int // the number of capturing groups with non-default regular expressions (i.e. not ‘([^  /]+?)’)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (r routeCandidate) expressionToMatch() string {
 | 
			
		||||
	return r.route.pathExpr.Source
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (r routeCandidate) String() string {
 | 
			
		||||
	return fmt.Sprintf("(m=%d,l=%d,n=%d)", r.matchesCount, r.literalCount, r.nonDefaultCount)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type sortableRouteCandidates struct {
 | 
			
		||||
	candidates []routeCandidate
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (rcs *sortableRouteCandidates) Len() int {
 | 
			
		||||
	return len(rcs.candidates)
 | 
			
		||||
}
 | 
			
		||||
func (rcs *sortableRouteCandidates) Swap(i, j int) {
 | 
			
		||||
	rcs.candidates[i], rcs.candidates[j] = rcs.candidates[j], rcs.candidates[i]
 | 
			
		||||
}
 | 
			
		||||
func (rcs *sortableRouteCandidates) Less(i, j int) bool {
 | 
			
		||||
	ci := rcs.candidates[i]
 | 
			
		||||
	cj := rcs.candidates[j]
 | 
			
		||||
	// primary key
 | 
			
		||||
	if ci.literalCount < cj.literalCount {
 | 
			
		||||
		return true
 | 
			
		||||
	}
 | 
			
		||||
	if ci.literalCount > cj.literalCount {
 | 
			
		||||
		return false
 | 
			
		||||
	}
 | 
			
		||||
	// secundary key
 | 
			
		||||
	if ci.matchesCount < cj.matchesCount {
 | 
			
		||||
		return true
 | 
			
		||||
	}
 | 
			
		||||
	if ci.matchesCount > cj.matchesCount {
 | 
			
		||||
		return false
 | 
			
		||||
	}
 | 
			
		||||
	// tertiary key
 | 
			
		||||
	if ci.nonDefaultCount < cj.nonDefaultCount {
 | 
			
		||||
		return true
 | 
			
		||||
	}
 | 
			
		||||
	if ci.nonDefaultCount > cj.nonDefaultCount {
 | 
			
		||||
		return false
 | 
			
		||||
	}
 | 
			
		||||
	// quaternary key ("source" is interpreted as Path)
 | 
			
		||||
	return ci.route.Path < cj.route.Path
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Types and functions to support the sorting of Dispatchers
 | 
			
		||||
 | 
			
		||||
type dispatcherCandidate struct {
 | 
			
		||||
	dispatcher      *WebService
 | 
			
		||||
	finalMatch      string
 | 
			
		||||
	matchesCount    int // the number of capturing groups
 | 
			
		||||
	literalCount    int // the number of literal characters (means those not resulting from template variable substitution)
 | 
			
		||||
	nonDefaultCount int // the number of capturing groups with non-default regular expressions (i.e. not ‘([^  /]+?)’)
 | 
			
		||||
}
 | 
			
		||||
type sortableDispatcherCandidates struct {
 | 
			
		||||
	candidates []dispatcherCandidate
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (dc *sortableDispatcherCandidates) Len() int {
 | 
			
		||||
	return len(dc.candidates)
 | 
			
		||||
}
 | 
			
		||||
func (dc *sortableDispatcherCandidates) Swap(i, j int) {
 | 
			
		||||
	dc.candidates[i], dc.candidates[j] = dc.candidates[j], dc.candidates[i]
 | 
			
		||||
}
 | 
			
		||||
func (dc *sortableDispatcherCandidates) Less(i, j int) bool {
 | 
			
		||||
	ci := dc.candidates[i]
 | 
			
		||||
	cj := dc.candidates[j]
 | 
			
		||||
	// primary key
 | 
			
		||||
	if ci.matchesCount < cj.matchesCount {
 | 
			
		||||
		return true
 | 
			
		||||
	}
 | 
			
		||||
	if ci.matchesCount > cj.matchesCount {
 | 
			
		||||
		return false
 | 
			
		||||
	}
 | 
			
		||||
	// secundary key
 | 
			
		||||
	if ci.literalCount < cj.literalCount {
 | 
			
		||||
		return true
 | 
			
		||||
	}
 | 
			
		||||
	if ci.literalCount > cj.literalCount {
 | 
			
		||||
		return false
 | 
			
		||||
	}
 | 
			
		||||
	// tertiary key
 | 
			
		||||
	return ci.nonDefaultCount < cj.nonDefaultCount
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										34
									
								
								vendor/github.com/emicklei/go-restful/v3/log/log.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								vendor/github.com/emicklei/go-restful/v3/log/log.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,34 @@
 | 
			
		||||
package log
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	stdlog "log"
 | 
			
		||||
	"os"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// StdLogger corresponds to a minimal subset of the interface satisfied by stdlib log.Logger
 | 
			
		||||
type StdLogger interface {
 | 
			
		||||
	Print(v ...interface{})
 | 
			
		||||
	Printf(format string, v ...interface{})
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
var Logger StdLogger
 | 
			
		||||
 | 
			
		||||
func init() {
 | 
			
		||||
	// default Logger
 | 
			
		||||
	SetLogger(stdlog.New(os.Stderr, "[restful] ", stdlog.LstdFlags|stdlog.Lshortfile))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// SetLogger sets the logger for this package
 | 
			
		||||
func SetLogger(customLogger StdLogger) {
 | 
			
		||||
	Logger = customLogger
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Print delegates to the Logger
 | 
			
		||||
func Print(v ...interface{}) {
 | 
			
		||||
	Logger.Print(v...)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Printf delegates to the Logger
 | 
			
		||||
func Printf(format string, v ...interface{}) {
 | 
			
		||||
	Logger.Printf(format, v...)
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										32
									
								
								vendor/github.com/emicklei/go-restful/v3/logger.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										32
									
								
								vendor/github.com/emicklei/go-restful/v3/logger.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,32 @@
 | 
			
		||||
package restful
 | 
			
		||||
 | 
			
		||||
// 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.
 | 
			
		||||
import (
 | 
			
		||||
	"github.com/emicklei/go-restful/v3/log"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
var trace bool = false
 | 
			
		||||
var traceLogger log.StdLogger
 | 
			
		||||
 | 
			
		||||
func init() {
 | 
			
		||||
	traceLogger = log.Logger // use the package logger by default
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// TraceLogger enables detailed logging of Http request matching and filter invocation. Default no logger is set.
 | 
			
		||||
// You may call EnableTracing() directly to enable trace logging to the package-wide logger.
 | 
			
		||||
func TraceLogger(logger log.StdLogger) {
 | 
			
		||||
	traceLogger = logger
 | 
			
		||||
	EnableTracing(logger != nil)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// SetLogger exposes the setter for the global logger on the top-level package
 | 
			
		||||
func SetLogger(customLogger log.StdLogger) {
 | 
			
		||||
	log.SetLogger(customLogger)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// EnableTracing can be used to Trace logging on and off.
 | 
			
		||||
func EnableTracing(enabled bool) {
 | 
			
		||||
	trace = enabled
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										50
									
								
								vendor/github.com/emicklei/go-restful/v3/mime.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										50
									
								
								vendor/github.com/emicklei/go-restful/v3/mime.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,50 @@
 | 
			
		||||
package restful
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"strconv"
 | 
			
		||||
	"strings"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type mime struct {
 | 
			
		||||
	media   string
 | 
			
		||||
	quality float64
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// insertMime adds a mime to a list and keeps it sorted by quality.
 | 
			
		||||
func insertMime(l []mime, e mime) []mime {
 | 
			
		||||
	for i, each := range l {
 | 
			
		||||
		// if current mime has lower quality then insert before
 | 
			
		||||
		if e.quality > each.quality {
 | 
			
		||||
			left := append([]mime{}, l[0:i]...)
 | 
			
		||||
			return append(append(left, e), l[i:]...)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return append(l, e)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const qFactorWeightingKey = "q"
 | 
			
		||||
 | 
			
		||||
// sortedMimes returns a list of mime sorted (desc) by its specified quality.
 | 
			
		||||
// e.g. text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3
 | 
			
		||||
func sortedMimes(accept string) (sorted []mime) {
 | 
			
		||||
	for _, each := range strings.Split(accept, ",") {
 | 
			
		||||
		typeAndQuality := strings.Split(strings.Trim(each, " "), ";")
 | 
			
		||||
		if len(typeAndQuality) == 1 {
 | 
			
		||||
			sorted = insertMime(sorted, mime{typeAndQuality[0], 1.0})
 | 
			
		||||
		} else {
 | 
			
		||||
			// take factor
 | 
			
		||||
			qAndWeight := strings.Split(typeAndQuality[1], "=")
 | 
			
		||||
			if len(qAndWeight) == 2 && strings.Trim(qAndWeight[0], " ") == qFactorWeightingKey {
 | 
			
		||||
				f, err := strconv.ParseFloat(qAndWeight[1], 64)
 | 
			
		||||
				if err != nil {
 | 
			
		||||
					traceLogger.Printf("unable to parse quality in %s, %v", each, err)
 | 
			
		||||
				} else {
 | 
			
		||||
					sorted = insertMime(sorted, mime{typeAndQuality[0], f})
 | 
			
		||||
				}
 | 
			
		||||
			} else {
 | 
			
		||||
				sorted = insertMime(sorted, mime{typeAndQuality[0], 1.0})
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										34
									
								
								vendor/github.com/emicklei/go-restful/v3/options_filter.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								vendor/github.com/emicklei/go-restful/v3/options_filter.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,34 @@
 | 
			
		||||
package restful
 | 
			
		||||
 | 
			
		||||
import "strings"
 | 
			
		||||
 | 
			
		||||
// Copyright 2013 Ernest Micklei. All rights reserved.
 | 
			
		||||
// Use of this source code is governed by a license
 | 
			
		||||
// that can be found in the LICENSE file.
 | 
			
		||||
 | 
			
		||||
// 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.
 | 
			
		||||
// Note: this filter is not needed when using CrossOriginResourceSharing (for CORS).
 | 
			
		||||
func (c *Container) OPTIONSFilter(req *Request, resp *Response, chain *FilterChain) {
 | 
			
		||||
	if "OPTIONS" != req.Request.Method {
 | 
			
		||||
		chain.ProcessFilter(req, resp)
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	archs := req.Request.Header.Get(HEADER_AccessControlRequestHeaders)
 | 
			
		||||
	methods := strings.Join(c.computeAllowedMethods(req), ",")
 | 
			
		||||
	origin := req.Request.Header.Get(HEADER_Origin)
 | 
			
		||||
 | 
			
		||||
	resp.AddHeader(HEADER_Allow, methods)
 | 
			
		||||
	resp.AddHeader(HEADER_AccessControlAllowOrigin, origin)
 | 
			
		||||
	resp.AddHeader(HEADER_AccessControlAllowHeaders, archs)
 | 
			
		||||
	resp.AddHeader(HEADER_AccessControlAllowMethods, methods)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 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.
 | 
			
		||||
// Note: this filter is not needed when using CrossOriginResourceSharing (for CORS).
 | 
			
		||||
func OPTIONSFilter() FilterFunction {
 | 
			
		||||
	return DefaultContainer.OPTIONSFilter
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										234
									
								
								vendor/github.com/emicklei/go-restful/v3/parameter.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										234
									
								
								vendor/github.com/emicklei/go-restful/v3/parameter.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,234 @@
 | 
			
		||||
package restful
 | 
			
		||||
 | 
			
		||||
import "sort"
 | 
			
		||||
 | 
			
		||||
// Copyright 2013 Ernest Micklei. All rights reserved.
 | 
			
		||||
// Use of this source code is governed by a license
 | 
			
		||||
// that can be found in the LICENSE file.
 | 
			
		||||
 | 
			
		||||
const (
 | 
			
		||||
	// PathParameterKind = indicator of Request parameter type "path"
 | 
			
		||||
	PathParameterKind = iota
 | 
			
		||||
 | 
			
		||||
	// QueryParameterKind = indicator of Request parameter type "query"
 | 
			
		||||
	QueryParameterKind
 | 
			
		||||
 | 
			
		||||
	// BodyParameterKind = indicator of Request parameter type "body"
 | 
			
		||||
	BodyParameterKind
 | 
			
		||||
 | 
			
		||||
	// HeaderParameterKind = indicator of Request parameter type "header"
 | 
			
		||||
	HeaderParameterKind
 | 
			
		||||
 | 
			
		||||
	// FormParameterKind = indicator of Request parameter type "form"
 | 
			
		||||
	FormParameterKind
 | 
			
		||||
 | 
			
		||||
	// CollectionFormatCSV comma separated values `foo,bar`
 | 
			
		||||
	CollectionFormatCSV = CollectionFormat("csv")
 | 
			
		||||
 | 
			
		||||
	// CollectionFormatSSV space separated values `foo bar`
 | 
			
		||||
	CollectionFormatSSV = CollectionFormat("ssv")
 | 
			
		||||
 | 
			
		||||
	// CollectionFormatTSV tab separated values `foo\tbar`
 | 
			
		||||
	CollectionFormatTSV = CollectionFormat("tsv")
 | 
			
		||||
 | 
			
		||||
	// CollectionFormatPipes pipe separated values `foo|bar`
 | 
			
		||||
	CollectionFormatPipes = CollectionFormat("pipes")
 | 
			
		||||
 | 
			
		||||
	// CollectionFormatMulti corresponds to multiple parameter instances instead of multiple values for a single
 | 
			
		||||
	// instance `foo=bar&foo=baz`. This is valid only for QueryParameters and FormParameters
 | 
			
		||||
	CollectionFormatMulti = CollectionFormat("multi")
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type CollectionFormat string
 | 
			
		||||
 | 
			
		||||
func (cf CollectionFormat) String() string {
 | 
			
		||||
	return string(cf)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Parameter is for documententing the parameter used in a Http Request
 | 
			
		||||
// ParameterData kinds are Path,Query and Body
 | 
			
		||||
type Parameter struct {
 | 
			
		||||
	data *ParameterData
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ParameterData represents the state of a Parameter.
 | 
			
		||||
// It is made public to make it accessible to e.g. the Swagger package.
 | 
			
		||||
type ParameterData struct {
 | 
			
		||||
	ExtensionProperties
 | 
			
		||||
	Name, Description, DataType, DataFormat string
 | 
			
		||||
	Kind                                    int
 | 
			
		||||
	Required                                bool
 | 
			
		||||
	// AllowableValues is deprecated. Use PossibleValues instead
 | 
			
		||||
	AllowableValues  map[string]string
 | 
			
		||||
	PossibleValues   []string
 | 
			
		||||
	AllowMultiple    bool
 | 
			
		||||
	AllowEmptyValue  bool
 | 
			
		||||
	DefaultValue     string
 | 
			
		||||
	CollectionFormat string
 | 
			
		||||
	Pattern          string
 | 
			
		||||
	Minimum          *float64
 | 
			
		||||
	Maximum          *float64
 | 
			
		||||
	MinLength        *int64
 | 
			
		||||
	MaxLength        *int64
 | 
			
		||||
	MinItems         *int64
 | 
			
		||||
	MaxItems         *int64
 | 
			
		||||
	UniqueItems      bool
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Data returns the state of the Parameter
 | 
			
		||||
func (p *Parameter) Data() ParameterData {
 | 
			
		||||
	return *p.data
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Kind returns the parameter type indicator (see const for valid values)
 | 
			
		||||
func (p *Parameter) Kind() int {
 | 
			
		||||
	return p.data.Kind
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (p *Parameter) bePath() *Parameter {
 | 
			
		||||
	p.data.Kind = PathParameterKind
 | 
			
		||||
	return p
 | 
			
		||||
}
 | 
			
		||||
func (p *Parameter) beQuery() *Parameter {
 | 
			
		||||
	p.data.Kind = QueryParameterKind
 | 
			
		||||
	return p
 | 
			
		||||
}
 | 
			
		||||
func (p *Parameter) beBody() *Parameter {
 | 
			
		||||
	p.data.Kind = BodyParameterKind
 | 
			
		||||
	return p
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (p *Parameter) beHeader() *Parameter {
 | 
			
		||||
	p.data.Kind = HeaderParameterKind
 | 
			
		||||
	return p
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (p *Parameter) beForm() *Parameter {
 | 
			
		||||
	p.data.Kind = FormParameterKind
 | 
			
		||||
	return p
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Required sets the required field and returns the receiver
 | 
			
		||||
func (p *Parameter) Required(required bool) *Parameter {
 | 
			
		||||
	p.data.Required = required
 | 
			
		||||
	return p
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// AllowMultiple sets the allowMultiple field and returns the receiver
 | 
			
		||||
func (p *Parameter) AllowMultiple(multiple bool) *Parameter {
 | 
			
		||||
	p.data.AllowMultiple = multiple
 | 
			
		||||
	return p
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// AddExtension adds or updates a key=value pair to the extension map
 | 
			
		||||
func (p *Parameter) AddExtension(key string, value interface{}) *Parameter {
 | 
			
		||||
	p.data.AddExtension(key, value)
 | 
			
		||||
	return p
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// AllowEmptyValue sets the AllowEmptyValue field and returns the receiver
 | 
			
		||||
func (p *Parameter) AllowEmptyValue(multiple bool) *Parameter {
 | 
			
		||||
	p.data.AllowEmptyValue = multiple
 | 
			
		||||
	return p
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// AllowableValues is deprecated. Use PossibleValues instead. Both will be set.
 | 
			
		||||
func (p *Parameter) AllowableValues(values map[string]string) *Parameter {
 | 
			
		||||
	p.data.AllowableValues = values
 | 
			
		||||
 | 
			
		||||
	allowableSortedKeys := make([]string, 0, len(values))
 | 
			
		||||
	for k := range values {
 | 
			
		||||
		allowableSortedKeys = append(allowableSortedKeys, k)
 | 
			
		||||
	}
 | 
			
		||||
	sort.Strings(allowableSortedKeys)
 | 
			
		||||
 | 
			
		||||
	p.data.PossibleValues = make([]string, 0, len(values))
 | 
			
		||||
	for _, k := range allowableSortedKeys {
 | 
			
		||||
		p.data.PossibleValues = append(p.data.PossibleValues, values[k])
 | 
			
		||||
	}
 | 
			
		||||
	return p
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// PossibleValues sets the possible values field and returns the receiver
 | 
			
		||||
func (p *Parameter) PossibleValues(values []string) *Parameter {
 | 
			
		||||
	p.data.PossibleValues = values
 | 
			
		||||
	return p
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// DataType sets the dataType field and returns the receiver
 | 
			
		||||
func (p *Parameter) DataType(typeName string) *Parameter {
 | 
			
		||||
	p.data.DataType = typeName
 | 
			
		||||
	return p
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// DataFormat sets the dataFormat field for Swagger UI
 | 
			
		||||
func (p *Parameter) DataFormat(formatName string) *Parameter {
 | 
			
		||||
	p.data.DataFormat = formatName
 | 
			
		||||
	return p
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// DefaultValue sets the default value field and returns the receiver
 | 
			
		||||
func (p *Parameter) DefaultValue(stringRepresentation string) *Parameter {
 | 
			
		||||
	p.data.DefaultValue = stringRepresentation
 | 
			
		||||
	return p
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Description sets the description value field and returns the receiver
 | 
			
		||||
func (p *Parameter) Description(doc string) *Parameter {
 | 
			
		||||
	p.data.Description = doc
 | 
			
		||||
	return p
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// CollectionFormat sets the collection format for an array type
 | 
			
		||||
func (p *Parameter) CollectionFormat(format CollectionFormat) *Parameter {
 | 
			
		||||
	p.data.CollectionFormat = format.String()
 | 
			
		||||
	return p
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Pattern sets the pattern field and returns the receiver
 | 
			
		||||
func (p *Parameter) Pattern(pattern string) *Parameter {
 | 
			
		||||
	p.data.Pattern = pattern
 | 
			
		||||
	return p
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Minimum sets the minimum field and returns the receiver
 | 
			
		||||
func (p *Parameter) Minimum(minimum float64) *Parameter {
 | 
			
		||||
	p.data.Minimum = &minimum
 | 
			
		||||
	return p
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Maximum sets the maximum field and returns the receiver
 | 
			
		||||
func (p *Parameter) Maximum(maximum float64) *Parameter {
 | 
			
		||||
	p.data.Maximum = &maximum
 | 
			
		||||
	return p
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// MinLength sets the minLength field and returns the receiver
 | 
			
		||||
func (p *Parameter) MinLength(minLength int64) *Parameter {
 | 
			
		||||
	p.data.MinLength = &minLength
 | 
			
		||||
	return p
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// MaxLength sets the maxLength field and returns the receiver
 | 
			
		||||
func (p *Parameter) MaxLength(maxLength int64) *Parameter {
 | 
			
		||||
	p.data.MaxLength = &maxLength
 | 
			
		||||
	return p
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// MinItems sets the minItems field and returns the receiver
 | 
			
		||||
func (p *Parameter) MinItems(minItems int64) *Parameter {
 | 
			
		||||
	p.data.MinItems = &minItems
 | 
			
		||||
	return p
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// MaxItems sets the maxItems field and returns the receiver
 | 
			
		||||
func (p *Parameter) MaxItems(maxItems int64) *Parameter {
 | 
			
		||||
	p.data.MaxItems = &maxItems
 | 
			
		||||
	return p
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// UniqueItems sets the uniqueItems field and returns the receiver
 | 
			
		||||
func (p *Parameter) UniqueItems(uniqueItems bool) *Parameter {
 | 
			
		||||
	p.data.UniqueItems = uniqueItems
 | 
			
		||||
	return p
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										74
									
								
								vendor/github.com/emicklei/go-restful/v3/path_expression.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										74
									
								
								vendor/github.com/emicklei/go-restful/v3/path_expression.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,74 @@
 | 
			
		||||
package restful
 | 
			
		||||
 | 
			
		||||
// Copyright 2013 Ernest Micklei. All rights reserved.
 | 
			
		||||
// Use of this source code is governed by a license
 | 
			
		||||
// that can be found in the LICENSE file.
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"bytes"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"regexp"
 | 
			
		||||
	"strings"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// PathExpression holds a compiled path expression (RegExp) needed to match against
 | 
			
		||||
// Http request paths and to extract path parameter values.
 | 
			
		||||
type pathExpression struct {
 | 
			
		||||
	LiteralCount int      // the number of literal characters (means those not resulting from template variable substitution)
 | 
			
		||||
	VarNames     []string // the names of parameters (enclosed by {}) in the path
 | 
			
		||||
	VarCount     int      // the number of named parameters (enclosed by {}) in the path
 | 
			
		||||
	Matcher      *regexp.Regexp
 | 
			
		||||
	Source       string // Path as defined by the RouteBuilder
 | 
			
		||||
	tokens       []string
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// NewPathExpression creates a PathExpression from the input URL path.
 | 
			
		||||
// Returns an error if the path is invalid.
 | 
			
		||||
func newPathExpression(path string) (*pathExpression, error) {
 | 
			
		||||
	expression, literalCount, varNames, varCount, tokens := templateToRegularExpression(path)
 | 
			
		||||
	compiled, err := regexp.Compile(expression)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	return &pathExpression{literalCount, varNames, varCount, compiled, expression, tokens}, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// http://jsr311.java.net/nonav/releases/1.1/spec/spec3.html#x3-370003.7.3
 | 
			
		||||
func templateToRegularExpression(template string) (expression string, literalCount int, varNames []string, varCount int, tokens []string) {
 | 
			
		||||
	var buffer bytes.Buffer
 | 
			
		||||
	buffer.WriteString("^")
 | 
			
		||||
	//tokens = strings.Split(template, "/")
 | 
			
		||||
	tokens = tokenizePath(template)
 | 
			
		||||
	for _, each := range tokens {
 | 
			
		||||
		if each == "" {
 | 
			
		||||
			continue
 | 
			
		||||
		}
 | 
			
		||||
		buffer.WriteString("/")
 | 
			
		||||
		if strings.HasPrefix(each, "{") {
 | 
			
		||||
			// check for regular expression in variable
 | 
			
		||||
			colon := strings.Index(each, ":")
 | 
			
		||||
			var varName string
 | 
			
		||||
			if colon != -1 {
 | 
			
		||||
				// extract expression
 | 
			
		||||
				varName = strings.TrimSpace(each[1:colon])
 | 
			
		||||
				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
 | 
			
		||||
				varName = strings.TrimSpace(each[1 : len(each)-1])
 | 
			
		||||
				buffer.WriteString("([^/]+?)")
 | 
			
		||||
			}
 | 
			
		||||
			varNames = append(varNames, varName)
 | 
			
		||||
			varCount += 1
 | 
			
		||||
		} else {
 | 
			
		||||
			literalCount += len(each)
 | 
			
		||||
			encoded := each // TODO URI encode
 | 
			
		||||
			buffer.WriteString(regexp.QuoteMeta(encoded))
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return strings.TrimRight(buffer.String(), "/") + "(/.*)?$", literalCount, varNames, varCount, tokens
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										74
									
								
								vendor/github.com/emicklei/go-restful/v3/path_processor.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										74
									
								
								vendor/github.com/emicklei/go-restful/v3/path_processor.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,74 @@
 | 
			
		||||
package restful
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"bytes"
 | 
			
		||||
	"strings"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// Copyright 2018 Ernest Micklei. All rights reserved.
 | 
			
		||||
// Use of this source code is governed by a license
 | 
			
		||||
// that can be found in the LICENSE file.
 | 
			
		||||
 | 
			
		||||
// PathProcessor is extra behaviour that a Router can provide to extract path parameters from the path.
 | 
			
		||||
// If a Router does not implement this interface then the default behaviour will be used.
 | 
			
		||||
type PathProcessor interface {
 | 
			
		||||
	// ExtractParameters gets the path parameters defined in the route and webService from the urlPath
 | 
			
		||||
	ExtractParameters(route *Route, webService *WebService, urlPath string) map[string]string
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type defaultPathProcessor struct{}
 | 
			
		||||
 | 
			
		||||
// Extract the parameters from the request url path
 | 
			
		||||
func (d defaultPathProcessor) ExtractParameters(r *Route, _ *WebService, urlPath string) map[string]string {
 | 
			
		||||
	urlParts := tokenizePath(urlPath)
 | 
			
		||||
	pathParameters := map[string]string{}
 | 
			
		||||
	for i, key := range r.pathParts {
 | 
			
		||||
		var value string
 | 
			
		||||
		if i >= len(urlParts) {
 | 
			
		||||
			value = ""
 | 
			
		||||
		} else {
 | 
			
		||||
			value = urlParts[i]
 | 
			
		||||
		}
 | 
			
		||||
		if r.hasCustomVerb && hasCustomVerb(key) {
 | 
			
		||||
			key = removeCustomVerb(key)
 | 
			
		||||
			value = removeCustomVerb(value)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if strings.Index(key, "{") > -1 { // path-parameter
 | 
			
		||||
			if colon := strings.Index(key, ":"); colon != -1 {
 | 
			
		||||
				// extract by regex
 | 
			
		||||
				regPart := key[colon+1 : len(key)-1]
 | 
			
		||||
				keyPart := key[1:colon]
 | 
			
		||||
				if regPart == "*" {
 | 
			
		||||
					pathParameters[keyPart] = untokenizePath(i, urlParts)
 | 
			
		||||
					break
 | 
			
		||||
				} else {
 | 
			
		||||
					pathParameters[keyPart] = value
 | 
			
		||||
				}
 | 
			
		||||
			} else {
 | 
			
		||||
				// without enclosing {}
 | 
			
		||||
				startIndex := strings.Index(key, "{")
 | 
			
		||||
				endKeyIndex := strings.Index(key, "}")
 | 
			
		||||
 | 
			
		||||
				suffixLength := len(key) - endKeyIndex - 1
 | 
			
		||||
				endValueIndex := len(value) - suffixLength
 | 
			
		||||
 | 
			
		||||
				pathParameters[key[startIndex+1:endKeyIndex]] = value[startIndex:endValueIndex]
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return pathParameters
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Untokenize back into an URL path using the slash separator
 | 
			
		||||
func untokenizePath(offset int, parts []string) string {
 | 
			
		||||
	var buffer bytes.Buffer
 | 
			
		||||
	for p := offset; p < len(parts); p++ {
 | 
			
		||||
		buffer.WriteString(parts[p])
 | 
			
		||||
		// do not end
 | 
			
		||||
		if p < len(parts)-1 {
 | 
			
		||||
			buffer.WriteString("/")
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return buffer.String()
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										132
									
								
								vendor/github.com/emicklei/go-restful/v3/request.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										132
									
								
								vendor/github.com/emicklei/go-restful/v3/request.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,132 @@
 | 
			
		||||
package restful
 | 
			
		||||
 | 
			
		||||
// Copyright 2013 Ernest Micklei. All rights reserved.
 | 
			
		||||
// Use of this source code is governed by a license
 | 
			
		||||
// that can be found in the LICENSE file.
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"compress/zlib"
 | 
			
		||||
	"net/http"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
var defaultRequestContentType string
 | 
			
		||||
 | 
			
		||||
// Request is a wrapper for a http Request that provides convenience methods
 | 
			
		||||
type Request struct {
 | 
			
		||||
	Request        *http.Request
 | 
			
		||||
	pathParameters map[string]string
 | 
			
		||||
	attributes     map[string]interface{} // for storing request-scoped values
 | 
			
		||||
	selectedRoute  *Route                 // is nil when no route was matched
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func NewRequest(httpRequest *http.Request) *Request {
 | 
			
		||||
	return &Request{
 | 
			
		||||
		Request:        httpRequest,
 | 
			
		||||
		pathParameters: map[string]string{},
 | 
			
		||||
		attributes:     map[string]interface{}{},
 | 
			
		||||
	} // empty parameters, attributes
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// If ContentType is missing or */* is given then fall back to this type, otherwise
 | 
			
		||||
// a "Unable to unmarshal content of type:" response is returned.
 | 
			
		||||
// Valid values are restful.MIME_JSON and restful.MIME_XML
 | 
			
		||||
// Example:
 | 
			
		||||
// 	restful.DefaultRequestContentType(restful.MIME_JSON)
 | 
			
		||||
func DefaultRequestContentType(mime string) {
 | 
			
		||||
	defaultRequestContentType = mime
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// PathParameter accesses the Path parameter value by its name
 | 
			
		||||
func (r *Request) PathParameter(name string) string {
 | 
			
		||||
	return r.pathParameters[name]
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// PathParameters accesses the Path parameter values
 | 
			
		||||
func (r *Request) PathParameters() map[string]string {
 | 
			
		||||
	return r.pathParameters
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// QueryParameter returns the (first) Query parameter value by its name
 | 
			
		||||
func (r *Request) QueryParameter(name string) string {
 | 
			
		||||
	return r.Request.FormValue(name)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// QueryParameters returns the all the query parameters values by name
 | 
			
		||||
func (r *Request) QueryParameters(name string) []string {
 | 
			
		||||
	return r.Request.URL.Query()[name]
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// BodyParameter parses the body of the request (once for typically a POST or a PUT) and returns the value of the given name or an error.
 | 
			
		||||
func (r *Request) BodyParameter(name string) (string, error) {
 | 
			
		||||
	err := r.Request.ParseForm()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return "", err
 | 
			
		||||
	}
 | 
			
		||||
	return r.Request.PostFormValue(name), nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// HeaderParameter returns the HTTP Header value of a Header name or empty if missing
 | 
			
		||||
func (r *Request) HeaderParameter(name string) string {
 | 
			
		||||
	return r.Request.Header.Get(name)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ReadEntity checks the Accept header and reads the content into the entityPointer.
 | 
			
		||||
func (r *Request) ReadEntity(entityPointer interface{}) (err error) {
 | 
			
		||||
	contentType := r.Request.Header.Get(HEADER_ContentType)
 | 
			
		||||
	contentEncoding := r.Request.Header.Get(HEADER_ContentEncoding)
 | 
			
		||||
 | 
			
		||||
	// check if the request body needs decompression
 | 
			
		||||
	if ENCODING_GZIP == contentEncoding {
 | 
			
		||||
		gzipReader := currentCompressorProvider.AcquireGzipReader()
 | 
			
		||||
		defer currentCompressorProvider.ReleaseGzipReader(gzipReader)
 | 
			
		||||
		gzipReader.Reset(r.Request.Body)
 | 
			
		||||
		r.Request.Body = gzipReader
 | 
			
		||||
	} else if ENCODING_DEFLATE == contentEncoding {
 | 
			
		||||
		zlibReader, err := zlib.NewReader(r.Request.Body)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
		r.Request.Body = zlibReader
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// lookup the EntityReader, use defaultRequestContentType if needed and provided
 | 
			
		||||
	entityReader, ok := entityAccessRegistry.accessorAt(contentType)
 | 
			
		||||
	if !ok {
 | 
			
		||||
		if len(defaultRequestContentType) != 0 {
 | 
			
		||||
			entityReader, ok = entityAccessRegistry.accessorAt(defaultRequestContentType)
 | 
			
		||||
		}
 | 
			
		||||
		if !ok {
 | 
			
		||||
			return NewError(http.StatusBadRequest, "Unable to unmarshal content of type:"+contentType)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return entityReader.Read(r, entityPointer)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// SetAttribute adds or replaces the attribute with the given value.
 | 
			
		||||
func (r *Request) SetAttribute(name string, value interface{}) {
 | 
			
		||||
	r.attributes[name] = value
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Attribute returns the value associated to the given name. Returns nil if absent.
 | 
			
		||||
func (r Request) Attribute(name string) interface{} {
 | 
			
		||||
	return r.attributes[name]
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// SelectedRoutePath root path + route path that matched the request, e.g. /meetings/{id}/attendees
 | 
			
		||||
// If no route was matched then return an empty string.
 | 
			
		||||
func (r Request) SelectedRoutePath() string {
 | 
			
		||||
	if r.selectedRoute == nil {
 | 
			
		||||
		return ""
 | 
			
		||||
	}
 | 
			
		||||
	// skip creating an accessor
 | 
			
		||||
	return r.selectedRoute.Path
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// SelectedRoute returns a reader to access the selected Route by the container
 | 
			
		||||
// Returns nil if no route was matched.
 | 
			
		||||
func (r Request) SelectedRoute() RouteReader {
 | 
			
		||||
	if r.selectedRoute == nil {
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
	return routeAccessor{route: r.selectedRoute}
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										256
									
								
								vendor/github.com/emicklei/go-restful/v3/response.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										256
									
								
								vendor/github.com/emicklei/go-restful/v3/response.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,256 @@
 | 
			
		||||
package restful
 | 
			
		||||
 | 
			
		||||
// Copyright 2013 Ernest Micklei. All rights reserved.
 | 
			
		||||
// Use of this source code is governed by a license
 | 
			
		||||
// that can be found in the LICENSE file.
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"bufio"
 | 
			
		||||
	"errors"
 | 
			
		||||
	"net"
 | 
			
		||||
	"net/http"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// DefaultResponseMimeType is DEPRECATED, use DefaultResponseContentType(mime)
 | 
			
		||||
var DefaultResponseMimeType string
 | 
			
		||||
 | 
			
		||||
//PrettyPrintResponses controls the indentation feature of XML and JSON serialization
 | 
			
		||||
var PrettyPrintResponses = true
 | 
			
		||||
 | 
			
		||||
// Response is a wrapper on the actual http ResponseWriter
 | 
			
		||||
// It provides several convenience methods to prepare and write response content.
 | 
			
		||||
type Response struct {
 | 
			
		||||
	http.ResponseWriter
 | 
			
		||||
	requestAccept string        // mime-type what the Http Request says it wants to receive
 | 
			
		||||
	routeProduces []string      // mime-types what the Route says it can produce
 | 
			
		||||
	statusCode    int           // HTTP status code that has been written explicitly (if zero then net/http has written 200)
 | 
			
		||||
	contentLength int           // number of bytes written for the response body
 | 
			
		||||
	prettyPrint   bool          // controls the indentation feature of XML and JSON serialization. It is initialized using var PrettyPrintResponses.
 | 
			
		||||
	err           error         // err property is kept when WriteError is called
 | 
			
		||||
	hijacker      http.Hijacker // if underlying ResponseWriter supports it
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// NewResponse creates a new response based on a http ResponseWriter.
 | 
			
		||||
func NewResponse(httpWriter http.ResponseWriter) *Response {
 | 
			
		||||
	hijacker, _ := httpWriter.(http.Hijacker)
 | 
			
		||||
	return &Response{ResponseWriter: httpWriter, routeProduces: []string{}, statusCode: http.StatusOK, prettyPrint: PrettyPrintResponses, hijacker: hijacker}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// DefaultResponseContentType set a default.
 | 
			
		||||
// If Accept header matching fails, fall back to this type.
 | 
			
		||||
// Valid values are restful.MIME_JSON and restful.MIME_XML
 | 
			
		||||
// Example:
 | 
			
		||||
// 	restful.DefaultResponseContentType(restful.MIME_JSON)
 | 
			
		||||
func DefaultResponseContentType(mime string) {
 | 
			
		||||
	DefaultResponseMimeType = mime
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// InternalServerError writes the StatusInternalServerError header.
 | 
			
		||||
// DEPRECATED, use WriteErrorString(http.StatusInternalServerError,reason)
 | 
			
		||||
func (r Response) InternalServerError() Response {
 | 
			
		||||
	r.WriteHeader(http.StatusInternalServerError)
 | 
			
		||||
	return r
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Hijack implements the http.Hijacker interface.  This expands
 | 
			
		||||
// the Response to fulfill http.Hijacker if the underlying
 | 
			
		||||
// http.ResponseWriter supports it.
 | 
			
		||||
func (r *Response) Hijack() (net.Conn, *bufio.ReadWriter, error) {
 | 
			
		||||
	if r.hijacker == nil {
 | 
			
		||||
		return nil, nil, errors.New("http.Hijacker not implemented by underlying http.ResponseWriter")
 | 
			
		||||
	}
 | 
			
		||||
	return r.hijacker.Hijack()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// PrettyPrint changes whether this response must produce pretty (line-by-line, indented) JSON or XML output.
 | 
			
		||||
func (r *Response) PrettyPrint(bePretty bool) {
 | 
			
		||||
	r.prettyPrint = bePretty
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// AddHeader is a shortcut for .Header().Add(header,value)
 | 
			
		||||
func (r Response) AddHeader(header string, value string) Response {
 | 
			
		||||
	r.Header().Add(header, value)
 | 
			
		||||
	return r
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// SetRequestAccepts tells the response what Mime-type(s) the HTTP request said it wants to accept. Exposed for testing.
 | 
			
		||||
func (r *Response) SetRequestAccepts(mime string) {
 | 
			
		||||
	r.requestAccept = mime
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// EntityWriter returns the registered EntityWriter that the entity (requested resource)
 | 
			
		||||
// can write according to what the request wants (Accept) and what the Route can produce or what the restful defaults say.
 | 
			
		||||
// If called before WriteEntity and WriteHeader then a false return value can be used to write a 406: Not Acceptable.
 | 
			
		||||
func (r *Response) EntityWriter() (EntityReaderWriter, bool) {
 | 
			
		||||
	sorted := sortedMimes(r.requestAccept)
 | 
			
		||||
	for _, eachAccept := range sorted {
 | 
			
		||||
		for _, eachProduce := range r.routeProduces {
 | 
			
		||||
			if eachProduce == eachAccept.media {
 | 
			
		||||
				if w, ok := entityAccessRegistry.accessorAt(eachAccept.media); ok {
 | 
			
		||||
					return w, true
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		if eachAccept.media == "*/*" {
 | 
			
		||||
			for _, each := range r.routeProduces {
 | 
			
		||||
				if w, ok := entityAccessRegistry.accessorAt(each); ok {
 | 
			
		||||
					return w, true
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	// if requestAccept is empty
 | 
			
		||||
	writer, ok := entityAccessRegistry.accessorAt(r.requestAccept)
 | 
			
		||||
	if !ok {
 | 
			
		||||
		// if not registered then fallback to the defaults (if set)
 | 
			
		||||
		if DefaultResponseMimeType == MIME_JSON {
 | 
			
		||||
			return entityAccessRegistry.accessorAt(MIME_JSON)
 | 
			
		||||
		}
 | 
			
		||||
		if DefaultResponseMimeType == MIME_XML {
 | 
			
		||||
			return entityAccessRegistry.accessorAt(MIME_XML)
 | 
			
		||||
		}
 | 
			
		||||
		// Fallback to whatever the route says it can produce.
 | 
			
		||||
		// https://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html
 | 
			
		||||
		for _, each := range r.routeProduces {
 | 
			
		||||
			if w, ok := entityAccessRegistry.accessorAt(each); ok {
 | 
			
		||||
				return w, true
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		if trace {
 | 
			
		||||
			traceLogger.Printf("no registered EntityReaderWriter found for %s", r.requestAccept)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return writer, ok
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// WriteEntity calls WriteHeaderAndEntity with Http Status OK (200)
 | 
			
		||||
func (r *Response) WriteEntity(value interface{}) error {
 | 
			
		||||
	return r.WriteHeaderAndEntity(http.StatusOK, value)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// WriteHeaderAndEntity marshals the value using the representation denoted by the Accept Header and the registered EntityWriters.
 | 
			
		||||
// If no Accept header is specified (or */*) then respond with the Content-Type as specified by the first in the Route.Produces.
 | 
			
		||||
// If an Accept header is specified then respond with the Content-Type as specified by the first in the Route.Produces that is matched with the Accept header.
 | 
			
		||||
// If the value is nil then no response is send except for the Http status. You may want to call WriteHeader(http.StatusNotFound) instead.
 | 
			
		||||
// If there is no writer available that can represent the value in the requested MIME type then Http Status NotAcceptable is written.
 | 
			
		||||
// Current implementation ignores any q-parameters in the Accept Header.
 | 
			
		||||
// Returns an error if the value could not be written on the response.
 | 
			
		||||
func (r *Response) WriteHeaderAndEntity(status int, value interface{}) error {
 | 
			
		||||
	writer, ok := r.EntityWriter()
 | 
			
		||||
	if !ok {
 | 
			
		||||
		r.WriteHeader(http.StatusNotAcceptable)
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
	return writer.Write(r, status, value)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// WriteAsXml is a convenience method for writing a value in xml (requires Xml tags on the value)
 | 
			
		||||
// It uses the standard encoding/xml package for marshalling the value ; not using a registered EntityReaderWriter.
 | 
			
		||||
func (r *Response) WriteAsXml(value interface{}) error {
 | 
			
		||||
	return writeXML(r, http.StatusOK, MIME_XML, value)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// WriteHeaderAndXml is a convenience method for writing a status and value in xml (requires Xml tags on the value)
 | 
			
		||||
// It uses the standard encoding/xml package for marshalling the value ; not using a registered EntityReaderWriter.
 | 
			
		||||
func (r *Response) WriteHeaderAndXml(status int, value interface{}) error {
 | 
			
		||||
	return writeXML(r, status, MIME_XML, value)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// WriteAsJson is a convenience method for writing a value in json.
 | 
			
		||||
// It uses the standard encoding/json package for marshalling the value ; not using a registered EntityReaderWriter.
 | 
			
		||||
func (r *Response) WriteAsJson(value interface{}) error {
 | 
			
		||||
	return writeJSON(r, http.StatusOK, MIME_JSON, value)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// WriteJson is a convenience method for writing a value in Json with a given Content-Type.
 | 
			
		||||
// It uses the standard encoding/json package for marshalling the value ; not using a registered EntityReaderWriter.
 | 
			
		||||
func (r *Response) WriteJson(value interface{}, contentType string) error {
 | 
			
		||||
	return writeJSON(r, http.StatusOK, contentType, value)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// WriteHeaderAndJson is a convenience method for writing the status and a value in Json with a given Content-Type.
 | 
			
		||||
// It uses the standard encoding/json package for marshalling the value ; not using a registered EntityReaderWriter.
 | 
			
		||||
func (r *Response) WriteHeaderAndJson(status int, value interface{}, contentType string) error {
 | 
			
		||||
	return writeJSON(r, status, contentType, value)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// WriteError writes the http status and the error string on the response. err can be nil.
 | 
			
		||||
// Return an error if writing was not successful.
 | 
			
		||||
func (r *Response) WriteError(httpStatus int, err error) (writeErr error) {
 | 
			
		||||
	r.err = err
 | 
			
		||||
	if err == nil {
 | 
			
		||||
		writeErr = r.WriteErrorString(httpStatus, "")
 | 
			
		||||
	} else {
 | 
			
		||||
		writeErr = r.WriteErrorString(httpStatus, err.Error())
 | 
			
		||||
	}
 | 
			
		||||
	return writeErr
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// WriteServiceError is a convenience method for a responding with a status and a ServiceError
 | 
			
		||||
func (r *Response) WriteServiceError(httpStatus int, err ServiceError) error {
 | 
			
		||||
	r.err = err
 | 
			
		||||
	return r.WriteHeaderAndEntity(httpStatus, err)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// WriteErrorString is a convenience method for an error status with the actual error
 | 
			
		||||
func (r *Response) WriteErrorString(httpStatus int, errorReason string) error {
 | 
			
		||||
	if r.err == nil {
 | 
			
		||||
		// if not called from WriteError
 | 
			
		||||
		r.err = errors.New(errorReason)
 | 
			
		||||
	}
 | 
			
		||||
	r.WriteHeader(httpStatus)
 | 
			
		||||
	if _, err := r.Write([]byte(errorReason)); err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Flush implements http.Flusher interface, which sends any buffered data to the client.
 | 
			
		||||
func (r *Response) Flush() {
 | 
			
		||||
	if f, ok := r.ResponseWriter.(http.Flusher); ok {
 | 
			
		||||
		f.Flush()
 | 
			
		||||
	} else if trace {
 | 
			
		||||
		traceLogger.Printf("ResponseWriter %v doesn't support Flush", r)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// WriteHeader is overridden to remember the Status Code that has been written.
 | 
			
		||||
// Changes to the Header of the response have no effect after this.
 | 
			
		||||
func (r *Response) WriteHeader(httpStatus int) {
 | 
			
		||||
	r.statusCode = httpStatus
 | 
			
		||||
	r.ResponseWriter.WriteHeader(httpStatus)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// StatusCode returns the code that has been written using WriteHeader.
 | 
			
		||||
func (r Response) StatusCode() int {
 | 
			
		||||
	if 0 == r.statusCode {
 | 
			
		||||
		// no status code has been written yet; assume OK
 | 
			
		||||
		return http.StatusOK
 | 
			
		||||
	}
 | 
			
		||||
	return r.statusCode
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Write writes the data to the connection as part of an HTTP reply.
 | 
			
		||||
// Write is part of http.ResponseWriter interface.
 | 
			
		||||
func (r *Response) Write(bytes []byte) (int, error) {
 | 
			
		||||
	written, err := r.ResponseWriter.Write(bytes)
 | 
			
		||||
	r.contentLength += written
 | 
			
		||||
	return written, err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ContentLength returns the number of bytes written for the response content.
 | 
			
		||||
// Note that this value is only correct if all data is written through the Response using its Write* methods.
 | 
			
		||||
// Data written directly using the underlying http.ResponseWriter is not accounted for.
 | 
			
		||||
func (r Response) ContentLength() int {
 | 
			
		||||
	return r.contentLength
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// CloseNotify is part of http.CloseNotifier interface
 | 
			
		||||
func (r Response) CloseNotify() <-chan bool {
 | 
			
		||||
	return r.ResponseWriter.(http.CloseNotifier).CloseNotify()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Error returns the err created by WriteError
 | 
			
		||||
func (r Response) Error() error {
 | 
			
		||||
	return r.err
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										178
									
								
								vendor/github.com/emicklei/go-restful/v3/route.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										178
									
								
								vendor/github.com/emicklei/go-restful/v3/route.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,178 @@
 | 
			
		||||
package restful
 | 
			
		||||
 | 
			
		||||
// Copyright 2013 Ernest Micklei. All rights reserved.
 | 
			
		||||
// Use of this source code is governed by a license
 | 
			
		||||
// that can be found in the LICENSE file.
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"net/http"
 | 
			
		||||
	"strings"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// RouteFunction declares the signature of a function that can be bound to a Route.
 | 
			
		||||
type RouteFunction func(*Request, *Response)
 | 
			
		||||
 | 
			
		||||
// RouteSelectionConditionFunction declares the signature of a function that
 | 
			
		||||
// can be used to add extra conditional logic when selecting whether the route
 | 
			
		||||
// matches the HTTP request.
 | 
			
		||||
type RouteSelectionConditionFunction func(httpRequest *http.Request) bool
 | 
			
		||||
 | 
			
		||||
// Route binds a HTTP Method,Path,Consumes combination to a RouteFunction.
 | 
			
		||||
type Route struct {
 | 
			
		||||
	ExtensionProperties
 | 
			
		||||
	Method   string
 | 
			
		||||
	Produces []string
 | 
			
		||||
	Consumes []string
 | 
			
		||||
	Path     string // webservice root path + described path
 | 
			
		||||
	Function RouteFunction
 | 
			
		||||
	Filters  []FilterFunction
 | 
			
		||||
	If       []RouteSelectionConditionFunction
 | 
			
		||||
 | 
			
		||||
	// cached values for dispatching
 | 
			
		||||
	relativePath string
 | 
			
		||||
	pathParts    []string
 | 
			
		||||
	pathExpr     *pathExpression // cached compilation of relativePath as RegExp
 | 
			
		||||
 | 
			
		||||
	// documentation
 | 
			
		||||
	Doc                     string
 | 
			
		||||
	Notes                   string
 | 
			
		||||
	Operation               string
 | 
			
		||||
	ParameterDocs           []*Parameter
 | 
			
		||||
	ResponseErrors          map[int]ResponseError
 | 
			
		||||
	DefaultResponse         *ResponseError
 | 
			
		||||
	ReadSample, WriteSample interface{} // structs that model an example request or response payload
 | 
			
		||||
 | 
			
		||||
	// Extra information used to store custom information about the route.
 | 
			
		||||
	Metadata map[string]interface{}
 | 
			
		||||
 | 
			
		||||
	// marks a route as deprecated
 | 
			
		||||
	Deprecated bool
 | 
			
		||||
 | 
			
		||||
	//Overrides the container.contentEncodingEnabled
 | 
			
		||||
	contentEncodingEnabled *bool
 | 
			
		||||
 | 
			
		||||
	// indicate route path has custom verb
 | 
			
		||||
	hasCustomVerb bool
 | 
			
		||||
 | 
			
		||||
	// if a request does not include a content-type header then
 | 
			
		||||
	// depending on the method, it may return a 415 Unsupported Media
 | 
			
		||||
	// Must have uppercase HTTP Method names such as GET,HEAD,OPTIONS,...
 | 
			
		||||
	allowedMethodsWithoutContentType []string
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Initialize for Route
 | 
			
		||||
func (r *Route) postBuild() {
 | 
			
		||||
	r.pathParts = tokenizePath(r.Path)
 | 
			
		||||
	r.hasCustomVerb = hasCustomVerb(r.Path)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Create Request and Response from their http versions
 | 
			
		||||
func (r *Route) wrapRequestResponse(httpWriter http.ResponseWriter, httpRequest *http.Request, pathParams map[string]string) (*Request, *Response) {
 | 
			
		||||
	wrappedRequest := NewRequest(httpRequest)
 | 
			
		||||
	wrappedRequest.pathParameters = pathParams
 | 
			
		||||
	wrappedRequest.selectedRoute = r
 | 
			
		||||
	wrappedResponse := NewResponse(httpWriter)
 | 
			
		||||
	wrappedResponse.requestAccept = httpRequest.Header.Get(HEADER_Accept)
 | 
			
		||||
	wrappedResponse.routeProduces = r.Produces
 | 
			
		||||
	return wrappedRequest, wrappedResponse
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func stringTrimSpaceCutset(r rune) bool {
 | 
			
		||||
	return r == ' '
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Return whether the mimeType matches to what this Route can produce.
 | 
			
		||||
func (r Route) matchesAccept(mimeTypesWithQuality string) bool {
 | 
			
		||||
	remaining := mimeTypesWithQuality
 | 
			
		||||
	for {
 | 
			
		||||
		var mimeType string
 | 
			
		||||
		if end := strings.Index(remaining, ","); end == -1 {
 | 
			
		||||
			mimeType, remaining = remaining, ""
 | 
			
		||||
		} else {
 | 
			
		||||
			mimeType, remaining = remaining[:end], remaining[end+1:]
 | 
			
		||||
		}
 | 
			
		||||
		if quality := strings.Index(mimeType, ";"); quality != -1 {
 | 
			
		||||
			mimeType = mimeType[:quality]
 | 
			
		||||
		}
 | 
			
		||||
		mimeType = strings.TrimFunc(mimeType, stringTrimSpaceCutset)
 | 
			
		||||
		if mimeType == "*/*" {
 | 
			
		||||
			return true
 | 
			
		||||
		}
 | 
			
		||||
		for _, producibleType := range r.Produces {
 | 
			
		||||
			if producibleType == "*/*" || producibleType == mimeType {
 | 
			
		||||
				return true
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		if len(remaining) == 0 {
 | 
			
		||||
			return false
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Return whether this Route can consume content with a type specified by mimeTypes (can be empty).
 | 
			
		||||
func (r Route) matchesContentType(mimeTypes string) bool {
 | 
			
		||||
 | 
			
		||||
	if len(r.Consumes) == 0 {
 | 
			
		||||
		// did not specify what it can consume ;  any media type (“*/*”) is assumed
 | 
			
		||||
		return true
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if len(mimeTypes) == 0 {
 | 
			
		||||
		// idempotent methods with (most-likely or guaranteed) empty content match missing Content-Type
 | 
			
		||||
		m := r.Method
 | 
			
		||||
		// if route specifies less or non-idempotent methods then use that
 | 
			
		||||
		if len(r.allowedMethodsWithoutContentType) > 0 {
 | 
			
		||||
			for _, each := range r.allowedMethodsWithoutContentType {
 | 
			
		||||
				if m == each {
 | 
			
		||||
					return true
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		} else {
 | 
			
		||||
			if m == "GET" || m == "HEAD" || m == "OPTIONS" || m == "DELETE" || m == "TRACE" {
 | 
			
		||||
				return true
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		// proceed with default
 | 
			
		||||
		mimeTypes = MIME_OCTET
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	remaining := mimeTypes
 | 
			
		||||
	for {
 | 
			
		||||
		var mimeType string
 | 
			
		||||
		if end := strings.Index(remaining, ","); end == -1 {
 | 
			
		||||
			mimeType, remaining = remaining, ""
 | 
			
		||||
		} else {
 | 
			
		||||
			mimeType, remaining = remaining[:end], remaining[end+1:]
 | 
			
		||||
		}
 | 
			
		||||
		if quality := strings.Index(mimeType, ";"); quality != -1 {
 | 
			
		||||
			mimeType = mimeType[:quality]
 | 
			
		||||
		}
 | 
			
		||||
		mimeType = strings.TrimFunc(mimeType, stringTrimSpaceCutset)
 | 
			
		||||
		for _, consumeableType := range r.Consumes {
 | 
			
		||||
			if consumeableType == "*/*" || consumeableType == mimeType {
 | 
			
		||||
				return true
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		if len(remaining) == 0 {
 | 
			
		||||
			return false
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Tokenize an URL path using the slash separator ; the result does not have empty tokens
 | 
			
		||||
func tokenizePath(path string) []string {
 | 
			
		||||
	if "/" == path {
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
	return strings.Split(strings.Trim(path, "/"), "/")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// for debugging
 | 
			
		||||
func (r *Route) String() string {
 | 
			
		||||
	return r.Method + " " + r.Path
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// EnableContentEncoding (default=false) allows for GZIP or DEFLATE encoding of responses. Overrides the container.contentEncodingEnabled value.
 | 
			
		||||
func (r *Route) EnableContentEncoding(enabled bool) {
 | 
			
		||||
	r.contentEncodingEnabled = &enabled
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										376
									
								
								vendor/github.com/emicklei/go-restful/v3/route_builder.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										376
									
								
								vendor/github.com/emicklei/go-restful/v3/route_builder.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,376 @@
 | 
			
		||||
package restful
 | 
			
		||||
 | 
			
		||||
// Copyright 2013 Ernest Micklei. All rights reserved.
 | 
			
		||||
// Use of this source code is governed by a license
 | 
			
		||||
// that can be found in the LICENSE file.
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"os"
 | 
			
		||||
	"reflect"
 | 
			
		||||
	"runtime"
 | 
			
		||||
	"strings"
 | 
			
		||||
	"sync/atomic"
 | 
			
		||||
 | 
			
		||||
	"github.com/emicklei/go-restful/v3/log"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// RouteBuilder is a helper to construct Routes.
 | 
			
		||||
type RouteBuilder struct {
 | 
			
		||||
	rootPath                         string
 | 
			
		||||
	currentPath                      string
 | 
			
		||||
	produces                         []string
 | 
			
		||||
	consumes                         []string
 | 
			
		||||
	httpMethod                       string        // required
 | 
			
		||||
	function                         RouteFunction // required
 | 
			
		||||
	filters                          []FilterFunction
 | 
			
		||||
	conditions                       []RouteSelectionConditionFunction
 | 
			
		||||
	allowedMethodsWithoutContentType []string // see Route
 | 
			
		||||
 | 
			
		||||
	typeNameHandleFunc TypeNameHandleFunction // required
 | 
			
		||||
 | 
			
		||||
	// documentation
 | 
			
		||||
	doc                     string
 | 
			
		||||
	notes                   string
 | 
			
		||||
	operation               string
 | 
			
		||||
	readSample, writeSample interface{}
 | 
			
		||||
	parameters              []*Parameter
 | 
			
		||||
	errorMap                map[int]ResponseError
 | 
			
		||||
	defaultResponse         *ResponseError
 | 
			
		||||
	metadata                map[string]interface{}
 | 
			
		||||
	extensions              map[string]interface{}
 | 
			
		||||
	deprecated              bool
 | 
			
		||||
	contentEncodingEnabled  *bool
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Do evaluates each argument with the RouteBuilder itself.
 | 
			
		||||
// This allows you to follow DRY principles without breaking the fluent programming style.
 | 
			
		||||
// Example:
 | 
			
		||||
// 		ws.Route(ws.DELETE("/{name}").To(t.deletePerson).Do(Returns200, Returns500))
 | 
			
		||||
//
 | 
			
		||||
//		func Returns500(b *RouteBuilder) {
 | 
			
		||||
//			b.Returns(500, "Internal Server Error", restful.ServiceError{})
 | 
			
		||||
//		}
 | 
			
		||||
func (b *RouteBuilder) Do(oneArgBlocks ...func(*RouteBuilder)) *RouteBuilder {
 | 
			
		||||
	for _, each := range oneArgBlocks {
 | 
			
		||||
		each(b)
 | 
			
		||||
	}
 | 
			
		||||
	return b
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// To bind the route to a function.
 | 
			
		||||
// If this route is matched with the incoming Http Request then call this function with the *Request,*Response pair. Required.
 | 
			
		||||
func (b *RouteBuilder) To(function RouteFunction) *RouteBuilder {
 | 
			
		||||
	b.function = function
 | 
			
		||||
	return b
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Method specifies what HTTP method to match. Required.
 | 
			
		||||
func (b *RouteBuilder) Method(method string) *RouteBuilder {
 | 
			
		||||
	b.httpMethod = method
 | 
			
		||||
	return b
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Produces specifies what MIME types can be produced ; the matched one will appear in the Content-Type Http header.
 | 
			
		||||
func (b *RouteBuilder) Produces(mimeTypes ...string) *RouteBuilder {
 | 
			
		||||
	b.produces = mimeTypes
 | 
			
		||||
	return b
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Consumes specifies what MIME types can be consumes ; the Accept Http header must matched any of these
 | 
			
		||||
func (b *RouteBuilder) Consumes(mimeTypes ...string) *RouteBuilder {
 | 
			
		||||
	b.consumes = mimeTypes
 | 
			
		||||
	return b
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Path specifies the relative (w.r.t WebService root path) URL path to match. Default is "/".
 | 
			
		||||
func (b *RouteBuilder) Path(subPath string) *RouteBuilder {
 | 
			
		||||
	b.currentPath = subPath
 | 
			
		||||
	return b
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Doc tells what this route is all about. Optional.
 | 
			
		||||
func (b *RouteBuilder) Doc(documentation string) *RouteBuilder {
 | 
			
		||||
	b.doc = documentation
 | 
			
		||||
	return b
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Notes is 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{}, optionalDescription ...string) *RouteBuilder {
 | 
			
		||||
	fn := b.typeNameHandleFunc
 | 
			
		||||
	if fn == nil {
 | 
			
		||||
		fn = reflectTypeName
 | 
			
		||||
	}
 | 
			
		||||
	typeAsName := fn(sample)
 | 
			
		||||
	description := ""
 | 
			
		||||
	if len(optionalDescription) > 0 {
 | 
			
		||||
		description = optionalDescription[0]
 | 
			
		||||
	}
 | 
			
		||||
	b.readSample = sample
 | 
			
		||||
	bodyParameter := &Parameter{&ParameterData{Name: "body", Description: description}}
 | 
			
		||||
	bodyParameter.beBody()
 | 
			
		||||
	bodyParameter.Required(true)
 | 
			
		||||
	bodyParameter.DataType(typeAsName)
 | 
			
		||||
	b.Param(bodyParameter)
 | 
			
		||||
	return b
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ParameterNamed returns a Parameter already known to the RouteBuilder. Returns nil if not.
 | 
			
		||||
// Use this to modify or extend information for the Parameter (through its Data()).
 | 
			
		||||
func (b RouteBuilder) ParameterNamed(name string) (p *Parameter) {
 | 
			
		||||
	for _, each := range b.parameters {
 | 
			
		||||
		if each.Data().Name == name {
 | 
			
		||||
			return each
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return p
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Writes tells what resource type will be written as the response payload. Optional.
 | 
			
		||||
func (b *RouteBuilder) Writes(sample interface{}) *RouteBuilder {
 | 
			
		||||
	b.writeSample = sample
 | 
			
		||||
	return b
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Param allows you to document the parameters of the Route. It adds a new Parameter (does not check for duplicates).
 | 
			
		||||
func (b *RouteBuilder) Param(parameter *Parameter) *RouteBuilder {
 | 
			
		||||
	if b.parameters == nil {
 | 
			
		||||
		b.parameters = []*Parameter{}
 | 
			
		||||
	}
 | 
			
		||||
	b.parameters = append(b.parameters, parameter)
 | 
			
		||||
	return b
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Operation allows you to document what the actual method/function call is of the Route.
 | 
			
		||||
// Unless called, the operation name is derived from the RouteFunction set using To(..).
 | 
			
		||||
func (b *RouteBuilder) Operation(name string) *RouteBuilder {
 | 
			
		||||
	b.operation = name
 | 
			
		||||
	return b
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ReturnsError is deprecated, use Returns instead.
 | 
			
		||||
func (b *RouteBuilder) ReturnsError(code int, message string, model interface{}) *RouteBuilder {
 | 
			
		||||
	log.Print("ReturnsError is deprecated, use Returns instead.")
 | 
			
		||||
	return b.Returns(code, message, model)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Returns allows you to document what responses (errors or regular) can be expected.
 | 
			
		||||
// The model parameter is optional ; either pass a struct instance or use nil if not applicable.
 | 
			
		||||
func (b *RouteBuilder) Returns(code int, message string, model interface{}) *RouteBuilder {
 | 
			
		||||
	err := ResponseError{
 | 
			
		||||
		Code:      code,
 | 
			
		||||
		Message:   message,
 | 
			
		||||
		Model:     model,
 | 
			
		||||
		IsDefault: false, // this field is deprecated, use default response instead.
 | 
			
		||||
	}
 | 
			
		||||
	// lazy init because there is no NewRouteBuilder (yet)
 | 
			
		||||
	if b.errorMap == nil {
 | 
			
		||||
		b.errorMap = map[int]ResponseError{}
 | 
			
		||||
	}
 | 
			
		||||
	b.errorMap[code] = err
 | 
			
		||||
	return b
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ReturnsWithHeaders is similar to Returns, but can specify response headers
 | 
			
		||||
func (b *RouteBuilder) ReturnsWithHeaders(code int, message string, model interface{}, headers map[string]Header) *RouteBuilder {
 | 
			
		||||
	b.Returns(code, message, model)
 | 
			
		||||
	err := b.errorMap[code]
 | 
			
		||||
	err.Headers = headers
 | 
			
		||||
	b.errorMap[code] = err
 | 
			
		||||
	return b
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// DefaultReturns is a special Returns call that sets the default of the response.
 | 
			
		||||
func (b *RouteBuilder) DefaultReturns(message string, model interface{}) *RouteBuilder {
 | 
			
		||||
	b.defaultResponse = &ResponseError{
 | 
			
		||||
		Message: message,
 | 
			
		||||
		Model:   model,
 | 
			
		||||
	}
 | 
			
		||||
	return b
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Metadata adds or updates a key=value pair to the metadata map.
 | 
			
		||||
func (b *RouteBuilder) Metadata(key string, value interface{}) *RouteBuilder {
 | 
			
		||||
	if b.metadata == nil {
 | 
			
		||||
		b.metadata = map[string]interface{}{}
 | 
			
		||||
	}
 | 
			
		||||
	b.metadata[key] = value
 | 
			
		||||
	return b
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// AddExtension adds or updates a key=value pair to the extensions map.
 | 
			
		||||
func (b *RouteBuilder) AddExtension(key string, value interface{}) *RouteBuilder {
 | 
			
		||||
	if b.extensions == nil {
 | 
			
		||||
		b.extensions = map[string]interface{}{}
 | 
			
		||||
	}
 | 
			
		||||
	b.extensions[key] = value
 | 
			
		||||
	return b
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Deprecate sets the value of deprecated to true.  Deprecated routes have a special UI treatment to warn against use
 | 
			
		||||
func (b *RouteBuilder) Deprecate() *RouteBuilder {
 | 
			
		||||
	b.deprecated = true
 | 
			
		||||
	return b
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// AllowedMethodsWithoutContentType overrides the default list GET,HEAD,OPTIONS,DELETE,TRACE
 | 
			
		||||
// If a request does not include a content-type header then
 | 
			
		||||
// depending on the method, it may return a 415 Unsupported Media.
 | 
			
		||||
// Must have uppercase HTTP Method names such as GET,HEAD,OPTIONS,...
 | 
			
		||||
func (b *RouteBuilder) AllowedMethodsWithoutContentType(methods []string) *RouteBuilder {
 | 
			
		||||
	b.allowedMethodsWithoutContentType = methods
 | 
			
		||||
	return b
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ResponseError represents a response; not necessarily an error.
 | 
			
		||||
type ResponseError struct {
 | 
			
		||||
	ExtensionProperties
 | 
			
		||||
	Code      int
 | 
			
		||||
	Message   string
 | 
			
		||||
	Model     interface{}
 | 
			
		||||
	Headers   map[string]Header
 | 
			
		||||
	IsDefault bool
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Header describes a header for a response of the API
 | 
			
		||||
//
 | 
			
		||||
// For more information: http://goo.gl/8us55a#headerObject
 | 
			
		||||
type Header struct {
 | 
			
		||||
	*Items
 | 
			
		||||
	Description string
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Items describe swagger simple schemas for headers
 | 
			
		||||
type Items struct {
 | 
			
		||||
	Type             string
 | 
			
		||||
	Format           string
 | 
			
		||||
	Items            *Items
 | 
			
		||||
	CollectionFormat string
 | 
			
		||||
	Default          interface{}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (b *RouteBuilder) servicePath(path string) *RouteBuilder {
 | 
			
		||||
	b.rootPath = path
 | 
			
		||||
	return b
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Filter appends a FilterFunction to the end of filters for this Route to build.
 | 
			
		||||
func (b *RouteBuilder) Filter(filter FilterFunction) *RouteBuilder {
 | 
			
		||||
	b.filters = append(b.filters, filter)
 | 
			
		||||
	return b
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// If sets a condition function that controls matching the Route based on custom logic.
 | 
			
		||||
// The condition function is provided the HTTP request and should return true if the route
 | 
			
		||||
// should be considered.
 | 
			
		||||
//
 | 
			
		||||
// Efficiency note: the condition function is called before checking the method, produces, and
 | 
			
		||||
// consumes criteria, so that the correct HTTP status code can be returned.
 | 
			
		||||
//
 | 
			
		||||
// Lifecycle note: no filter functions have been called prior to calling the condition function,
 | 
			
		||||
// so the condition function should not depend on any context that might be set up by container
 | 
			
		||||
// or route filters.
 | 
			
		||||
func (b *RouteBuilder) If(condition RouteSelectionConditionFunction) *RouteBuilder {
 | 
			
		||||
	b.conditions = append(b.conditions, condition)
 | 
			
		||||
	return b
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ContentEncodingEnabled allows you to override the Containers value for auto-compressing this route response.
 | 
			
		||||
func (b *RouteBuilder) ContentEncodingEnabled(enabled bool) *RouteBuilder {
 | 
			
		||||
	b.contentEncodingEnabled = &enabled
 | 
			
		||||
	return b
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// If no specific Route path then set to rootPath
 | 
			
		||||
// If no specific Produces then set to rootProduces
 | 
			
		||||
// If no specific Consumes then set to rootConsumes
 | 
			
		||||
func (b *RouteBuilder) copyDefaults(rootProduces, rootConsumes []string) {
 | 
			
		||||
	if len(b.produces) == 0 {
 | 
			
		||||
		b.produces = rootProduces
 | 
			
		||||
	}
 | 
			
		||||
	if len(b.consumes) == 0 {
 | 
			
		||||
		b.consumes = rootConsumes
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// typeNameHandler sets the function that will convert types to strings in the parameter
 | 
			
		||||
// and model definitions.
 | 
			
		||||
func (b *RouteBuilder) typeNameHandler(handler TypeNameHandleFunction) *RouteBuilder {
 | 
			
		||||
	b.typeNameHandleFunc = handler
 | 
			
		||||
	return b
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Build creates a new Route using the specification details collected by the RouteBuilder
 | 
			
		||||
func (b *RouteBuilder) Build() Route {
 | 
			
		||||
	pathExpr, err := newPathExpression(b.currentPath)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		log.Printf("Invalid path:%s because:%v", b.currentPath, err)
 | 
			
		||||
		os.Exit(1)
 | 
			
		||||
	}
 | 
			
		||||
	if b.function == nil {
 | 
			
		||||
		log.Printf("No function specified for route:" + b.currentPath)
 | 
			
		||||
		os.Exit(1)
 | 
			
		||||
	}
 | 
			
		||||
	operationName := b.operation
 | 
			
		||||
	if len(operationName) == 0 && b.function != nil {
 | 
			
		||||
		// extract from definition
 | 
			
		||||
		operationName = nameOfFunction(b.function)
 | 
			
		||||
	}
 | 
			
		||||
	route := Route{
 | 
			
		||||
		Method:                           b.httpMethod,
 | 
			
		||||
		Path:                             concatPath(b.rootPath, b.currentPath),
 | 
			
		||||
		Produces:                         b.produces,
 | 
			
		||||
		Consumes:                         b.consumes,
 | 
			
		||||
		Function:                         b.function,
 | 
			
		||||
		Filters:                          b.filters,
 | 
			
		||||
		If:                               b.conditions,
 | 
			
		||||
		relativePath:                     b.currentPath,
 | 
			
		||||
		pathExpr:                         pathExpr,
 | 
			
		||||
		Doc:                              b.doc,
 | 
			
		||||
		Notes:                            b.notes,
 | 
			
		||||
		Operation:                        operationName,
 | 
			
		||||
		ParameterDocs:                    b.parameters,
 | 
			
		||||
		ResponseErrors:                   b.errorMap,
 | 
			
		||||
		DefaultResponse:                  b.defaultResponse,
 | 
			
		||||
		ReadSample:                       b.readSample,
 | 
			
		||||
		WriteSample:                      b.writeSample,
 | 
			
		||||
		Metadata:                         b.metadata,
 | 
			
		||||
		Deprecated:                       b.deprecated,
 | 
			
		||||
		contentEncodingEnabled:           b.contentEncodingEnabled,
 | 
			
		||||
		allowedMethodsWithoutContentType: b.allowedMethodsWithoutContentType,
 | 
			
		||||
	}
 | 
			
		||||
	route.Extensions = b.extensions
 | 
			
		||||
	route.postBuild()
 | 
			
		||||
	return route
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func concatPath(path1, path2 string) string {
 | 
			
		||||
	return strings.TrimRight(path1, "/") + "/" + strings.TrimLeft(path2, "/")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
var anonymousFuncCount int32
 | 
			
		||||
 | 
			
		||||
// nameOfFunction returns the short name of the function f for documentation.
 | 
			
		||||
// It uses a runtime feature for debugging ; its value may change for later Go versions.
 | 
			
		||||
func nameOfFunction(f interface{}) string {
 | 
			
		||||
	fun := runtime.FuncForPC(reflect.ValueOf(f).Pointer())
 | 
			
		||||
	tokenized := strings.Split(fun.Name(), ".")
 | 
			
		||||
	last := tokenized[len(tokenized)-1]
 | 
			
		||||
	last = strings.TrimSuffix(last, ")·fm") // < Go 1.5
 | 
			
		||||
	last = strings.TrimSuffix(last, ")-fm") // Go 1.5
 | 
			
		||||
	last = strings.TrimSuffix(last, "·fm")  // < Go 1.5
 | 
			
		||||
	last = strings.TrimSuffix(last, "-fm")  // Go 1.5
 | 
			
		||||
	if last == "func1" {                    // this could mean conflicts in API docs
 | 
			
		||||
		val := atomic.AddInt32(&anonymousFuncCount, 1)
 | 
			
		||||
		last = "func" + fmt.Sprintf("%d", val)
 | 
			
		||||
		atomic.StoreInt32(&anonymousFuncCount, val)
 | 
			
		||||
	}
 | 
			
		||||
	return last
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										66
									
								
								vendor/github.com/emicklei/go-restful/v3/route_reader.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										66
									
								
								vendor/github.com/emicklei/go-restful/v3/route_reader.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,66 @@
 | 
			
		||||
package restful
 | 
			
		||||
 | 
			
		||||
// Copyright 2021 Ernest Micklei. All rights reserved.
 | 
			
		||||
// Use of this source code is governed by a license
 | 
			
		||||
// that can be found in the LICENSE file.
 | 
			
		||||
 | 
			
		||||
type RouteReader interface {
 | 
			
		||||
	Method() string
 | 
			
		||||
	Consumes() []string
 | 
			
		||||
	Path() string
 | 
			
		||||
	Doc() string
 | 
			
		||||
	Notes() string
 | 
			
		||||
	Operation() string
 | 
			
		||||
	ParameterDocs() []*Parameter
 | 
			
		||||
	// Returns a copy
 | 
			
		||||
	Metadata() map[string]interface{}
 | 
			
		||||
	Deprecated() bool
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type routeAccessor struct {
 | 
			
		||||
	route *Route
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (r routeAccessor) Method() string {
 | 
			
		||||
	return r.route.Method
 | 
			
		||||
}
 | 
			
		||||
func (r routeAccessor) Consumes() []string {
 | 
			
		||||
	return r.route.Consumes[:]
 | 
			
		||||
}
 | 
			
		||||
func (r routeAccessor) Path() string {
 | 
			
		||||
	return r.route.Path
 | 
			
		||||
}
 | 
			
		||||
func (r routeAccessor) Doc() string {
 | 
			
		||||
	return r.route.Doc
 | 
			
		||||
}
 | 
			
		||||
func (r routeAccessor) Notes() string {
 | 
			
		||||
	return r.route.Notes
 | 
			
		||||
}
 | 
			
		||||
func (r routeAccessor) Operation() string {
 | 
			
		||||
	return r.route.Operation
 | 
			
		||||
}
 | 
			
		||||
func (r routeAccessor) ParameterDocs() []*Parameter {
 | 
			
		||||
	return r.route.ParameterDocs[:]
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Returns a copy
 | 
			
		||||
func (r routeAccessor) Metadata() map[string]interface{} {
 | 
			
		||||
	return copyMap(r.route.Metadata)
 | 
			
		||||
}
 | 
			
		||||
func (r routeAccessor) Deprecated() bool {
 | 
			
		||||
	return r.route.Deprecated
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// https://stackoverflow.com/questions/23057785/how-to-copy-a-map
 | 
			
		||||
func copyMap(m map[string]interface{}) map[string]interface{} {
 | 
			
		||||
	cp := make(map[string]interface{})
 | 
			
		||||
	for k, v := range m {
 | 
			
		||||
		vm, ok := v.(map[string]interface{})
 | 
			
		||||
		if ok {
 | 
			
		||||
			cp[k] = copyMap(vm)
 | 
			
		||||
		} else {
 | 
			
		||||
			cp[k] = v
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return cp
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										20
									
								
								vendor/github.com/emicklei/go-restful/v3/router.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								vendor/github.com/emicklei/go-restful/v3/router.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,20 @@
 | 
			
		||||
package restful
 | 
			
		||||
 | 
			
		||||
// Copyright 2013 Ernest Micklei. All rights reserved.
 | 
			
		||||
// Use of this source code is governed by a license
 | 
			
		||||
// that can be found in the LICENSE file.
 | 
			
		||||
 | 
			
		||||
import "net/http"
 | 
			
		||||
 | 
			
		||||
// A RouteSelector finds the best matching Route given the input HTTP Request
 | 
			
		||||
// RouteSelectors can optionally also implement the PathProcessor interface to also calculate the
 | 
			
		||||
// path parameters after the route has been selected.
 | 
			
		||||
type RouteSelector interface {
 | 
			
		||||
 | 
			
		||||
	// SelectRoute finds a Route given the input HTTP Request and a list of WebServices.
 | 
			
		||||
	// It returns a selected Route and its containing WebService or an error indicating
 | 
			
		||||
	// a problem.
 | 
			
		||||
	SelectRoute(
 | 
			
		||||
		webServices []*WebService,
 | 
			
		||||
		httpRequest *http.Request) (selectedService *WebService, selected *Route, err error)
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										32
									
								
								vendor/github.com/emicklei/go-restful/v3/service_error.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										32
									
								
								vendor/github.com/emicklei/go-restful/v3/service_error.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,32 @@
 | 
			
		||||
package restful
 | 
			
		||||
 | 
			
		||||
// Copyright 2013 Ernest Micklei. All rights reserved.
 | 
			
		||||
// Use of this source code is governed by a license
 | 
			
		||||
// that can be found in the LICENSE file.
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"net/http"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// ServiceError is a transport object to pass information about a non-Http error occurred in a WebService while processing a request.
 | 
			
		||||
type ServiceError struct {
 | 
			
		||||
	Code    int
 | 
			
		||||
	Message string
 | 
			
		||||
	Header  http.Header
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// NewError returns a ServiceError using the code and reason
 | 
			
		||||
func NewError(code int, message string) ServiceError {
 | 
			
		||||
	return ServiceError{Code: code, Message: message}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// NewErrorWithHeader returns a ServiceError using the code, reason and header
 | 
			
		||||
func NewErrorWithHeader(code int, message string, header http.Header) ServiceError {
 | 
			
		||||
	return ServiceError{Code: code, Message: message, Header: header}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Error returns a text representation of the service error
 | 
			
		||||
func (s ServiceError) Error() string {
 | 
			
		||||
	return fmt.Sprintf("[ServiceError:%v] %v", s.Code, s.Message)
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										293
									
								
								vendor/github.com/emicklei/go-restful/v3/web_service.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										293
									
								
								vendor/github.com/emicklei/go-restful/v3/web_service.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,293 @@
 | 
			
		||||
package restful
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"errors"
 | 
			
		||||
	"os"
 | 
			
		||||
	"reflect"
 | 
			
		||||
	"sync"
 | 
			
		||||
 | 
			
		||||
	"github.com/emicklei/go-restful/v3/log"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// Copyright 2013 Ernest Micklei. All rights reserved.
 | 
			
		||||
// Use of this source code is governed by a license
 | 
			
		||||
// that can be found in the LICENSE file.
 | 
			
		||||
 | 
			
		||||
// WebService holds a collection of Route values that bind a Http Method + URL Path to a function.
 | 
			
		||||
type WebService struct {
 | 
			
		||||
	rootPath       string
 | 
			
		||||
	pathExpr       *pathExpression // cached compilation of rootPath as RegExp
 | 
			
		||||
	routes         []Route
 | 
			
		||||
	produces       []string
 | 
			
		||||
	consumes       []string
 | 
			
		||||
	pathParameters []*Parameter
 | 
			
		||||
	filters        []FilterFunction
 | 
			
		||||
	documentation  string
 | 
			
		||||
	apiVersion     string
 | 
			
		||||
 | 
			
		||||
	typeNameHandleFunc TypeNameHandleFunction
 | 
			
		||||
 | 
			
		||||
	dynamicRoutes bool
 | 
			
		||||
 | 
			
		||||
	// protects 'routes' if dynamic routes are enabled
 | 
			
		||||
	routesLock sync.RWMutex
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (w *WebService) SetDynamicRoutes(enable bool) {
 | 
			
		||||
	w.dynamicRoutes = enable
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// TypeNameHandleFunction declares functions that can handle translating the name of a sample object
 | 
			
		||||
// into the restful documentation for the service.
 | 
			
		||||
type TypeNameHandleFunction func(sample interface{}) string
 | 
			
		||||
 | 
			
		||||
// TypeNameHandler sets the function that will convert types to strings in the parameter
 | 
			
		||||
// and model definitions. If not set, the web service will invoke
 | 
			
		||||
// reflect.TypeOf(object).String().
 | 
			
		||||
func (w *WebService) TypeNameHandler(handler TypeNameHandleFunction) *WebService {
 | 
			
		||||
	w.typeNameHandleFunc = handler
 | 
			
		||||
	return w
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// reflectTypeName is the default TypeNameHandleFunction and for a given object
 | 
			
		||||
// returns the name that Go identifies it with (e.g. "string" or "v1.Object") via
 | 
			
		||||
// the reflection API.
 | 
			
		||||
func reflectTypeName(sample interface{}) string {
 | 
			
		||||
	return reflect.TypeOf(sample).String()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// compilePathExpression ensures that the path is compiled into a RegEx for those routers that need it.
 | 
			
		||||
func (w *WebService) compilePathExpression() {
 | 
			
		||||
	compiled, err := newPathExpression(w.rootPath)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		log.Printf("invalid path:%s because:%v", w.rootPath, err)
 | 
			
		||||
		os.Exit(1)
 | 
			
		||||
	}
 | 
			
		||||
	w.pathExpr = compiled
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ApiVersion sets the API version for documentation purposes.
 | 
			
		||||
func (w *WebService) ApiVersion(apiVersion string) *WebService {
 | 
			
		||||
	w.apiVersion = apiVersion
 | 
			
		||||
	return w
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Version returns the API version for documentation purposes.
 | 
			
		||||
func (w *WebService) Version() string { return w.apiVersion }
 | 
			
		||||
 | 
			
		||||
// Path specifies the root URL template path of the WebService.
 | 
			
		||||
// All Routes will be relative to this path.
 | 
			
		||||
func (w *WebService) Path(root string) *WebService {
 | 
			
		||||
	w.rootPath = root
 | 
			
		||||
	if len(w.rootPath) == 0 {
 | 
			
		||||
		w.rootPath = "/"
 | 
			
		||||
	}
 | 
			
		||||
	w.compilePathExpression()
 | 
			
		||||
	return w
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Param adds a PathParameter to document parameters used in the root path.
 | 
			
		||||
func (w *WebService) Param(parameter *Parameter) *WebService {
 | 
			
		||||
	if w.pathParameters == nil {
 | 
			
		||||
		w.pathParameters = []*Parameter{}
 | 
			
		||||
	}
 | 
			
		||||
	w.pathParameters = append(w.pathParameters, parameter)
 | 
			
		||||
	return w
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 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
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 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", CollectionFormat: CollectionFormatCSV.String()}}
 | 
			
		||||
	p.beQuery()
 | 
			
		||||
	return p
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 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
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 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
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 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
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Route creates a new Route using the RouteBuilder and add to the ordered list of Routes.
 | 
			
		||||
func (w *WebService) Route(builder *RouteBuilder) *WebService {
 | 
			
		||||
	w.routesLock.Lock()
 | 
			
		||||
	defer w.routesLock.Unlock()
 | 
			
		||||
	builder.copyDefaults(w.produces, w.consumes)
 | 
			
		||||
	w.routes = append(w.routes, builder.Build())
 | 
			
		||||
	return w
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// RemoveRoute removes the specified route, looks for something that matches 'path' and 'method'
 | 
			
		||||
func (w *WebService) RemoveRoute(path, method string) error {
 | 
			
		||||
    if !w.dynamicRoutes {
 | 
			
		||||
        return errors.New("dynamic routes are not enabled.")
 | 
			
		||||
    }
 | 
			
		||||
    w.routesLock.Lock()
 | 
			
		||||
    defer w.routesLock.Unlock()
 | 
			
		||||
    newRoutes := []Route{}
 | 
			
		||||
    for _, route := range w.routes {
 | 
			
		||||
        if route.Method == method && route.Path == path {
 | 
			
		||||
            continue
 | 
			
		||||
        }
 | 
			
		||||
        newRoutes = append(newRoutes, route)
 | 
			
		||||
    }
 | 
			
		||||
    w.routes = newRoutes
 | 
			
		||||
    return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Method creates a new RouteBuilder and initialize its http method
 | 
			
		||||
func (w *WebService) Method(httpMethod string) *RouteBuilder {
 | 
			
		||||
	return new(RouteBuilder).typeNameHandler(w.typeNameHandleFunc).servicePath(w.rootPath).Method(httpMethod)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Produces specifies that this WebService can produce one or more MIME types.
 | 
			
		||||
// Http requests must have one of these values set for the Accept header.
 | 
			
		||||
func (w *WebService) Produces(contentTypes ...string) *WebService {
 | 
			
		||||
	w.produces = contentTypes
 | 
			
		||||
	return w
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Consumes specifies that this WebService can consume one or more MIME types.
 | 
			
		||||
// Http requests must have one of these values set for the Content-Type header.
 | 
			
		||||
func (w *WebService) Consumes(accepts ...string) *WebService {
 | 
			
		||||
	w.consumes = accepts
 | 
			
		||||
	return w
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Routes returns the Routes associated with this WebService
 | 
			
		||||
func (w *WebService) Routes() []Route {
 | 
			
		||||
	if !w.dynamicRoutes {
 | 
			
		||||
		return w.routes
 | 
			
		||||
	}
 | 
			
		||||
	// Make a copy of the array to prevent concurrency problems
 | 
			
		||||
	w.routesLock.RLock()
 | 
			
		||||
	defer w.routesLock.RUnlock()
 | 
			
		||||
	result := make([]Route, len(w.routes))
 | 
			
		||||
	for ix := range w.routes {
 | 
			
		||||
		result[ix] = w.routes[ix]
 | 
			
		||||
	}
 | 
			
		||||
	return result
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// RootPath returns the RootPath associated with this WebService. Default "/"
 | 
			
		||||
func (w *WebService) RootPath() string {
 | 
			
		||||
	return w.rootPath
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// PathParameters return the path parameter names for (shared among its Routes)
 | 
			
		||||
func (w *WebService) PathParameters() []*Parameter {
 | 
			
		||||
	return w.pathParameters
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Filter adds a filter function to the chain of filters applicable to all its Routes
 | 
			
		||||
func (w *WebService) Filter(filter FilterFunction) *WebService {
 | 
			
		||||
	w.filters = append(w.filters, filter)
 | 
			
		||||
	return w
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Doc is used to set the documentation of this service.
 | 
			
		||||
func (w *WebService) Doc(plainText string) *WebService {
 | 
			
		||||
	w.documentation = plainText
 | 
			
		||||
	return w
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Documentation returns it.
 | 
			
		||||
func (w *WebService) Documentation() string {
 | 
			
		||||
	return w.documentation
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
	Convenience methods
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
// HEAD is a shortcut for .Method("HEAD").Path(subPath)
 | 
			
		||||
func (w *WebService) HEAD(subPath string) *RouteBuilder {
 | 
			
		||||
	return new(RouteBuilder).typeNameHandler(w.typeNameHandleFunc).servicePath(w.rootPath).Method("HEAD").Path(subPath)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// GET is a shortcut for .Method("GET").Path(subPath)
 | 
			
		||||
func (w *WebService) GET(subPath string) *RouteBuilder {
 | 
			
		||||
	return new(RouteBuilder).typeNameHandler(w.typeNameHandleFunc).servicePath(w.rootPath).Method("GET").Path(subPath)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// POST is a shortcut for .Method("POST").Path(subPath)
 | 
			
		||||
func (w *WebService) POST(subPath string) *RouteBuilder {
 | 
			
		||||
	return new(RouteBuilder).typeNameHandler(w.typeNameHandleFunc).servicePath(w.rootPath).Method("POST").Path(subPath)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// PUT is a shortcut for .Method("PUT").Path(subPath)
 | 
			
		||||
func (w *WebService) PUT(subPath string) *RouteBuilder {
 | 
			
		||||
	return new(RouteBuilder).typeNameHandler(w.typeNameHandleFunc).servicePath(w.rootPath).Method("PUT").Path(subPath)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// PATCH is a shortcut for .Method("PATCH").Path(subPath)
 | 
			
		||||
func (w *WebService) PATCH(subPath string) *RouteBuilder {
 | 
			
		||||
	return new(RouteBuilder).typeNameHandler(w.typeNameHandleFunc).servicePath(w.rootPath).Method("PATCH").Path(subPath)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// DELETE is a shortcut for .Method("DELETE").Path(subPath)
 | 
			
		||||
func (w *WebService) DELETE(subPath string) *RouteBuilder {
 | 
			
		||||
	return new(RouteBuilder).typeNameHandler(w.typeNameHandleFunc).servicePath(w.rootPath).Method("DELETE").Path(subPath)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// OPTIONS is a shortcut for .Method("OPTIONS").Path(subPath)
 | 
			
		||||
func (w *WebService) OPTIONS(subPath string) *RouteBuilder {
 | 
			
		||||
	return new(RouteBuilder).typeNameHandler(w.typeNameHandleFunc).servicePath(w.rootPath).Method("OPTIONS").Path(subPath)
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										39
									
								
								vendor/github.com/emicklei/go-restful/v3/web_service_container.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										39
									
								
								vendor/github.com/emicklei/go-restful/v3/web_service_container.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,39 @@
 | 
			
		||||
package restful
 | 
			
		||||
 | 
			
		||||
// Copyright 2013 Ernest Micklei. All rights reserved.
 | 
			
		||||
// Use of this source code is governed by a license
 | 
			
		||||
// that can be found in the LICENSE file.
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"net/http"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// DefaultContainer is a restful.Container that uses http.DefaultServeMux
 | 
			
		||||
var DefaultContainer *Container
 | 
			
		||||
 | 
			
		||||
func init() {
 | 
			
		||||
	DefaultContainer = NewContainer()
 | 
			
		||||
	DefaultContainer.ServeMux = http.DefaultServeMux
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// If set the true then panics will not be caught to return HTTP 500.
 | 
			
		||||
// In that case, Route functions are responsible for handling any error situation.
 | 
			
		||||
// Default value is false = recover from panics. This has performance implications.
 | 
			
		||||
// OBSOLETE ; use restful.DefaultContainer.DoNotRecover(true)
 | 
			
		||||
var DoNotRecover = false
 | 
			
		||||
 | 
			
		||||
// Add registers a new WebService add it to the DefaultContainer.
 | 
			
		||||
func Add(service *WebService) {
 | 
			
		||||
	DefaultContainer.Add(service)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Filter appends a container FilterFunction from the DefaultContainer.
 | 
			
		||||
// These are called before dispatching a http.Request to a WebService.
 | 
			
		||||
func Filter(filter FilterFunction) {
 | 
			
		||||
	DefaultContainer.Filter(filter)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// RegisteredWebServices returns the collections of WebServices from the DefaultContainer
 | 
			
		||||
func RegisteredWebServices() []*WebService {
 | 
			
		||||
	return DefaultContainer.RegisteredWebServices()
 | 
			
		||||
}
 | 
			
		||||
		Reference in New Issue
	
	Block a user