Documentation ¶
Index ¶
Examples ¶
Constants ¶
This section is empty.
Variables ¶
var ( // ErrNotFound signals that the resource is absent. // See CRUDRepo's SetReadFunc, SetUpdateFunc and SetDeleteFunc for the details. ErrNotFound = errors.New("no such entry") // ErrOptimisticLock signals that the latest version does not match the request. // See CRUDRepo's SetUpdateFunc and SetDeleteFunc for the details. ErrOptimisticLock = errors.New("lost optimistic lock") )
Functions ¶
func ReceiveJSON ¶
func ReceiveJSON(dst interface{}, r *http.Request, w http.ResponseWriter) bool
ReceiveJSON reads the HTTP request body. When the return is false then w must be left as is.
func ServeJSON ¶
func ServeJSON(w http.ResponseWriter, statusCode int, src interface{})
ServeJSON writes the HTTP response body.
Types ¶
type CRUDRepo ¶
type CRUDRepo struct {
// contains filtered or unexported fields
}
CRUDRepo is a REST repository.
func NewCRUD ¶
NewCRUD returns a new REST repository for the CRUD operations. The mountLocation specifies the root for CRUDRepo.ServeHTTP. The versionPath is a GoEL expression to the date version (in the data type).
It's operation is based on two assumptions. 1) Identifiers are int64. 2) Versions are int64 unix timestamps in nanoseconds.
func (*CRUDRepo) ServeHTTP ¶
func (repo *CRUDRepo) ServeHTTP(w http.ResponseWriter, r *http.Request)
ServeHTTP honors the http.Handler interface for the mount point provided with NewCRUD. For now only JSON is supported.
func (*CRUDRepo) SetCreateFunc ¶
func (repo *CRUDRepo) SetCreateFunc(f interface{})
SetCreateFunc enables create support. The method panics on any of the following conditions. 1) f does not match signature func(data T) (id int64, err error) 2) Data type T does not match the other CRUD operations. 3) Data type T is not a pointer.
It is the responsibility of f to set the version.
Example ¶
package main import ( "bytes" "fmt" "net/http" "net/http/httptest" "sync/atomic" "time" "github.com/pascaldekloe/goe/rest" ) func main() { type Data struct { Version int64 `json:"version"` Msg string `json:"msg"` } var v atomic.Value v.Store(&Data{}) repo := rest.NewCRUD("/", "/Version") repo.SetCreateFunc(func(d *Data) (int64, error) { d.Version = time.Now().UnixNano() v.Store(d) return 42, nil }) server := httptest.NewServer(repo) defer server.Close() res, err := http.Post(server.URL, "application/json", bytes.NewBufferString(`{"msg": "Hello World!"}`)) if err != nil { panic(err) } fmt.Printf("Got HTTP %s %s: %s\n", res.Status, res.Header.Get("Location"), v.Load().(*Data).Msg) }
Output: Got HTTP 201 Created /42: Hello World!
func (*CRUDRepo) SetDeleteFunc ¶
func (repo *CRUDRepo) SetDeleteFunc(f interface{})
SetUpdateFunc enables update support. The method panics when f does not match signature func(id, version int64) error.
When the id is not found f must return ErrNotFound. When the version is not equal to 0 and version does not match the latest one available then f must skip normal operation and return ErrOptimisticLock.
func (*CRUDRepo) SetReadFunc ¶
func (repo *CRUDRepo) SetReadFunc(f interface{})
SetReadFunc enables read support. The method panics on any of the following conditions. 1) f does not match signature func(id, version int64) (hit T, err error) 2) Data type T does not match the other CRUD operations. 3) Data type T is not a pointer.
When the id is not found f must return ErrNotFound. The version must be honored and the latest version should be served as a fallback.
Example ¶
package main import ( "fmt" "net/http" "net/http/httptest" "github.com/pascaldekloe/goe/rest" ) func main() { type Data struct { Version int64 `json:"version"` Msg string `json:"msg"` } repo := rest.NewCRUD("/", "/Version") repo.SetReadFunc(func(id, version int64) (*Data, error) { if id != 42 { return nil, rest.ErrNotFound } return &Data{1456260879956532222, "Hello World!"}, nil }) server := httptest.NewServer(repo) defer server.Close() req, err := http.NewRequest("GET", server.URL+"/42", nil) if err != nil { panic(err) } req.Header.Set("If-None-Match", `"1456260879956532222"`) res, err := http.DefaultClient.Do(req) if err != nil { panic(err) } fmt.Printf("Got HTTP %s: %s\n", res.Status, res.Header.Get("Content-Location")) }
Output: Got HTTP 304 Not Modified: /42?v=1456260879956532222
func (*CRUDRepo) SetUpdateFunc ¶
func (repo *CRUDRepo) SetUpdateFunc(f interface{})
SetUpdateFunc enables update support. The method panics on any of the following conditions. 1) f does not match signature func(id int64, data T) (error) 2) Data type T does not match the other CRUD operations. 3) Data type T is not a pointer.
When the id is not found f must return ErrNotFound. When the data's version is not equal to 0 and version does not match the latest one available then f must skip normal operation and return ErrOptimisticLock. It is the responsibility of f to set the new version.
Notes ¶
Bugs ¶
No support for multiple entity tags in If-None-Match header.
No support for multiple entity tags in If-Match header.