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
+9.1k Golang : Find the length of big.Int variable example
+22.6k Golang : Test file read write permission example
+21.3k SSL : How to check if current certificate is sha1 or sha2
+19.3k Golang : Close channel after ticker stopped example
+5.7k Golang : Extract unicode string from another unicode string example
+12.2k Golang : "https://" not allowed in import path
+19.2k Golang : Get current URL example
+44.4k Golang : Use wildcard patterns with filepath.Glob() example
+12.2k Elastic Search : Return all records (higher than default 10)
+19.1k Golang : Fix cannot download, $GOPATH not set error
+7.3k Golang : Get YouTube playlist
+14.2k Golang : On enumeration