Code Monkey home page Code Monkey logo

joint's Introduction

Joint

Provides access to files in ISO-9660 images, FTP-servers, SFTP-servers, WebDAV-servers by standard file system interfaces. Contains cache with reusable connections to endpoints.

Go Reference Go Report Card Hits-of-Code

Goals

You can read the contents of a folder on an FTP-server either sequentially through one connection, but then this will take a lot of time, or by opening multiple connections, in which case too many connections will be opened for multiple requests. This library uses joints, which hold the connection to the FTP-server after reading a file, or some kind of access, after closing the file, they are placed into the cache, and can be reused later. If the connection has not been used for a certain time, it is reset.

Examples

HTTP file server with WebDAV content

package main

import (
    "log"
    "net/http"

    jnt "github.com/schwarzlichtbezirk/hms/joint"
)

// Open http://localhost:8080/ in browser
// to get a list of files in WebDAV-server for given user.
func main() {
    var sp = jnt.NewSubPool(nil, "https://music:[email protected]/webdav/")
    defer sp.Close()
    http.Handle("/", http.FileServer(http.FS(sp)))
    log.Fatal(http.ListenAndServe(":8080", nil))
}

HTTP file server with ISO-image content

package main

import (
    "log"
    "net/http"

    jnt "github.com/schwarzlichtbezirk/hms/joint"
)

// Open http://localhost:8080/ in browser
// to get a list of files in ISO-image.
func main() {
    // create map with caches for all currently unused joints
    var jp = jnt.NewJointPool()
    defer jp.Close()
    // file system, that shares content of "testdata" folder
    // and all embedded into ISO-disks files
    var sp, err = jp.Sub("testdata")
    if err != nil {
        log.Fatal(err)
    }
    http.Handle("/", http.FileServer(http.FS(sp)))
    log.Fatal(http.ListenAndServe(":8080", nil))
}

HTTP file server with ISO, WebDAV, FTP and SFTP content

package main

import (
    "log"
    "net/http"

    jnt "github.com/schwarzlichtbezirk/hms/joint"
)

// http://localhost:8080/iso/ - content of ISO-image
// http://localhost:8080/dav/ - content of WebDAV-server
// http://localhost:8080/ftp/ - content of FTP-server
// http://localhost:8080/sftp/ - content of SFTP-server
func main() {
    // create map with caches for all currently unused joints
    var jp = jnt.NewJointPool()
    defer jp.Close()
    // handle list of resources as binded file systems
    http.Handle("/iso/", http.StripPrefix("/iso/", http.FileServer(
        http.FS(jnt.NewSubPool(jp, "testdata/external.iso")))))
    http.Handle("/dav/", http.StripPrefix("/dav/", http.FileServer(
        http.FS(jnt.NewSubPool(jp, "https://music:[email protected]/webdav/")))))
    http.Handle("/ftp/", http.StripPrefix("/ftp/", http.FileServer(
        http.FS(jnt.NewSubPool(jp, "ftp://music:[email protected]:21")))))
    http.Handle("/sftp/", http.StripPrefix("/sftp/", http.FileServer(
        http.FS(jnt.NewSubPool(jp, "sftp://music:[email protected]:22")))))
    log.Fatal(http.ListenAndServe(":8080", nil))
}

Files reading by joints

package main

import (
    "fmt"
    "io"
    "io/fs"
    "log"

    jnt "github.com/schwarzlichtbezirk/joint"
)

func main() {
    var err error

    // Create joint to ISO-9660 image.
    var j jnt.Joint = &jnt.IsoJoint{}
    if err = j.Make(nil, "testdata/external.iso"); err != nil {
        log.Fatal(err)
    }
    // Cleanup drops joint's link at the end. Any not cached joints
    // should be destroyed by Cleanup call.
    defer j.Cleanup()

    // Working with file object returned by Open-function.
    // Open-function returns joint casted to fs.File.
    var f fs.File
    if f, err = j.Open("fox.txt"); err != nil {
        log.Fatal(err)
    }
    var b []byte
    if b, err = io.ReadAll(f); err != nil { // read from file
        log.Fatal(err)
    }
    fmt.Println(string(b))
    f.Close()

    // Working with joint explicitly. If joint is received from cache,
    // Close-call will return joint back to cache.
    if _, err = j.Open("data/lorem1.txt"); err != nil {
        log.Fatal(err)
    }
    if _, err = io.Copy(os.Stdout, j); err != nil { // read from joint
        log.Fatal(err)
    }
    j.Close() // f.Close() and j.Close() do the same work
}

Open nested ISO-image by joints

package main

import (
    "io"
    "io/fs"
    "log"
    "os"

    jnt "github.com/schwarzlichtbezirk/joint"
)

func main() {
    var err error

    // Create joint to external ISO-image.
    // This joint will be removed by top-level joint.
    var j1 jnt.Joint = &jnt.IsoJoint{}
    if err = j1.Make(nil, "testdata/external.iso"); err != nil {
        log.Fatal(err)
    }
    defer j1.Cleanup() // Cleanup or Close can be called twice

    // Create top-level joint to internal ISO-image placed inside of first.
    var j2 jnt.Joint = &jnt.IsoJoint{}
    if err = j2.Make(j1, "disk/internal.iso"); err != nil {
        log.Fatal(err)
    }
    // Top-level joint calls inherited Cleanup, so this call can be one.
    defer j2.Cleanup()

    // Open file at internal ISO-image.
    var f fs.File
    if f, err = j2.Open("fox.txt"); err != nil {
        log.Fatal(err)
    }
    defer f.Close() // Close file and joint can be reused

    io.Copy(os.Stdout, f)
}

Simple file reading

package main

import (
    "io"
    "log"
    "os"

    jnt "github.com/schwarzlichtbezirk/joint"
)

var jp = jnt.NewJointPool()

func main() {
    // Open file and get the joint by one call.
    var j, err = jp.Open("testdata/external.iso/disk/internal.iso/docs/doc1.txt")
    if err != nil {
        log.Fatal(err)
    }
    defer j.Cleanup()

    io.Copy(os.Stdout, j)
}

Tests remarks

Unit tests for services runs on real FTP, SFTP and WebDAV services, not on any emulations. Before run go test command it should be set 3 environment variables:

  1. JOINT_FTP with address of FTP-service and credentials. As in pattern set JOINT_FTP=ftp://user:[email protected]:21
  2. JOINT_SFTP with address of SFTP-service and credentials. As in pattern set JOINT_SFTP=sftp://user:[email protected]:22
  3. JOINT_DAV with URL of WebDAV-service and credentials. As in pattern set JOINT_DAV=https://user:[email protected]/webdav/

If some environment variables not set or empty, those tests will be skipped.

Then copy testdata folder with ISO-file to the services root folder as is.


(c) schwarzlichtbezirk, 2023-2024.

joint's People

Contributors

schwarzlichtbezirk avatar

Watchers

 avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.