In the development process, it is inevitable to call other apis of the development team. Sometimes these apis provide HTTP interfaces or RPC interfaces. When the service is HTTP interface, if the back-end request interface is needed, the request needs to be sent through THE HTTP client

Request scenario

  • When you upload the file, you need to attach the request parameters
  • Sends the JSON request body

The overall train of thought

  • Put the request content into an output stream
  • Take the output stream as a parameter to the request
  • Send the request

Request parameters + file upload

  • Prepare a buffer to buffer the request parameters and files
  • Create a multipartWriter for writing request parameters and files
  • Write request parameters and files in Writer
  • Send the request

If you want to upload a file, with a description of the file, in HTML it looks like this

<form
    action="http://upload.com/post"
    method="post"
    enctype="multipart/form-data"
>
  <input type="text" name="description"/>
  <input type="file" name="fileName">
  <input type="submit">
</form>
Copy the code

So without further ado about the code

func uploadFile(fileName string, targetUrl string) error {
	bodyBuf := &bytes.Buffer{}
	bw := multipart.NewWriter(bodyBuf)
  // Simulate the text field in the form
	bw.WriteField("description"."A good book.")
	// Simulate the file upload field in the form
	fileWriter, err := bw.CreateFormFile("fileName", fileName)
	iferr ! =nil {
		fmt.Println("write to buffer error")
		return err
	}
	// Open the file to be uploaded
	fh, err := os.Open(fileName)
	iferr ! =nil {
		fmt.Println("open file error")
		return err
	}
	defer fh.Close()

	// Copy the file stream to the created file upstream
	_, err = io.Copy(fileWriter, fh)
	iferr ! =nil {
		return err
	}
	//multipart/form-data
	contentType := bw.FormDataContentType()
	bw.Close()
	// Send the request
	resp, err := http.Post(targetUrl, contentType, bodyBuf)
	iferr ! =nil {
		return err
	}
	defer resp.Body.Close()
	respBody, err := ioutil.ReadAll(resp.Body)
	iferr ! =nil {
		return err
	}
	fmt.Println(respBody)
	return nil
}
Copy the code

Sending JSON Data

  • Create JSON encoder
  • Encodes a structure into a byte stream
  • Take the byte stream as the request parameter
  • Send the request
/ / the server
func Handeler(respWriter http.ResponseWriter, req *http.Request) {
	if req.Method == "POST" {
		msg := Msg{}
		json.NewDecoder(req.Body).Decode(&msg)
		fmt.Println("des:", msg.Description)
	}
	respWriter.Write([]byte("every thing is ok!"))}func main(a) {
	http.HandleFunc("/test", Handeler)
	http.ListenAndServe(": 8080".nil)}/ / the client
type Msg struct {
	Description string `json:"description"`
}
func main(a) {
	msg := Msg{"test"}
	bf := &bytes.Buffer{}
  // Create a JSON encoder and encode the struct structure
	err := json.NewEncoder(bf).Encode(msg)
	iferr ! =nil {
		fmt.Println("encoding error")
		os.Exit(- 1)}// Send the request
	req, err := http.NewRequest("POST"."http://localhost:8080/test", bf)
	client := &http.Client{
		Timeout: time.Millisecond * 100,
	}
	resp, err := client.Do(req)
	fmt.Println(resp.Status)
	resByte, _ := ioutil.ReadAll(resp.Body)
	fmt.Println(string(resByte))
}
Copy the code

Hit the pit

  • The Body of http.Response needs to be read by ioutil
    • Instead of calling the resp.body.read () method directly, doing so would not read the response. Body.read() returns error when the network connection fails or the server terminates the request response