gofileserver

GoLang: Update file that is served by FileServer


I am serving a directory using FileServer as follows:

go func() {
  fs := http.FileServer(http.Dir("./view"))
  err := http.ListenAndServe(":8000", fs)
  if err != nil {
    log.Fatal("ListenAndServe: ", err)
  }
}()

Inside the view directory I have an index.html file, which I am trying to update while the view directory is being served. I observe that the append commands block and update the file only after I stop serving the directory.

Below is the code to modify the file:

func AppendToFile() {
  f, err := os.OpenFile("./view/index.html", os.O_RDWR, 0644)
  if err != nil {
    panic(err)
  }
  defer f.Close()
  // This assumes that the file ends with </body></html>
  f.Seek(-15, 2)
  if _, err = f.WriteString("test test test\n"); err != nil {
    panic(err)
  }
  if _, err = f.WriteString("</body></html>\n"); err != nil {
    panic(err)
  }
}

Is this the expected behavior?

Thank you!


Solution

  • http.FileServer function just returns a handler. So it is not blocking the filesystem. The problem in here might be related with the offset of your file. I've tried in my machine and it worked without any problem.

    I've modified your code to this;

    package main
    
    import (
        "net/http"
        "os"
        "time"
    )
    
    func main() {
        t := time.NewTicker(time.Second)
        defer t.Stop()
        go func() {
            srv := http.FileServer(http.Dir("./test"))
            http.ListenAndServe(":8080", srv)
        }()
    
        for {
            select {
            case <-t.C:
                appendToFile()
            }
        }
    }
    
    func appendToFile() {
        f, err := os.OpenFile("./test/index.html", os.O_RDWR, 0644)
        if err != nil {
            panic(err)
        }
        defer f.Close()
        // This assumes that the file ends with </body></html>
        f.Seek(-16, 2)
        if _, err = f.WriteString("test test test\n"); err != nil {
            panic(err)
        }
        if _, err = f.WriteString("</body></html>\n"); err != nil {
            panic(err)
        }
    }
    

    In index.html I put blank document initially,

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Document</title>
    </head>
    <body>
    
    </body></html>
    

    PS: It is better to check offset of first, then write the string to that position.