parent
800ea949b9
commit
8ead7afe9f
@ -0,0 +1,23 @@
|
||||
Copyright (c) 2014, Elazar Leibovich
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
@ -0,0 +1,46 @@
|
||||
# go-bindata-assetfs
|
||||
|
||||
Serve embedded files from [jteeuwen/go-bindata](https://github.com/jteeuwen/go-bindata) with `net/http`.
|
||||
|
||||
[GoDoc](http://godoc.org/github.com/elazarl/go-bindata-assetfs)
|
||||
|
||||
### Installation
|
||||
|
||||
Install with
|
||||
|
||||
$ go get github.com/jteeuwen/go-bindata/...
|
||||
$ go get github.com/elazarl/go-bindata-assetfs/...
|
||||
|
||||
### Creating embedded data
|
||||
|
||||
Usage is identical to [jteeuwen/go-bindata](https://github.com/jteeuwen/go-bindata) usage,
|
||||
instead of running `go-bindata` run `go-bindata-assetfs`.
|
||||
|
||||
The tool will create a `bindata_assetfs.go` file, which contains the embedded data.
|
||||
|
||||
A typical use case is
|
||||
|
||||
$ go-bindata-assetfs data/...
|
||||
|
||||
### Using assetFS in your code
|
||||
|
||||
The generated file provides an `assetFS()` function that returns a `http.Filesystem`
|
||||
wrapping the embedded files. What you usually want to do is:
|
||||
|
||||
http.Handle("/", http.FileServer(assetFS()))
|
||||
|
||||
This would run an HTTP server serving the embedded files.
|
||||
|
||||
## Without running binary tool
|
||||
|
||||
You can always just run the `go-bindata` tool, and then
|
||||
|
||||
use
|
||||
|
||||
import "github.com/elazarl/go-bindata-assetfs"
|
||||
...
|
||||
http.Handle("/",
|
||||
http.FileServer(
|
||||
&assetfs.AssetFS{Asset: Asset, AssetDir: AssetDir, Prefix: "data"}))
|
||||
|
||||
to serve files embedded from the `data` directory.
|
@ -0,0 +1,147 @@
|
||||
package assetfs
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"time"
|
||||
)
|
||||
|
||||
var (
|
||||
fileTimestamp = time.Now()
|
||||
)
|
||||
|
||||
// FakeFile implements os.FileInfo interface for a given path and size
|
||||
type FakeFile struct {
|
||||
// Path is the path of this file
|
||||
Path string
|
||||
// Dir marks of the path is a directory
|
||||
Dir bool
|
||||
// Len is the length of the fake file, zero if it is a directory
|
||||
Len int64
|
||||
}
|
||||
|
||||
func (f *FakeFile) Name() string {
|
||||
_, name := filepath.Split(f.Path)
|
||||
return name
|
||||
}
|
||||
|
||||
func (f *FakeFile) Mode() os.FileMode {
|
||||
mode := os.FileMode(0644)
|
||||
if f.Dir {
|
||||
return mode | os.ModeDir
|
||||
}
|
||||
return mode
|
||||
}
|
||||
|
||||
func (f *FakeFile) ModTime() time.Time {
|
||||
return fileTimestamp
|
||||
}
|
||||
|
||||
func (f *FakeFile) Size() int64 {
|
||||
return f.Len
|
||||
}
|
||||
|
||||
func (f *FakeFile) IsDir() bool {
|
||||
return f.Mode().IsDir()
|
||||
}
|
||||
|
||||
func (f *FakeFile) Sys() interface{} {
|
||||
return nil
|
||||
}
|
||||
|
||||
// AssetFile implements http.File interface for a no-directory file with content
|
||||
type AssetFile struct {
|
||||
*bytes.Reader
|
||||
io.Closer
|
||||
FakeFile
|
||||
}
|
||||
|
||||
func NewAssetFile(name string, content []byte) *AssetFile {
|
||||
return &AssetFile{
|
||||
bytes.NewReader(content),
|
||||
ioutil.NopCloser(nil),
|
||||
FakeFile{name, false, int64(len(content))}}
|
||||
}
|
||||
|
||||
func (f *AssetFile) Readdir(count int) ([]os.FileInfo, error) {
|
||||
return nil, errors.New("not a directory")
|
||||
}
|
||||
|
||||
func (f *AssetFile) Size() int64 {
|
||||
return f.FakeFile.Size()
|
||||
}
|
||||
|
||||
func (f *AssetFile) Stat() (os.FileInfo, error) {
|
||||
return f, nil
|
||||
}
|
||||
|
||||
// AssetDirectory implements http.File interface for a directory
|
||||
type AssetDirectory struct {
|
||||
AssetFile
|
||||
ChildrenRead int
|
||||
Children []os.FileInfo
|
||||
}
|
||||
|
||||
func NewAssetDirectory(name string, children []string, fs *AssetFS) *AssetDirectory {
|
||||
fileinfos := make([]os.FileInfo, 0, len(children))
|
||||
for _, child := range children {
|
||||
_, err := fs.AssetDir(filepath.Join(name, child))
|
||||
fileinfos = append(fileinfos, &FakeFile{child, err == nil, 0})
|
||||
}
|
||||
return &AssetDirectory{
|
||||
AssetFile{
|
||||
bytes.NewReader(nil),
|
||||
ioutil.NopCloser(nil),
|
||||
FakeFile{name, true, 0},
|
||||
},
|
||||
0,
|
||||
fileinfos}
|
||||
}
|
||||
|
||||
func (f *AssetDirectory) Readdir(count int) ([]os.FileInfo, error) {
|
||||
if count <= 0 {
|
||||
return f.Children, nil
|
||||
}
|
||||
if f.ChildrenRead+count > len(f.Children) {
|
||||
count = len(f.Children) - f.ChildrenRead
|
||||
}
|
||||
rv := f.Children[f.ChildrenRead : f.ChildrenRead+count]
|
||||
f.ChildrenRead += count
|
||||
return rv, nil
|
||||
}
|
||||
|
||||
func (f *AssetDirectory) Stat() (os.FileInfo, error) {
|
||||
return f, nil
|
||||
}
|
||||
|
||||
// AssetFS implements http.FileSystem, allowing
|
||||
// embedded files to be served from net/http package.
|
||||
type AssetFS struct {
|
||||
// Asset should return content of file in path if exists
|
||||
Asset func(path string) ([]byte, error)
|
||||
// AssetDir should return list of files in the path
|
||||
AssetDir func(path string) ([]string, error)
|
||||
// Prefix would be prepended to http requests
|
||||
Prefix string
|
||||
}
|
||||
|
||||
func (fs *AssetFS) Open(name string) (http.File, error) {
|
||||
name = path.Join(fs.Prefix, name)
|
||||
if len(name) > 0 && name[0] == '/' {
|
||||
name = name[1:]
|
||||
}
|
||||
if b, err := fs.Asset(name); err == nil {
|
||||
return NewAssetFile(name, b), nil
|
||||
}
|
||||
if children, err := fs.AssetDir(name); err == nil {
|
||||
return NewAssetDirectory(name, children, fs), nil
|
||||
} else {
|
||||
return nil, err
|
||||
}
|
||||
}
|
@ -0,0 +1,13 @@
|
||||
// assetfs allows packages to serve static content embedded
|
||||
// with the go-bindata tool with the standard net/http package.
|
||||
//
|
||||
// See https://github.com/jteeuwen/go-bindata for more information
|
||||
// about embedding binary data with go-bindata.
|
||||
//
|
||||
// Usage example, after running
|
||||
// $ go-bindata data/...
|
||||
// use:
|
||||
// http.Handle("/",
|
||||
// http.FileServer(
|
||||
// &assetfs.AssetFS{Asset: Asset, AssetDir: AssetDir, Prefix: "data"}))
|
||||
package assetfs
|
@ -0,0 +1,22 @@
|
||||
language: go
|
||||
sudo: false
|
||||
|
||||
matrix:
|
||||
include:
|
||||
- go: 1.2
|
||||
- go: 1.3
|
||||
- go: 1.4
|
||||
- go: 1.5
|
||||
- go: 1.6
|
||||
- go: tip
|
||||
allow_failures:
|
||||
- go: tip
|
||||
|
||||
install:
|
||||
- # skip
|
||||
|
||||
script:
|
||||
- go get -t -v ./...
|
||||
- diff -u <(echo -n) <(gofmt -d .)
|
||||
- go vet $(go list ./... | grep -v /vendor/)
|
||||
- go test -v -race ./...
|
@ -0,0 +1,20 @@
|
||||
Copyright (c) 2014 Carl Jackson (carl@avtok.com), Matt Silverlock (matt@eatsleeprepeat.net)
|
||||
|
||||
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.
|
@ -0,0 +1,163 @@
|
||||
# goji/httpauth [![GoDoc](https://godoc.org/github.com/goji/httpauth?status.svg)](https://godoc.org/github.com/goji/httpauth) [![Build Status](https://travis-ci.org/goji/httpauth.svg)](https://travis-ci.org/goji/httpauth)
|
||||
|
||||
`httpauth` currently provides [HTTP Basic Authentication middleware](http://tools.ietf.org/html/rfc2617) for Go. It is compatible with Go's own `net/http`, [goji](https://goji.io), Gin & anything that speaks the `http.Handler` interface.
|
||||
|
||||
## Example
|
||||
|
||||
`httpauth` provides a `SimpleBasicAuth` function to get you up and running. Particularly ideal for development servers.
|
||||
|
||||
Note that HTTP Basic Authentication credentials are sent over the wire "in the clear" (read: plaintext!) and therefore should not be considered a robust way to secure a HTTP server. If you're after that, you'll need to use SSL/TLS ("HTTPS") at a minimum.
|
||||
|
||||
### Install It
|
||||
|
||||
```sh
|
||||
$ go get github.com/goji/httpauth
|
||||
```
|
||||
|
||||
### Goji v2
|
||||
|
||||
#### Simple Usage
|
||||
|
||||
The fastest and simplest way to get started using `httpauth` is to use the
|
||||
`SimpleBasicAuth` function.
|
||||
|
||||
```go
|
||||
|
||||
package main
|
||||
|
||||
import(
|
||||
"net/http"
|
||||
|
||||
"goji.io"
|
||||
)
|
||||
|
||||
func main() {
|
||||
mux := goji.NewMux()
|
||||
|
||||
mux.Use(httpauth.SimpleBasicAuth("dave", "somepassword"))
|
||||
mux.Use(SomeOtherMiddleware)
|
||||
|
||||
// YourHandler now requires HTTP Basic Auth
|
||||
mux.Handle(pat.Get("/some-route"), YourHandler))
|
||||
|
||||
log.Fatal(http.ListenAndServe("localhost:8000", mux))
|
||||
}
|
||||
```
|
||||
|
||||
#### Advanced Usage
|
||||
|
||||
For more control over the process, pass a `AuthOptions` struct to `BasicAuth` instead. This allows you to:
|
||||
|
||||
* Configure the authentication realm.
|
||||
* Provide your own UnauthorizedHandler (anything that satisfies `http.Handler`) so you can return a better looking 401 page.
|
||||
* Define a custom authentication function, which is discussed in the next section.
|
||||
|
||||
```go
|
||||
|
||||
func main() {
|
||||
|
||||
authOpts := httpauth.AuthOptions{
|
||||
Realm: "DevCo",
|
||||
User: "dave",
|
||||
Password: "plaintext!",
|
||||
UnauthorizedHandler: myUnauthorizedHandler,
|
||||
}
|
||||
|
||||
mux := goji.NewMux()
|
||||
|
||||
mux.Use(BasicAuth(authOpts))
|
||||
mux.Use(SomeOtherMiddleware)
|
||||
|
||||
mux.Handle(pat.Get("/some-route"), YourHandler))
|
||||
|
||||
log.Fatal(http.ListenAndServe("localhost:8000", mux))
|
||||
}
|
||||
```
|
||||
|
||||
#### Custom Authentication Function
|
||||
|
||||
`httpauth` will accept a custom authentication function.
|
||||
Normally, you would not set `AuthOptions.User` nor `AuthOptions.Password` in this scenario.
|
||||
You would instead validate the given credentials against an external system such as a database.
|
||||
The contrived example below is for demonstration purposes only.
|
||||
|
||||
```go
|
||||
func main() {
|
||||
|
||||
authOpts := httpauth.AuthOptions{
|
||||
Realm: "DevCo",
|
||||
AuthFunc: myAuthFunc,
|
||||
UnauthorizedHandler: myUnauthorizedHandler,
|
||||
}
|
||||
|
||||
mux := goji.NewMux()
|
||||
|
||||
mux.Use(BasicAuth(authOpts))
|
||||
mux.Use(SomeOtherMiddleware)
|
||||
|
||||
mux.Handle(pat.Get("/some-route"), YourHandler))
|
||||
|
||||
log.Fatal(http.ListenAndServe("localhost:8000", mux))
|
||||
}
|
||||
|
||||
// myAuthFunc is not secure. It checks to see if the password is simply
|
||||
// the username repeated three times.
|
||||
func myAuthFunc(user, pass string, r *http.Request) bool {
|
||||
return pass == strings.Repeat(user, 3)
|
||||
}
|
||||
```
|
||||
|
||||
### gorilla/mux
|
||||
|
||||
Since it's all `http.Handler`, `httpauth` works with [gorilla/mux](https://github.com/gorilla/mux) (and most other routers) as well:
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/goji/httpauth"
|
||||
"github.com/gorilla/mux"
|
||||
)
|
||||
|
||||
func main() {
|
||||
r := mux.NewRouter()
|
||||
|
||||
r.HandleFunc("/", YourHandler)
|
||||
http.Handle("/", httpauth.SimpleBasicAuth("dave", "somepassword")(r))
|
||||
|
||||
http.ListenAndServe(":7000", nil)
|
||||
}
|
||||
|
||||
func YourHandler(w http.ResponseWriter, r *http.Request) {
|
||||
w.Write([]byte("Gorilla!\n"))
|
||||
}
|
||||
```
|
||||
|
||||
### net/http
|
||||
|
||||
If you're using vanilla `net/http`:
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import(
|
||||
"net/http"
|
||||
|
||||
"github.com/goji/httpauth"
|
||||
)
|
||||
|
||||
func main() {
|
||||
http.Handle("/", httpauth.SimpleBasicAuth("dave", "somepassword")(http.HandlerFunc(YourHandler)))
|
||||
http.ListenAndServe(":7000", nil)
|
||||
}
|
||||
```
|
||||
|
||||
## Contributing
|
||||
|
||||
Send a pull request! Note that features on the (informal) roadmap include HTTP Digest Auth.
|
||||
|
||||
## License
|
||||
|
||||
MIT Licensed. See the LICENSE file for details.
|
@ -0,0 +1,185 @@
|
||||
package httpauth
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/sha256"
|
||||
"crypto/subtle"
|
||||
"encoding/base64"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type basicAuth struct {
|
||||
h http.Handler
|
||||
opts AuthOptions
|
||||
}
|
||||
|
||||
// AuthOptions stores the configuration for HTTP Basic Authentication.
|
||||
//
|
||||
// A http.Handler may also be passed to UnauthorizedHandler to override the
|
||||
// default error handler if you wish to serve a custom template/response.
|
||||
type AuthOptions struct {
|
||||
Realm string
|
||||
User string
|
||||
Password string
|
||||
AuthFunc func(string, string, *http.Request) bool
|
||||
UnauthorizedHandler http.Handler
|
||||
}
|
||||
|
||||
// Satisfies the http.Handler interface for basicAuth.
|
||||
func (b basicAuth) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
// Check if we have a user-provided error handler, else set a default
|
||||
if b.opts.UnauthorizedHandler == nil {
|
||||
b.opts.UnauthorizedHandler = http.HandlerFunc(defaultUnauthorizedHandler)
|
||||
}
|
||||
|
||||
// Check that the provided details match
|
||||
if b.authenticate(r) == false {
|
||||
b.requestAuth(w, r)
|
||||
return
|
||||
}
|
||||
|
||||
// Call the next handler on success.
|
||||
b.h.ServeHTTP(w, r)
|
||||
}
|
||||
|
||||
// authenticate retrieves and then validates the user:password combination provided in
|
||||
// the request header. Returns 'false' if the user has not successfully authenticated.
|
||||
func (b *basicAuth) authenticate(r *http.Request) bool {
|
||||
const basicScheme string = "Basic "
|
||||
|
||||
if r == nil {
|
||||
return false
|
||||
}
|
||||
|
||||
// In simple mode, prevent authentication with empty credentials if User is
|
||||
// not set. Allow empty passwords to support non-password use-cases.
|
||||
if b.opts.AuthFunc == nil && b.opts.User == "" {
|
||||
return false
|
||||
}
|
||||
|
||||
// Confirm the request is sending Basic Authentication credentials.
|
||||
auth := r.Header.Get("Authorization")
|
||||
if !strings.HasPrefix(auth, basicScheme) {
|
||||
return false
|
||||
}
|
||||
|
||||
// Get the plain-text username and password from the request.
|
||||
// The first six characters are skipped - e.g. "Basic ".
|
||||
str, err := base64.StdEncoding.DecodeString(auth[len(basicScheme):])
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
|
||||
// Split on the first ":" character only, with any subsequent colons assumed to be part
|
||||
// of the password. Note that the RFC2617 standard does not place any limitations on
|
||||
// allowable characters in the password.
|
||||
creds := bytes.SplitN(str, []byte(":"), 2)
|
||||
|
||||
if len(creds) != 2 {
|
||||
return false
|
||||
}
|
||||
|
||||
givenUser := string(creds[0])
|
||||
givenPass := string(creds[1])
|
||||
|
||||
// Default to Simple mode if no AuthFunc is defined.
|
||||
if b.opts.AuthFunc == nil {
|
||||
b.opts.AuthFunc = b.simpleBasicAuthFunc
|
||||
}
|
||||
|
||||
return b.opts.AuthFunc(givenUser, givenPass, r)
|
||||
}
|
||||
|
||||
// simpleBasicAuthFunc authenticates the supplied username and password against
|
||||
// the User and Password set in the Options struct.
|
||||
func (b *basicAuth) simpleBasicAuthFunc(user, pass string, r *http.Request) bool {
|
||||
// Equalize lengths of supplied and required credentials
|
||||
// by hashing them
|
||||
givenUser := sha256.Sum256([]byte(user))
|
||||
givenPass := sha256.Sum256([]byte(pass))
|
||||
requiredUser := sha256.Sum256([]byte(b.opts.User))
|
||||
requiredPass := sha256.Sum256([]byte(b.opts.Password))
|
||||
|
||||
// Compare the supplied credentials to those set in our options
|
||||
if subtle.ConstantTimeCompare(givenUser[:], requiredUser[:]) == 1 &&
|
||||
subtle.ConstantTimeCompare(givenPass[:], requiredPass[:]) == 1 {
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
// Require authentication, and serve our error handler otherwise.
|
||||
func (b *basicAuth) requestAuth(w http.ResponseWriter, r *http.Request) {
|
||||
w.Header().Set("WWW-Authenticate", fmt.Sprintf(`Basic realm=%q`, b.opts.Realm))
|
||||
b.opts.UnauthorizedHandler.ServeHTTP(w, r)
|
||||
}
|
||||
|
||||
// defaultUnauthorizedHandler provides a default HTTP 401 Unauthorized response.
|
||||
func defaultUnauthorizedHandler(w http.ResponseWriter, r *http.Request) {
|
||||
http.Error(w, http.StatusText(http.StatusUnauthorized), http.StatusUnauthorized)
|
||||
}
|
||||
|
||||
// BasicAuth provides HTTP middleware for protecting URIs with HTTP Basic Authentication
|
||||
// as per RFC 2617. The server authenticates a user:password combination provided in the
|
||||
// "Authorization" HTTP header.
|
||||
//
|
||||
// Example:
|
||||
//
|
||||
// package main
|
||||
//
|
||||
// import(
|
||||
// "net/http"
|
||||
// "github.com/zenazn/goji"
|
||||
// "github.com/goji/httpauth"
|
||||
// )
|
||||
//
|
||||
// func main() {
|
||||
// basicOpts := httpauth.AuthOptions{
|
||||
// Realm: "Restricted",
|
||||
// User: "Dave",
|
||||
// Password: "ClearText",
|
||||
// }
|
||||
//
|
||||
// goji.Use(httpauth.BasicAuth(basicOpts), SomeOtherMiddleware)
|
||||
// goji.Get("/thing", myHandler)
|
||||
// }
|
||||
//
|
||||
// Note: HTTP Basic Authentication credentials are sent in plain text, and therefore it does
|
||||
// not make for a wholly secure authentication mechanism. You should serve your content over
|
||||
// HTTPS to mitigate this, noting that "Basic Authentication" is meant to be just that: basic!
|
||||
func BasicAuth(o AuthOptions) func(http.Handler) http.Handler {
|
||||
fn := func(h http.Handler) http.Handler {
|
||||
return basicAuth{h, o}
|
||||
}
|
||||
return fn
|
||||
}
|
||||
|
||||
// SimpleBasicAuth is a convenience wrapper around BasicAuth. It takes a user and password, and
|
||||
// returns a pre-configured BasicAuth handler using the "Restricted" realm and a default 401 handler.
|
||||
//
|
||||
// Example:
|
||||
//
|
||||
// package main
|
||||
//
|
||||
// import(
|
||||
// "net/http"
|
||||
// "github.com/zenazn/goji/web/httpauth"
|
||||
// )
|
||||
//
|
||||
// func main() {
|
||||
//
|
||||
// goji.Use(httpauth.SimpleBasicAuth("dave", "somepassword"), SomeOtherMiddleware)
|
||||
// goji.Get("/thing", myHandler)
|
||||
// }
|
||||
//
|
||||
func SimpleBasicAuth(user, password string) func(http.Handler) http.Handler {
|
||||
opts := AuthOptions{
|
||||
Realm: "Restricted",
|
||||
User: user,
|
||||
Password: password,
|
||||
}
|
||||
return BasicAuth(opts)
|
||||
}
|
Loading…
Reference in new issue