Golang : How to transmit update file to client by HTTP request example
Alright, got a friend here that wants a simple Golang http server that will handle updates to his software. Basically, his Android/iOS/desktop app needs to be updated from time to time with the latest data file. At the same time, he is also concern about security and don't want to serve the update files to any clients that request it.
Below is a simple update server that will transmit the update file upon request by any client. The client will initiate HTTP request to the update server and it will perform some sanity checks before transmitting.
The only authentication is that the request must provide the correct parameter in order to initiate the server to start transmitting the file. If the client's request parameter is incorrect, this program will not proceed.
Here you go!
package main
import (
"io"
"log"
"net"
"net/http"
"os"
"strconv"
)
func main() {
http.HandleFunc("/", downloadToClient)
port := ":8080"
log.Println("Download update files from localhost" + port)
err := http.ListenAndServe(port, nil)
if err != nil {
log.Println(err)
}
}
func downloadToClient(w http.ResponseWriter, r *http.Request) {
// there is where we want to do some simple verification
// if the app(client) did not supply the correct parameter, which is - "updatefile"
// abort!
fileName := r.URL.Query().Get("updatefile")
if fileName == "" {
// return 400 HTTP response code for BAD REQUEST
http.Error(w, "Update failed due to malformed URL.", 400)
return
}
// For more advance authentication, see
// https://www.socketloop.com/tutorials/golang-simple-client-server-hmac-authentication-without-ssl-example
// get client ip address
ip, _, _ := net.SplitHostPort(r.RemoteAddr)
log.Println("Transmiting to client at " + ip + " : " + fileName)
// Do we have the update with the given filename?
updateFile, err := os.Open(fileName)
defer updateFile.Close()
if err != nil {
// return 404 HTTP response code for File not found
http.Error(w, "Update file not found.", 404)
return
}
// Prepare the update file to be sent over to the client(which in this case is an APP)
fileHeader := make([]byte, 512) // 512 bytes is sufficient for http.DetectContentType() to work
updateFile.Read(fileHeader) // read the first 512 bytes from the updateFile
fileType := http.DetectContentType(fileHeader) // set the type
fileInfo, _ := updateFile.Stat()
fileSize := fileInfo.Size()
//Transmit the headers
w.Header().Set("Expires", "0")
w.Header().Set("Content-Transfer-Encoding", "binary")
w.Header().Set("Content-Control", "private, no-transform, no-store, must-revalidate")
w.Header().Set("Content-Disposition", "attachment; filename="+fileName)
w.Header().Set("Content-Type", fileType)
w.Header().Set("Content-Length", strconv.FormatInt(fileSize, 10))
//Send the file
updateFile.Seek(0, 0) // reset back to position since we've read first 512 bytes of data previously
io.Copy(w, updateFile) // transmit the updatefile bytes to the client
return
}
Example of proper execution, the server has an update file call
data.zip
Run the server and point your browser, curl or POST request to
localhost:8080?updatefile=data.zip
NOTE: For production use, it is advisable to make sure that any requests made either by APP or browsers to be authenticated first with HMAC or some secret update codes. This is to ensure your app or service integrity.
References :
https://www.socketloop.com/tutorials/golang-force-download-file-example
See also : Golang : Force download file example
By Adam Ng(黃武俊)
IF you gain some knowledge or the information here solved your programming problem. Please consider donating to the less fortunate or some charities that you like. Apart from donation, planting trees, volunteering or reducing your carbon footprint will be great too.
Advertisement
Tutorials
+4.9k Unix/Linux : secure copying between servers with SCP command examples
+8.8k Golang : Heap sort example
+11.6k CodeIgniter : Import Linkedin data
+13.1k Swift : Convert (cast) Int to String ?
+19.3k Golang : Check whether a network interface is up on your machine
+16.5k Golang : Send email and SMTP configuration example
+12k Golang : Convert decimal number(integer) to IPv4 address
+6.2k Golang : Dealing with backquote
+5.8k Golang : Struct field tags and what is their purpose?
+7.9k Golang : Lock executable to a specific machine with unique hash of the machine
+11k Golang : Removes punctuation or defined delimiter from the user's input
+8.2k Golang : Check from web if Go application is running or not