https://github.com/alecthomas/pathways
Pathways - An opinionated RESTful web service framework for Go
https://github.com/alecthomas/pathways
Last synced: over 1 year ago
JSON representation
Pathways - An opinionated RESTful web service framework for Go
- Host: GitHub
- URL: https://github.com/alecthomas/pathways
- Owner: alecthomas
- Created: 2013-06-10T02:06:03.000Z (about 13 years ago)
- Default Branch: master
- Last Pushed: 2024-02-01T08:47:21.000Z (over 2 years ago)
- Last Synced: 2025-02-18T17:06:53.883Z (over 1 year ago)
- Language: Go
- Size: 11.7 KB
- Stars: 1
- Watchers: 3
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
README
# Pathways - a RESTful web service framework for Go
The goal of Pathways is to make building RESTful web services simple.
Pathways centers around the concept of services. Services define exactly how every endpoint in a web service is accessed and handled. This provides several benefits, including the ability to construct client requests, and the ability to autogenerate API documentation.
## Example
Here's an example of an in-memory key-value service and client with Pathways:
```go
package main
import (
"github.com/alecthomas/pathways"
"net/http"
)
type KeyValueService struct {
service *pathways.Service
kv map[string]string
}
func KeyValueServiceMap(root string) *pathways.Service {
s := pathways.NewService(root)
s.Path("/").Name("List").Get().APIResponseType(map[string]string{})
str := ""
s.Path("/{key}").Name("Get").Get().APIResponseType(&str)
s.Path("/{key}").Name("Create").Post().APIRequestType(&str)
s.Path("/{key}").Name("Delete").Delete()
return s
}
func NewClient(url string) *pathways.Client {
s := KeyValueServiceMap(url)
return pathways.NewClient(s, "application/json")
}
func NewKeyValueService(root string) *KeyValueService {
k := &KeyValueService{
service: KeyValueServiceMap(root),
kv: make(map[string]string),
}
k.service.Find("List").APIFunction(k.List)
k.service.Find("Get").APIFunction(k.Get)
k.service.Find("Create").APIFunction(k.Create)
k.service.Find("Delete").APIFunction(k.Delete)
return k
}
func (k *KeyValueService) ServeHTTP(w http.ResponseWriter, r *http.Request) {
k.service.ServeHTTP(w, r)
}
func (k *KeyValueService) List(cx *pathways.Context) pathways.Response {
return cx.APIResponse(http.StatusOK, k.kv)
}
func (k *KeyValueService) Get(cx *pathways.Context) pathways.Response {
return cx.APIResponse(http.StatusOK, k.kv[cx.PathVars["key"]])
}
func (k *KeyValueService) Create(cx *pathways.Context, value *string) pathways.Response {
k.kv[cx.PathVars["key"]] = *value
return cx.APIResponse(http.StatusCreated, "ok")
}
func (k *KeyValueService) Delete(cx *pathways.Context) pathways.Response {
delete(k.kv, cx.PathVars["key"])
return cx.APIResponse(http.StatusOK, &struct{}{})
}
func main() {
s := NewKeyValueService("/api/")
http.ListenAndServe(":8080", s)
}
```
Test with:
```bash
$ curl http://localhost:8080/api/
{}
$ curl --data-binary '"hello world"' http://localhost:8080/api/foo
"ok"
$ curl http://localhost:8080/api/
{"foo":"hello world"}
$ curl http://localhost:8080/api/foo
"hello world"
```
## Features
### A simple yet flexible URL routing engine
For example, the following service definition might specify routes for a key/value store:
```go
s := pathways.NewService("/kv/")
s.Path("/").Name("List").Get()
s.Path("/{key}").Name("Create").Post()
s.Path("/{key}").Name("Get").Get()
s.Path("/{key}").Name("Delete").Delete()
```
### Automatic serialization/deserialization of requests/responses
Pathways routes can define the request and response structures expected, and route directly to functions and methods, passing the deserialized request as an argument:
```go
type KeyValueService struct {
}
func (k *KeyValueService) Create(cx *pathways.Context, req *CreateRequest) pathways.Response {
// ... do something with deserialized request
return cx.APIResponse(http.StatusOK, &CreateResponse{})
}
kvs := &KeyValueService{}
s.Path("/{key}").Name("Create").Post().APIRequestType(&CreateRequest{}).APIResponseType(&CreateResponse{}).APIFunction(kvs.Create)
```
### RESTful client using the service definition
The following will issue a `GET` request to `/kv/key` with the request body from `CreateRequest`. The response will be returned as a `CreateResponse` structure:
```go
c := pathways.NewClient(s, "application/x-msgpack")
response := &CreateResponse{}
err := c.Call("Create", pathways.Args{"key": "somekey"}, &CreateRequest{...}, response)
```
### Transparent support for JSON, MsgPack and BSON serialized requests/responses
The content-types for these formats are `application/json`, `application/x-msgpack` and `application/bson`. Setting the request `Content-Type` and/or `Accept` headers to one of these will set the desired serialization format. The default is JSON.
The Pathways server will detect the correct serialization format from request headers (falling back on JSON). The Pathways client will use the serialization format specified in the constructor.
Why not support only JSON? Primarily because JSON has [limitations on the numeric values](http://cdivilly.wordpress.com/2012/04/11/json-javascript-large-64-bit-integers/) that can be represented.