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
+7k CloudFlare : Another way to get visitor's real IP address
+40.8k Golang : How to count duplicate items in slice/array?
+24.8k Golang : Create PDF file from HTML file
+19k Golang : Delete item from slice based on index/key position
+41.2k Golang : Convert string to array/slice
+10.9k Golang : Web routing/multiplex example
+15.4k Golang : Get checkbox or extract multipart form data value example
+10.2k Golang : Meaning of omitempty in struct's field tag
+5.4k Golang : Frobnicate or tweaking a string example
+5.8k AWS S3 : Prevent Hotlinking policy
+6.9k Nginx : How to block user agent ?