An implementation of the remoteStorage protocol written in Go.
go get -u github.com/cvanloo/rmsgopackage main
import (
    "os"
    "github.com/cvanloo/rmsgo"
)
const (
    PersistFile = "/var/rms/persist"
    RemoteRoot  = "/storage/"
    StorageRoot = "/var/rms/storage/"
)
func main() {
    opts, err := rmsgo.Configure(RemoteRoot, StorageRoot)
    if err != nil {
        log.Fatal(err)
    }
    opts.UseErrorHandler(func(err error) {
        log.Fatalf("remote storage: unhandled error: %v", err)
    })
    opts.UseAuthentication(func(r *http.Request, bearer string) (rmsgo.User, bool) {
        // [!] TODO: Your authentication logic here...
        //       Return one of your own users.
        return rmsgo.UserReadWrite{}, true
    })
    persistFile, err := os.Open(PersistFile)
    if err != nil {
        log.Fatal(err)
    }
    // Restore server state
    err = rmsgo.Load(persistFile)
    if err != nil {
        log.Fatal(err)
    }
    defer func() {
        // At shutdown: persist server state
        persistFile.Truncate(0)
        persistFile.Seek(0, io.SeekStart)
        err = rmsgo.Persist(persistFile)
        if err != nil {
            log.Fatal(err)
        }
    }()
    // Register remote storage endpoints to the http.DefaultServeMux
    rmsgo.Register(nil)
    http.ListenAndServe(":8080", nil) // [!] TODO: Use TLS
}func logger(next http.Handler) http.Handler {
    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        start := time.Now()
        lrw := rmsgo.NewLoggingResponseWriter(w)
        // [!] pass request on to remote storage server
        next.ServeHTTP(lrw, r)
        duration := time.Since(start)
        // - Mom! Can we have slog?
        // - No darling, we have slog at home.
        // slog at home:
        log.Printf("%v", map[string]any{
            "method":   r.Method,
            "uri":      r.RequestURI,
            "duration": duration,
            "status":   lrw.Status,
            "size":     lrw.Size,
        })
    })
}
func main() {
    opts, err := rmsgo.Configure(RemoteRoot, StorageRoot)
    if err != nil {
        log.Fatal(err)
    }
    // [!] Register custom middleware
    opts.UseMiddleware(logger)
    // [!] Other configuration...
    rmsgo.Register(nil)
    http.ListenAndServe(":8080", nil) // [!] TODO: Use TLS
}- [Required] Configure- remoteRoot: URL path below which the server is accessible. (e.g. "/storage/")
- storageRoot: Location on server's file system to store remoteStorage documents. (e.g. "/var/rms/storage/")
 
- [Recommended] UseAuthenticationconfigure how requests are authenticated and control access permissions of users.- There are some default users, but for fine grained control custom users can be provided.
- UserReadOnlyhas read access to any folder/document
- UserReadWritehas read and write access to any folder/document
- UserReadPubliccan only read public folders
 
- [Recommended] UseAllowedOriginsallow-list of hosts that may make requests to the server. Per default any host is allowed.
- [Optional] UseAllowOriginfor more control, specify a function that decides based on the request if it is allowed or not. If this option is specified,UseAllowedOriginshas no effect.
- [Not Recommended] AllowAnyReadWriteallow even unauthenticated requests to create, read, and delete any documents on the server. Has no effect ifUseAuthenticationis specified.
- [Optional] UseErrorHandlerto catch unhandled errors. Default behavior is tolog.Printfthe error.
- [Optional] UseMiddlewareto intercept requests before they are passed to the remote storage handler.
Register registers the remote storage handler to a ServeMux.