Welcome To Golang By Example

HTTP send/receive application octet-stream request body in Go (Golang)

Overview

application/octet-stream content-type is used to transfer binary data in the HTTP request body. So application/octet-stream is used for sending files over HTTP request. Let’s see an example of both HTTP client and server in golang for sending and receiving application/octet-stream data.

Let’s create two folders first.

Also, create a file named photo.png in the client folder

HTTP Client Example

Below is the program for the same

client/main.go

package main

import (
	"bytes"
	"fmt"
	"io/ioutil"
	"log"
	"net/http"
	"time"
)

func main() {
	err := call("http://localhost:8080/photo", "POST")
	if err != nil {
		fmt.Printf("Error occurred. Err: %s", err.Error())
	}
}

func call(urlPath, method string) error {
	client := &http.Client{
		Timeout: time.Second * 10,
	}

	b, err := ioutil.ReadFile("photo.png")
	if err != nil {
		return err
	}

	req, err := http.NewRequest(method, urlPath, bytes.NewReader(b))
	if err != nil {
		return err
	}
	req.Header.Set("Content-Type", "application/octet-stream")
	rsp, _ := client.Do(req)
	if rsp.StatusCode != http.StatusOK {
		log.Printf("Request failed with response code: %d", rsp.StatusCode)
	}
	return nil
}

In the above program, we are sending the file photo.png as application/octet-stream request body in the POST request. photo.png is first converted into bytes and these bytes are sent as application/octet-stream body. For that, bytes of the file are read first

b, err := ioutil.ReadFile("photo.png")

After the file is converted into bytes, it is passed to the http.NewRequest method as below for the third argument

bytes.NewReader(b)

The bytes.NewReader returns the bytes.Reader instance. bytes.Reader implements both io.Reader and io.Writer. The http.NewRequest method accepts the io.Reader for the body part. Therefore bytes.Reader instance can be passed as the third argument to http.NewRequest

req, err := http.NewRequest(method, urlPath, bytes.NewReader(b))

Also in the above program, we are making a call to the below API

http://localhost:8080/photo

Let’s create a server that will listen on port 8080 so that we can test the above client as well. Also, the server will parse the application/octet-stream body and save it as photo.png. Let’s see the program for the server now

HTTP Server Example

Below is the program for the same.

server/main.go

package main

import (
	"io/ioutil"
	"net/http"
	"os"
)

func main() {
	createEmployeeHanlder := http.HandlerFunc(createEmployee)
	http.Handle("/photo", createEmployeeHanlder)
	http.ListenAndServe(":8080", nil)
}

func createEmployee(w http.ResponseWriter, request *http.Request) {
	d, err := ioutil.ReadAll(request.Body)
	if err != nil {
		http.Error(w, err.Error(), http.StatusBadRequest)
	}
	tmpfile, err := os.Create("./" + "photo.png")
	defer tmpfile.Close()
	if err != nil {
		http.Error(w, err.Error(), http.StatusBadRequest)
	}
	tmpfile.Write(d)

	w.WriteHeader(200)
	return
}

In the above program, we have created an API that will listen on port 8080. The API signature will be

http://localhost:8080/photo

It reads the bytes from the POST body and saves them to a file photo.png

Let’s run both the Server and the Client. Run the server first.

go run server/main.go

It will start listening to port 8080. After that run the client.

go run client/main.go

After the API is successfully executed, check at the server end. A file named photo.png will be created at the server end.