Last active
August 29, 2015 13:56
-
-
Save olekukonko/9312736 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import ( | |
"net/url" | |
"github.com/dougblack/sleepy" | |
) | |
type Item struct { } | |
func (item Item) Get(values url.Values) (int, interface{}) { | |
items := []string{"item1", "item2"} | |
data := map[string][]string{"items": items} | |
return 200, data | |
} | |
func main() { | |
item := new(Item) | |
var api = sleepy.NewAPI() | |
api.AddResource(item, "/items") | |
api.Start(3000) | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import ( | |
"encoding/json" | |
"errors" | |
"fmt" | |
"net/http" | |
"net/url" | |
) | |
const ( | |
GET = "GET" | |
POST = "POST" | |
PUT = "PUT" | |
DELETE = "DELETE" | |
) | |
// GetSupported is the interface that provides the Get | |
// method a resource must support to receive HTTP GETs. | |
type GetSupported interface { | |
Get(url.Values) (int, interface{}) | |
} | |
// PostSupported is the interface that provides the Post | |
// method a resource must support to receive HTTP POSTs. | |
type PostSupported interface { | |
Post(url.Values) (int, interface{}) | |
} | |
// PutSupported is the interface that provides the Put | |
// method a resource must support to receive HTTP PUTs. | |
type PutSupported interface { | |
Put(url.Values) (int, interface{}) | |
} | |
// DeleteSupported is the interface that provides the Delete | |
// method a resource must support to receive HTTP DELETEs. | |
type DeleteSupported interface { | |
Delete(url.Values) (int, interface{}) | |
} | |
// An API manages a group of resources by routing requests | |
// to the correct method on a matching resource and marshalling | |
// the returned data to JSON for the HTTP response. | |
// | |
// You can instantiate multiple APIs on separate ports. Each API | |
// will manage its own set of resources. | |
type API struct { | |
mux *http.ServeMux | |
} | |
// NewAPI allocates and returns a new API. | |
func NewAPI() *API { | |
return &API{} | |
} | |
func (api *API) requestHandler(resource interface{}) http.HandlerFunc { | |
return func(rw http.ResponseWriter, request *http.Request) { | |
if request.ParseForm() != nil { | |
rw.WriteHeader(http.StatusBadRequest) | |
return | |
} | |
var handler func(url.Values) (int, interface{}) | |
switch request.Method { | |
case GET: | |
if resource, ok := resource.(GetSupported); ok { | |
handler = resource.Get | |
} | |
case POST: | |
if resource, ok := resource.(PostSupported); ok { | |
handler = resource.Post | |
} | |
case PUT: | |
if resource, ok := resource.(PutSupported); ok { | |
handler = resource.Put | |
} | |
case DELETE: | |
if resource, ok := resource.(DeleteSupported); ok { | |
handler = resource.Delete | |
} | |
} | |
if handler == nil { | |
rw.WriteHeader(http.StatusMethodNotAllowed) | |
return | |
} | |
code, data := handler(request.Form) | |
content, err := json.Marshal(data) | |
if err != nil { | |
rw.WriteHeader(http.StatusInternalServerError) | |
return | |
} | |
rw.WriteHeader(code) | |
rw.Write(content) | |
} | |
} | |
// AddResource adds a new resource to an API. The API will route | |
// requests that match one of the given paths to the matching HTTP | |
// method on the resource. | |
func (api *API) AddResource(resource interface{}, paths ...string) { | |
if api.mux == nil { | |
api.mux = http.NewServeMux() | |
} | |
for _, path := range paths { | |
api.mux.HandleFunc(path, api.requestHandler(resource)) | |
} | |
} | |
// Start causes the API to begin serving requests on the given port. | |
func (api *API) Start(port int) error { | |
if api.mux == nil { | |
return errors.New("You must add at least one resource to this API.") | |
} | |
portString := fmt.Sprintf(":%d", port) | |
return http.ListenAndServe(portString, api.mux) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment