type Server struct { Addr string // TCP address to listen on, ":http" if empty Handler Handler // handler to invoke, http.DefaultServeMux if nil ReadTimeout time.Duration // maximum duration before timing out read of the request WriteTimeout time.Duration // maximum duration before timing out write of the response MaxHeaderBytes int // maximum size of request headers, DefaultMaxHeaderBytes if 0 TLSConfig *tls.Config // optional TLS config, used by ListenAndServeTLS // TLSNextProto optionally specifies a function to take over // ownership of the provided TLS connection when an NPN // protocol upgrade has occurred. The map key is the protocol // name negotiated. The Handler argument should be used to // handle HTTP requests and will initialize the Request's TLS // and RemoteAddr if not already set. The connection is // automatically closed when the function returns. TLSNextProto map[string]func(*Server, *tls.Conn, Handler) // ConnState specifies an optional callback function that is // called when a client connection changes state. See the // ConnState type and associated constants for details. ConnState func(net.Conn, ConnState) // ErrorLog specifies an optional logger for errors accepting // connections and unexpected behavior from handlers. // If nil, logging goes to os.Stderr via the log package's // standard logger. ErrorLog *log.Logger disableKeepAlives int32 // accessed atomically. }
type ServeMux struct { mu sync.RWMutex m map[string]muxEntry hosts bool // whether any patterns contain hostnames } type muxEntry struct { explicit bool h Handler pattern string }
package main import ( "io" "log" "net/http" ) type a struct{} type b struct{} func (*a) ServeHTTP(w http.ResponseWriter, r *http.Request) { //log.Println("the request url", r.RequestURI) //log.Println("r.Method", r.Method) io.WriteString(w, "hello world by mux the route is /a.") } func (*b) ServeHTTP(w http.ResponseWriter, r *http.Request) { io.WriteString(w, "hello world by mux the route is /b.") } func main() { mux := http.NewServeMux() //往mux中注册新的路由 mux.Handle("/a", &a{}) mux.Handle("/b", &b{}) //开启服务 具体的路由操作由 新生成的mux来负责 err := http.ListenAndServe(":8080", mux) if err != nil { log.Println(err.Error()) } }
func (mux *ServeMux) Handle(pattern string, handler Handler) { mux.mu.Lock() defer mux.mu.Unlock() if pattern == "" { panic("http: invalid pattern " + pattern) } if handler == nil { panic("http: nil handler") } if mux.m[pattern].explicit { panic("http: multiple registrations for " + pattern) } mux.m[pattern] = muxEntry{explicit: true, h: handler, pattern: pattern} if pattern[0] != '/' { mux.hosts = true } // Helpful behavior: // If pattern is /tree/, insert an implicit permanent redirect for /tree. // It can be overridden by an explicit registration. n := len(pattern) if n > 0 && pattern[n-1] == '/' && !mux.m[pattern[0:n-1]].explicit { // If pattern contains a host name, strip it and use remaining // path for redirect. path := pattern if pattern[0] != '/' { // In pattern, at least the last character is a '/', so // strings.Index can't be -1. path = pattern[strings.Index(pattern, "/"):] } mux.m[pattern[0:n-1]] = muxEntry{h: RedirectHandler(path, StatusMovedPermanently), pattern: pattern} } }
package main import ( "log" "net/http" "strconv" "github.com/emicklei/go-restful" "github.com/emicklei/go-restful/swagger" ) type User struct { Id, Name string } type UserResource struct { // normally one would use DAO (data access object) users map[string]User } //将路由以webservice的方式注册到container中 func (u UserResource) Register(container *restful.Container) { ws := new(restful.WebService) //这个是根路径 ws. Path("/users"). Doc("Manage Users"). Consumes(restful.MIME_XML, restful.MIME_JSON). Produces(restful.MIME_JSON, restful.MIME_XML) // you can specify this per route as well //后面是根路径之后的每个具体的方法 ws.Route(ws.GET("/{user-id}").To(u.findUser). // docs Doc("get a user"). Operation("findUser"). Param(ws.PathParameter("user-id", "identifier of the user").DataType("string")). Writes(User{})) // on the response ws.Route(ws.PUT("/{user-id}").To(u.updateUser). // docs Doc("update a user"). Operation("updateUser"). Param(ws.PathParameter("user-id", "identifier of the user").DataType("string")). ReturnsError(409, "duplicate user-id", nil). Reads(User{})) // from the request ws.Route(ws.POST("").To(u.createUser). // docs Doc("create a user"). Operation("createUser"). Reads(User{})) // from the request ws.Route(ws.DELETE("/{user-id}").To(u.removeUser). // docs Doc("delete a user"). Operation("removeUser"). Param(ws.PathParameter("user-id", "identifier of the user").DataType("string"))) container.Add(ws) } // GET http://localhost:8080/users/1 // func (u UserResource) findUser(request *restful.Request, response *restful.Response) { ... } // POST http://localhost:8080/users // <User><Name>Melissa</Name></User> // func (u *UserResource) createUser(request *restful.Request, response *restful.Response) { ... } // PUT http://localhost:8080/users/1 // <User><Id>1</Id><Name>Melissa Raspberry</Name></User> // func (u *UserResource) updateUser(request *restful.Request, response *restful.Response) { ... } // DELETE http://localhost:8080/users/1 // func (u *UserResource) removeUser(request *restful.Request, response *restful.Response) { ... } func main() { //创建一个新的container 将user的路由放到container当中 wsContainer := restful.NewContainer() u := UserResource{map[string]User{}} u.Register(wsContainer) //配置swagger config := swagger.Config{ WebServices: wsContainer.RegisteredWebServices(), // you control what services are visible WebServicesUrl: "http://localhost:8080", ApiPath: "/apidocs.json", // Optionally, specifiy where the UI is located SwaggerPath: "/apidocs/", SwaggerFilePath: "/Users/emicklei/xProjects/swagger-ui/dist"} swagger.RegisterSwaggerService(config, wsContainer) //开启服务 监听8080端口 log.Printf("start listening on localhost:8080") server := &http.Server{Addr: ":8080", Handler: wsContainer} log.Fatal(server.ListenAndServe()) }