reader

package module
v0.7.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jun 28, 2021 License: BSD-3-Clause Imports: 14 Imported by: 81

README

go-reader

There are many interfaces for reading files. This one is ours. It returns io.ReadSeekCloser instances.

This package supersedes the go-whosonfirst-readwrite package.

Documentation

Go Reference

Example

Readers are instantiated with the reader.NewReader method which takes as its arguments a context.Context instance and a URI string. The URI's scheme represents the type of reader it implements and the remaining (URI) properties are used by that reader type to instantiate itself.

For example to read files from a directory on the local filesystem you would write:

package main

import (
	"context"
	"github.com/whosonfirst/go-reader"
	"io"
	"os"
)

func main() {
	ctx := context.Background()
	r, _ := reader.NewReader(ctx, "fs:///usr/local/data")
	fh, _ := r.Read(ctx, "example.txt")
	defer fh.Close()
	io.Copy(os.Stdout, fh)
}

Note the use of the fs:// scheme rather than the more conventional file://. This is deliberate so as not to overlap with the Go Cloud Blob package's file handler.

There is also a handy "null" reader in case you need a "pretend" reader that doesn't actually do anything:

package main

import (
	"context"
	"github.com/whosonfirst/go-reader"
	"io"
	"os"
)

func main() {
	ctx := context.Background()
	r, _ := reader.NewReader(ctx, "null://")
	fh, _ := r.Read(ctx, "example.txt")
	defer fh.Close()
	io.Copy(os.Stdout, fh)
}

Interfaces

reader.Reader
type Reader interface {
	Read(context.Context, string) (io.ReadSeekCloser, error)
	ReaderURI(context.Context, string) string
}

Custom readers

Custom readers need to:

  1. Implement the interface above.
  2. Announce their availability using the go-reader.RegisterReader method on initialization, passing in an initialization function implementing the go-reader.ReaderInitializationFunc interface.

For example, this is how the go-reader-http reader is implemented:

package reader

import (
	"context"
	"errors"
	wof_reader "github.com/whosonfirst/go-reader"
	"github.com/whosonfirst/go-ioutil"
	"io"
	_ "log"
	"net/http"
	"net/url"
	"path/filepath"
	"time"
)

type HTTPReader struct {
	wof_reader.Reader
	url      *url.URL
	throttle <-chan time.Time
}

func init() {

	ctx := context.Background()

	schemes := []string{
		"http",
		"https",
	}

	for _, s := range schemes {

		err := wof_reader.RegisterReader(ctx, s, NewHTTPReader)

		if err != nil {
			panic(err)
		}
	}
}

func NewHTTPReader(ctx context.Context, uri string) (wof_reader.Reader, error) {

	u, err := url.Parse(uri)

	if err != nil {
		return nil, err
	}

	rate := time.Second / 3
	throttle := time.Tick(rate)

	r := HTTPReader{
		throttle: throttle,
		url:      u,
	}

	return &r, nil
}

func (r *HTTPReader) Read(ctx context.Context, uri string) (io.ReadSeekCloser, error) {

	<-r.throttle

	u, _ := url.Parse(r.url.String())
	u.Path = filepath.Join(u.Path, uri)

	url := u.String()

	rsp, err := http.Get(url)

	if err != nil {
		return nil, err
	}

	if rsp.StatusCode != 200 {
		return nil, errors.New(rsp.Status)
	}

	fh, err := ioutil.NewReadSeekCloser(rsp.Body)

	if err != nil {
		return nil, err
	}

	return fh, nil
}

func (r *HTTPReader) ReaderURI(ctx context.Context, uri string) string {
	return uri
}

And then to use it you would do this:

package main

import (
	"context"
	"github.com/whosonfirst/go-reader"
	_ "github.com/whosonfirst/go-reader-http"	
	"io"
	"os"
)

func main() {
	ctx := context.Background()
	r, _ := reader.NewReader(ctx, "https://data.whosonfirst.org")
	fh, _ := r.Read(ctx, "101/736/545/101736545.geojson")
	defer fh.Close()
	io.Copy(os.Stdout, fh)
}

Available readers

"blob"

Read files from any registered Go Cloud Blob source. For example:

import (
	"context"
	"github.com/whosonfirst/go-reader"
	_ "github.com/whosonfirst/go-reader-blob"
	_ "gocloud.dev/blob/s3blob"	
)

func main() {
	ctx := context.Background()
	r, _ := reader.NewReader(ctx, "s3://whosonfirst-data?region=us-west-1")
}
github://

Read files from a GitHub repository.

import (
	"context"
	"github.com/whosonfirst/go-reader"
	_ "github.com/whosonfirst/go-reader-github"
)

func main() {
	ctx := context.Background()
	r, _ := reader.NewReader(ctx, "github://{GITHUB_OWNER}/{GITHUB_REPO}")

	// to specify a specific branch you would do this:
	// r, _ := reader.NewReader(ctx, "github://{GITHUB_OWNER}/{GITHUB_REPO}/{GITHUB_BRANCH}")
}
githubapi://

