Golang(11)Web Service - RESTful

Golang(11)Web Service - RESTful

1. Concept
Requests can be matched based on URL host, path, path prefix, schemes, header and query values, HTTP methods or using custom matchers.

URL hosts and paths can have variables with an optional regular expression.

It implements the http.Handler interface so it is compatible with the standard http.ServeMux.
     
router := mux.NewRouter()
router.HandleFunc("/", HomeHandler)
router.HandleFunc("/products", ProductsHandler)

Once the router matches, the handler will be called passing (http.ResponseWriter, http.Requet)as parameters.

Variables in paths follow this pattern, {name} or {name:pattern}.

router.HandleFunc(“/products/{key}”, ProductHandler)
router.HandleFunc(“/articles/{category}/{id:[0-9]+}”, ArticleHandler)

We can fetch all these values from map
vars :=mux.Vars(request)
category := vars[“category"]

Some other matches
router.Host(“www.domain.com”)
router.Host(“{subdomain:[a-z]+}.domain.com”)

router.PathPrefix(“/products/“)

router.Methods(“GET”, “POST”)

router.Schemes(“https”)

router.Headers(“X-Requested-With”, “XMLHttpRequest”)

router.Queries(“key”, “value”)

Example:
router.HandleFunc(“/products”, ProductsHandler).Host(“www.domain.com”).Methods(“GET”).Schemes(“http”)

Work with Sub Router
router := mux.NewRouter()
sub := router.Host(“www.domain.com”).Subrouter()
sub.HandleFunc(“/products/“, ProductsHandler)

Name a Router and Build the URL
router := mux.NewRouter()
router.HandleFunc(“/articles/{category}/{id:[0-9]+}”, ArticleHandler).Name(“article”)

url, err := r.Get(“article”).URL(“category”, “technology”, “id”, “42”)
eg: “/articles/technology/42"

2. Installation
>go get github.com/gorilla/mux

Here is the Whole go implementation Class as follow:

package main

import (
     "encoding/json”    //import the json package to marshal and unmarshal JSON
     "fmt"
     "github.com/gorilla/mux”   //here is the router and dispatcher
     "io/ioutil”           //io util to read/write to io
     "net/http”             //handle the http based request and response
)

type Bug struct {           //my demo object in go
     Id        string
     BugNumber string
     BugName   string
     BugDesn   string
}

type BugResult struct {     //my common REST response object
     Bugs   []Bug
     Status string
}

func getBug(w http.ResponseWriter, r *http.Request) {     //get method
     b1 := Bug{Id: "1", BugNumber: "bug1", BugName: "bug1", BugDesn: "desn1"}
     re := BugResult{Status: "Ok", Bugs: []Bug{b1}}
     b, err := json.Marshal(re)                             //marshal the object to JSON
     if err != nil {
          fmt.Fprint(w, "json err: %s", err)
     }
     fmt.Fprint(w, string(b))                //write to the response
}

func updateBug(w http.ResponseWriter, r *http.Request) {
     var b Bug
     c, err := ioutil.ReadAll(r.Body)        //read the string from body and unmarshal
     fmt.Println("updateBug called with Body=" + string(c))

     json.Unmarshal(c, &b)

     fmt.Println("updateBug called with Id=" + b.Id)
     fmt.Println("updateBug called with BugNumber=" + b.BugNumber)
     fmt.Println("updateBug called with BugName=" + b.BugName)
     fmt.Println("updateBug called with BugDesn=" + b.BugDesn)

     re := BugResult{Status: "OK", Bugs: []Bug{b}}
     re_json, err := json.Marshal(re)
     if err != nil {
          fmt.Fprint(w, "json err: %s", err)
     }
     fmt.Fprint(w, string(re_json))
}

func deleteBug(w http.ResponseWriter, r *http.Request) {
     id := mux.Vars(r)["Id”]                                    //get the param from Path
     fmt.Println("deleteBug called with Id = ", id)

     re := BugResult{Status: "OK"}
     b, err := json.Marshal(re)
     if err != nil {
          fmt.Fprint(w, "json err: %s", err)
     }
     fmt.Fprint(w, string(b))
}

func addBug(w http.ResponseWriter, r *http.Request) {
     var b Bug
     content, err := ioutil.ReadAll(r.Body)
     fmt.Println("addBug called with Body=" + string(content))

     json.Unmarshal(content, &b)
     fmt.Println("addBug called with BugNumber=" + b.BugNumber)
     fmt.Println("addBug called with BugName=" + b.BugName)
     fmt.Println("addBug called with BugDesn=" + b.BugDesn)

     re := BugResult{Status: "OK", Bugs: []Bug{b}}
     re_json, err := json.Marshal(re)
     if err != nil {
          fmt.Fprint(w, "json err: %s", err)
     }
     fmt.Fprint(w, string(re_json))
}

func listBug(w http.ResponseWriter, r *http.Request) {
     b1 := Bug{Id: "1", BugNumber: "bug1", BugName: "bug1", BugDesn: "desn1"}
     b2 := Bug{Id: "2", BugNumber: "bug2", BugName: "bug2", BugDesn: "desn2"}
     re := BugResult{Status: "Ok", Bugs: []Bug{b1, b2}}
     b, err := json.Marshal(re)
     if err != nil {
          fmt.Fprint(w, "json err: %s", err)
     }
     fmt.Fprint(w, string(b))
}

func main() {
     router := mux.NewRouter()
     router.HandleFunc("/bugs", listBug).Methods("GET")
     router.HandleFunc("/bugs", addBug).Methods("POST")
     router.HandleFunc("/bugs/{Id}", getBug).Methods("GET")
     router.HandleFunc("/bugs/{Id}", updateBug).Methods("PUT")
     router.HandleFunc("/bugs/{Id}", deleteBug).Methods("DELETE")

     http.Handle("/", router)
     http.ListenAndServe(":8088", nil)
}

It is not very nice since there is repeat codes like this.
     b, err := json.Marshal(re)
     if err != nil {
          fmt.Fprint(w, "json err: %s", err)
     }
     fmt.Fprint(w, string(b))
I will check how to avoid that. 


References:
https://github.com/drone/routes

https://github.com/astaxie/build-web-application-with-golang/blob/master/ebook/08.3.md
https://github.com/gorilla/mux
http://www.gorillatoolkit.org/pkg/mux

JSON handle
http://sillycat.iteye.com/blog/2065585

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值