@@ -46,6 +46,7 @@ In fact the internal code of **go-json-rest** is itself implemented with Middlew
46
46
- [ Advanced] ( #advanced )
47
47
- [Streaming](#streaming)
48
48
- [Non JSON payload](#non-json-payload)
49
+ - [API Versioning](#api-versioning)
49
50
- [SPDY](#spdy)
50
51
- [Google App Engine](#gae)
51
52
- [Basic Auth Custom](#basic-auth-custom)
@@ -1020,6 +1021,110 @@ func main() {
1020
1021
1021
1022
```
1022
1023
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
+
1023
1128
#### SPDY
1024
1129
1025
1130
Demonstrate how to use SPDY with https://github.com/shykes/spdy-go
0 commit comments