Go net/http Pack

Source: Internet
Author: User
This is a creation in Article, where the information may have evolved or changed.

Go net/http Pack

Go HTTP Client

Get requests can be directly HTTP. Get method

package mainimport ("fmt""net/http""log""reflect""bytes")func main() {resp, err := http.Get("http://www.baidu.com")if err != nil {// handle errorlog.Println(err)return}defer resp.Body.Close()headers := resp.Headerfor k, v := range headers {fmt.Printf("k=%v, v=%v\n", k, v)}fmt.Printf("resp status %s,statusCode %d\n", resp.Status, resp.StatusCode)fmt.Printf("resp Proto %s\n", resp.Proto)fmt.Printf("resp content length %d\n", resp.ContentLength)fmt.Printf("resp transfer encoding %v\n", resp.TransferEncoding)fmt.Printf("resp Uncompressed %t\n", resp.Uncompressed)fmt.Println(reflect.TypeOf(resp.Body)) // *http.gzipReaderbuf := bytes.NewBuffer(make([]byte, 0, 512))length, _ := buf.ReadFrom(resp.Body)fmt.Println(len(buf.Bytes()))fmt.Println(length)fmt.Println(string(buf.Bytes()))}

Sometimes you need to set the header parameters, cookies and other data at the time of the request, you can use HTTP. Do method.

package mainimport ("net/http""strings""fmt""io/ioutil""log""encoding/json")func main() {client := &http.Client{}req, err := http.NewRequest("POST", "http://www.maimaiche.com/loginRegister/login.do",strings.NewReader("mobile=xxxxxxxxx&isRemberPwd=1"))if err != nil {log.Println(err)return}req.Header.Set("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8")resp, err := client.Do(req)defer resp.Body.Close()body, err := ioutil.ReadAll(resp.Body)if err != nil {log.Println(err)return}fmt.Println(resp.Header.Get("Content-Type")) //application/json;charset=UTF-8type Result struct {Msg    stringStatus stringObj    string}result := &Result{}json.Unmarshal(body, result) //解析json字符串if result.Status == "1" {fmt.Println(result.Msg)} else {fmt.Println("login error")}fmt.Println(result)}

If you use the HTTP Post method, you can use Http.post or HTTP directly. Postform,

package mainimport ("net/http""strings""fmt""io/ioutil")func main() {resp, err := http.Post("http://www.maimaiche.com/loginRegister/login.do","application/x-www-form-urlencoded",strings.NewReader("mobile=xxxxxxxxxx&isRemberPwd=1"))if err != nil {fmt.Println(err)return}defer resp.Body.Close()body, err := ioutil.ReadAll(resp.Body)if err != nil {fmt.Println(err)return}fmt.Println(string(body))}

http. Postform method,

package mainimport ("net/http""fmt""io/ioutil""net/url")func main() {postParam := url.Values{"mobile":      {"xxxxxx"},"isRemberPwd": {"1"},}resp, err := http.PostForm("http://www.maimaiche.com/loginRegister/login.do", postParam)if err != nil {fmt.Println(err)return}defer resp.Body.Close()body, err := ioutil.ReadAll(resp.Body)if err != nil {fmt.Println(err)return}fmt.Println(string(body))}

Go HTTP Server Side

Fundamentals of Everything: Servemux and Handler

The Go language handles HTTP requests mainly related to two things: Servemux and Handler.

Servrmux is essentially an HTTP request router (or called a multiplexer, multiplexor). It compares the received request to a list of pre-defined URL paths and then invokes the associated processor (Handler) when matching to the path.

The processor (Handler) is responsible for outputting the header and body of the HTTP response. Anything that satisfies the HTTP. The objects of the handler interface are available as a single processor. In layman's words, an object can be signed with the Servehttp method as follows:

ServeHTTP(http.ResponseWriter, *http.Request)

The Go language's HTTP package comes with several functions that are used as common processors, such as Fileserver,notfoundhandler and Redirecthandler. Let's start with a simple, concrete example:

package mainimport ("log""net/http")func main() {mux := http.NewServeMux()rh := http.RedirectHandler("http://www.baidu.com", 307)mux.Handle("/foo", rh)log.Println("Listening...")http.ListenAndServe(":3000", mux)}

Quickly over the code:

    1. In the main function we only use HTTP. Newservemux function to create an empty servemux.
    2. Then we use HTTP. The Redirecthandler function creates a new processor that performs a 307 redirect operation to Http://www.baidu.com for all requests received.
    3. Next we use the Servemux.handle function to register the processor with the newly created SERVEMUX, so it receives all requests on the URL path/foo to the processor.
    4. Finally we created a new server and passed HTTP. The Listenandserve function listens for all incoming requests by passing the Servemux that you just created to match the corresponding processor for the request.

Then access the Http://localhost:3000/foo in the browser and you should be able to see that the request has been redirected successfully.

Perspicacious you should be able to notice something interesting: Listenandserver's function signature is listenandserve (addr string, handler handler), but the second argument we pass is a servemux.

The reason we can do this is because Servemux also has a servehttp method, so it's also a legitimate Handler.

For me, using Servermux as a special handler is a simplification. Instead of outputting the response itself, it passes the request to the other Handler registered to it. This does not sound a significant leap at first-but it is a very common use to link Handler in Go.

Custom Processor (handlers)

Let's create a custom processor that will output the current local time in a specific format:

type timeHandler struct {format string}func (th *timeHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {tm := time.Now().Format(th.format)w.Write([]byte("The time is: " + tm))}

The code itself is not the focus in this example.

The real point is that we have an object (in this case a timerhandler struct, but it can also be a string, a function, or anything), and we implement a servehttp (HTTP) on this object. Responsewriter, *http. Request) Signature method, which is all we need to create a processor.

Let's integrate this into a specific example:

//File: main.gopackage mainimport ("log""net/http""time")type timeHandler struct {format string}func (th *timeHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {tm := time.Now().Format(th.format)w.Write([]byte("The time is: " + tm))}func main() {mux := http.NewServeMux()th := &timeHandler{format: time.RFC1123}mux.Handle("/time", th)log.Println("Listening...")http.ListenAndServe(":3000", mux)}

In the main function, we initialize the Timehandler as a regular struct, and get its address with the & symbol. Then, as in the previous example, we use a mux. The Handle function to register it with the Servermux.

Now when we run this application, Servermux will hand over any requests for/time directly to the Timehandler.servehttp method.

Visit this address to see the effect: Http://localhost:3000/time.

Note that we can easily reuse Timehandler in multiple routes:

//File: main.gopackage mainimport ("log""net/http""time")type timeHandler struct {format string}func (th *timeHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {tm := time.Now().Format(th.format)w.Write([]byte("The time is: " + tm))}func main() {mux := http.NewServeMux()th1123 := &timeHandler{format: time.RFC1123}mux.Handle("/time/rfc1123", th1123)th3339 := &timeHandler{format: time.RFC3339}mux.Handle("/time/rfc3339", th3339)log.Println("Listening...")http.ListenAndServe(":3000", mux)}

To use a function as a processor

For simple cases (such as the example above), it is a little cumbersome to define a new custom type with a Serverhttp method. Let's look at another way, we're using HTTP. The Handlerfunc type allows a regular function to satisfy the condition as a Handler interface.

Any have func (HTTP. Responsewriter, *http. Request) can be converted to a handlerfunc type. This is useful because the Handlerfunc object has a built-in Servehttp method that intelligently and conveniently invokes the content of the function we originally provided.

Let's use this technique to re-implement the Timehandler application:

package mainimport ("log""net/http""time")func timeHandler(w http.ResponseWriter, r *http.Request) {tm := time.Now().Format(time.RFC1123)w.Write([]byte("The time is: " + tm))}func main() {mux := http.NewServeMux()// Convert the timeHandler function to a HandlerFunc typeth := http.HandlerFunc(timeHandler)// And add it to the ServeMuxmux.Handle("/time", th)log.Println("Listening...")http.ListenAndServe(":3000", mux)}

In fact, registering to Servemux is a common use when converting a function to Handlerfunc, so the Go language provides a convenient way to do this: the Servermux.handlerfunc method.

We use a convenient way to rewrite the main () function to look like this:

package mainimport ("log""net/http""time")func timeHandler(w http.ResponseWriter, r *http.Request) {tm := time.Now().Format(time.RFC1123)w.Write([]byte("The time is: " + tm))}func main() {mux := http.NewServeMux()mux.HandleFunc("/time", timeHandler)log.Println("Listening...")http.ListenAndServe(":3000", mux)}

In most cases, this function works well in the same way as the processor. But when things start to get more complicated, there are some limitations.

You may have noticed that, unlike the previous approach, we had to hardcode the time format into the Timehandler method. What if we want to pass some information or variables to the processor from the main () function?

An elegant way is to put our processor in a closure and bring the variables we want to use:

//File: main.gopackage mainimport ("log""net/http""time")func timeHandler(format string) http.Handler {fn := func(w http.ResponseWriter, r *http.Request) {tm := time.Now().Format(format)w.Write([]byte("The time is: " + tm))}return http.HandlerFunc(fn)}func main() {mux := http.NewServeMux()th := timeHandler(time.RFC1123)mux.Handle("/time", th)log.Println("Listening...")http.ListenAndServe(":3000", mux)}

The Timehandler function now has a more subtle identity. In addition to encapsulating a function as Handler (as we did before), we now use it to return a processor. This mechanism has two key points:

The first is to create an FN, an anonymous function that encapsulates the format variable into a closure. The nature of closures allows the processor to access the format variable in the local scope in any case.

Next our closure function satisfies the func (HTTP. Responsewriter, *http. Request) signature. If you remember what we said before, this means that we can convert it to a handlerfunc type (satisfies the Http.handler interface). Our Timehandler function then returns after the converted Handlerfunc.

In the example above we can already pass a simple string to the processor. But in real-world applications, you can use this method to pass database connections, template groups, or other application-level contexts. Using global variables is also a good choice, and the additional benefit is to write more elegant self-contained processors for testing.

You may have seen the same wording, like this:

func timeHandler(format string) http.Handler {return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {tm := time.Now().Format(format)w.Write([]byte("The time is: " + tm))})}

Or, when returning, use an implicit conversion to the Handlerfunc type:

func timeHandler(format string) http.HandlerFunc {return func(w http.ResponseWriter, r *http.Request) {tm := time.Now().Format(format)w.Write([]byte("The time is: " + tm))}}

More Convenient Defaultservemux

You may have seen Defaultservemux in many places, from the simplest Hello world example to the source of the go language.

It took me a long time to realize that Defaultservermux didn't have any special place. Defaultservermux is the Servermux we used earlier, but it was initialized automatically with the NET/HTTPP package initialized. The related lines in the Go source code are as follows:

var DefaultServeMux = NewServeMux()

The Net/http package provides a set of shortcuts to match DefaultServeMux:http.Handle and HTTP. Handlefunc. The only difference between these functions and the functions of similar names we've seen before is that they register the processor with the Defaultservermux, and before we register it with the Servemux we created.

In addition, the Listenandserve uses Defaultservemux if the other processor is not provided (that is, the second parameter is set to nil).

So, as a final step, we use Defaultservemux to rewrite our Timehandler application:

//File: main.gopackage mainimport ("log""net/http""time")func timeHandler(format string) http.Handler {fn := func(w http.ResponseWriter, r *http.Request) {tm := time.Now().Format(format)w.Write([]byte("The time is: " + tm))}return http.HandlerFunc(fn)}func main() {// Note that we skip creating the ServeMux...var format string = time.RFC1123th := timeHandler(format)// We use http.Handle instead of mux.Handle...http.Handle("/time", th)log.Println("Listening...")// And pass nil as the handler to ListenAndServe.http.ListenAndServe(":3000", nil)}

======end======

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.