Read files from a GitHub repository using the GitHub API.

import (
	"context"
	"github.com/whosonfirst/go-reader"
	_ "github.com/whosonfirst/go-reader-github"
)

func main() {
	ctx := context.Background()
	r, _ := reader.NewReader(ctx, "githubapi://{GITHUB_OWNER}/{GITHUB_REPO}?access_token={GITHUBAPI_ACCESS_TOKEN}")

	// to specify a specific branch you would do this:
	// r, _ := reader.NewReader(ctx, "githubapi://{GITHUB_OWNER}/{GITHUB_REPO}/{GITHUB_BRANCH}?access_token={GITHUBAPI_ACCESS_TOKEN}")
}
http:// and https://

Read files from an HTTP(S) endpoint.

import (
	"context"
	"github.com/whosonfirst/go-reader"
	_ "github.com/whosonfirst/go-reader-http"
)

func main() {
	ctx := context.Background()
	r, _ := reader.NewReader(ctx, "https://{HTTP_HOST_AND_PATH}")
}
file://

Read files from a local filesystem.

import (
	"context"
	"github.com/whosonfirst/go-reader"
)

func main() {
	ctx := context.Background()
	r, _ := reader.NewReader(ctx, "file://{PATH_TO_DIRECTORY}")
}
null://

Pretend to read files.

import (
	"context"
	"github.com/whosonfirst/go-reader"
)

func main() {
	ctx := context.Background()
	r, _ := reader.NewReader(ctx, "null://")
}

Documentation

Overview

Example:

package main

import (
 	"context"
	"github.com/whosonfirst/go-reader"
	"io"
 	"os"
)

 func main() {
 	ctx := context.Background()
 	r, _ := reader.NewReader(ctx, "fs:///usr/local/data")
 	fh, _ := r.Read(ctx, "example.txt")
 	defer fh.Close()
 	io.Copy(os.Stdout, fh)
 }

Package reader provides a common interface for reading from a variety of sources. It has the following interface:

type Reader interface {
	Read(context.Context, string) (io.ReadSeekCloser, error)
	ReaderURI(string) string
}

Reader intstances are created either by calling a package-specific New{SOME_READER}Reader method or by invoking the reader.NewReader method passing in a context.Context instance and a URI specific to the reader class. For example:

r, _ := reader.NewReader(ctx, "fs:///usr/local/data")

Custom reader packages implement the reader.Reader interface and register their availability by calling the reader.RegisterRegister method on initialization. For example:

func init() {

	ctx := context.Background()

	err = RegisterReader(ctx, "file", NewFileReader)

 	if err != nil {
		panic(err)
	}
}

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func Readers

func Readers() []string

func RegisterReader added in v0.1.1

func RegisterReader(ctx context.Context, scheme string, init_func ReaderInitializationFunc) error

func Schemes added in v0.4.1

func Schemes() []string

Types

type FileReader

type FileReader struct {
	Reader
	// contains filtered or unexported fields
}

func (*FileReader) Read

func (r *FileReader) Read(ctx context.Context, path string) (io.ReadSeekCloser, error)

func (*FileReader) ReaderURI added in v0.3.0

func (r *FileReader) ReaderURI(ctx context.Context, path string) string

type MultiReader added in v0.2.1

type MultiReader struct {
	Reader
	// contains filtered or unexported fields
}

func (*MultiReader) Read added in v0.2.1

func (mr *MultiReader) Read(ctx context.Context, uri string) (io.ReadSeekCloser, error)

func (*MultiReader) ReaderURI added in v0.3.0

func (mr *MultiReader) ReaderURI(ctx context.Context, uri string) string

type NullReader

type NullReader struct {
	Reader
}

func (*NullReader) Read

func (r *NullReader) Read(ctx context.Context, uri string) (io.ReadSeekCloser, error)

func (*NullReader) ReaderURI added in v0.3.0

func (r *NullReader) ReaderURI(ctx context.Context, uri string) string

type Reader

type Reader interface {
	Read(context.Context, string) (io.ReadSeekCloser, error)
	ReaderURI(context.Context, string) string
}

func NewFileReader

func NewFileReader(ctx context.Context, uri string) (Reader, error)

func NewMultiReader added in v0.2.1

func NewMultiReader(ctx context.Context, readers ...Reader) (Reader, error)

func NewMultiReaderFromURIs added in v0.2.1

func NewMultiReaderFromURIs(ctx context.Context, uris ...string) (Reader, error)

func NewNullReader

func NewNullReader(ctx context.Context, uri string) (Reader, error)

func NewReader

func NewReader(ctx context.Context, uri string) (Reader, error)

type ReaderInitializationFunc added in v0.1.1

type ReaderInitializationFunc func(ctx context.Context, uri string) (Reader, error)

Directories

Path Synopsis
cmd
wof-reader command

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL