Skip to content

Commit 5fe7b58

Browse files
committed
README auto-gen (add the API-Versioning example)
1 parent 78ceab5 commit 5fe7b58

File tree

1 file changed

+105
-0
lines changed

1 file changed

+105
-0
lines changed

README.md

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ In fact the internal code of **go-json-rest** is itself implemented with Middlew
4646
- [Advanced](#advanced)
4747
- [Streaming](#streaming)
4848
- [Non JSON payload](#non-json-payload)
49+
- [API Versioning](#api-versioning)
4950
- [SPDY](#spdy)
5051
- [Google App Engine](#gae)
5152
- [Basic Auth Custom](#basic-auth-custom)
@@ -1020,6 +1021,110 @@ func main() {
10201021

10211022
```
10221023

1024+
#### API Versioning
1025+
1026+
First, API versioning is not easy and you may want to favor a mechanism that uses only backward compatible changes and deprecation cycles.
1027+
1028+
That been said, here is an example of API versioning using [Semver](http://semver.org/)
1029+
1030+
It defines a middleware that parses the version, checks a min and a max, and makes it available in the `request.Env`.
1031+
1032+
(TODO, there is an obvious need for PostRoutingMiddlewares here.)
1033+
1034+
The curl demo:
1035+
``` sh
1036+
curl -i http://127.0.0.1:8080/api/1.0.0/message
1037+
curl -i http://127.0.0.1:8080/api/2.0.0/message
1038+
curl -i http://127.0.0.1:8080/api/2.0.1/message
1039+
curl -i http://127.0.0.1:8080/api/0.0.1/message
1040+
curl -i http://127.0.0.1:8080/api/4.0.1/message
1041+
1042+
```
1043+
1044+
1045+
Go code:
1046+
``` go
1047+
package main
1048+
1049+
import (
1050+
"github.com/ant0ine/go-json-rest/rest"
1051+
"github.com/coreos/go-semver/semver"
1052+
"log"
1053+
"net/http"
1054+
)
1055+
1056+
type SemVerMiddleware struct {
1057+
MinVersion string
1058+
MaxVersion string
1059+
}
1060+
1061+
func (mw *SemVerMiddleware) MiddlewareFunc(handler rest.HandlerFunc) rest.HandlerFunc {
1062+
1063+
minVersion, err := semver.NewVersion(mw.MinVersion)
1064+
if err != nil {
1065+
panic(err)
1066+
}
1067+
1068+
maxVersion, err := semver.NewVersion(mw.MaxVersion)
1069+
if err != nil {
1070+
panic(err)
1071+
}
1072+
1073+
return func(writer rest.ResponseWriter, request *rest.Request) {
1074+
1075+
version, err := semver.NewVersion(request.PathParam("version"))
1076+
if err != nil {
1077+
rest.Error(writer, "Invalid version: "+err.Error(), http.StatusBadRequest)
1078+
return
1079+
}
1080+
1081+
if version.LessThan(*minVersion) {
1082+
rest.Error(writer, "Min supported version is "+minVersion.String(), http.StatusBadRequest)
1083+
return
1084+
}
1085+
1086+
if maxVersion.LessThan(*version) {
1087+
rest.Error(writer, "Max supported version is "+maxVersion.String(), http.StatusBadRequest)
1088+
return
1089+
}
1090+
1091+
request.Env["VERSION"] = version
1092+
handler(writer, request)
1093+
}
1094+
}
1095+
1096+
type Message struct {
1097+
Body string
1098+
}
1099+
1100+
func main() {
1101+
handler := rest.ResourceHandler{}
1102+
svmw := SemVerMiddleware{
1103+
MinVersion: "1.0.0",
1104+
MaxVersion: "3.0.0",
1105+
}
1106+
err := handler.SetRoutes(
1107+
&rest.Route{"GET", "/#version/message", svmw.MiddlewareFunc(
1108+
func(w rest.ResponseWriter, req *rest.Request) {
1109+
version := req.Env["VERSION"].(*semver.Version)
1110+
if version.Major == 2 {
1111+
// http://en.wikipedia.org/wiki/Second-system_effect
1112+
w.WriteJson(&Message{"Hello broken World!"})
1113+
} else {
1114+
w.WriteJson(&Message{"Hello World!"})
1115+
}
1116+
},
1117+
)},
1118+
)
1119+
if err != nil {
1120+
log.Fatal(err)
1121+
}
1122+
http.Handle("/api/", http.StripPrefix("/api", &handler))
1123+
log.Fatal(http.ListenAndServe(":8080", nil))
1124+
}
1125+
1126+
```
1127+
10231128
#### SPDY
10241129

10251130
Demonstrate how to use SPDY with https://github.com/shykes/spdy-go

0 commit comments

Comments
 (0)