jx/internal/transport/transport.go

241 lines
4.7 KiB
Go
Raw Normal View History

2024-05-12 08:20:51 +00:00
// Copyright 2024 Matthew Rich <matthewrich.conf@gmail.com>. All rights reserved.
package transport
import (
"errors"
2024-07-01 07:16:55 +00:00
_ "fmt"
2024-05-12 08:20:51 +00:00
"net/url"
"net/http"
2024-05-12 08:20:51 +00:00
_ "strings"
2024-07-01 07:16:55 +00:00
_ "path/filepath"
2024-05-12 08:20:51 +00:00
"io"
"io/fs"
2024-07-01 07:16:55 +00:00
_ "os"
"context"
2024-05-12 08:20:51 +00:00
)
var (
ErrTransportResourceAbsent error = errors.New("Transport resource is absent")
)
2024-07-01 07:16:55 +00:00
type Handler interface {
URI() *url.URL
ContentType() string
SetGzip(bool)
DetectGzip()
2024-07-01 07:16:55 +00:00
Gzip() bool
Signature() string
Stat() (fs.FileInfo, error)
}
type HandlerReader interface {
2024-07-01 07:16:55 +00:00
Reader() io.ReadCloser
}
type HandlerWriter interface {
2024-07-01 07:16:55 +00:00
Writer() io.WriteCloser
}
2024-05-12 08:20:51 +00:00
type Reader struct {
uri *url.URL
2024-07-01 07:16:55 +00:00
handle Handler
2024-05-12 08:20:51 +00:00
stream io.ReadCloser
2024-07-17 08:19:55 +00:00
exists func() bool
2024-05-12 08:20:51 +00:00
}
2024-07-01 07:16:55 +00:00
func NewReader(u *url.URL) (reader *Reader, e error) {
return NewReaderWithContext(u, context.Background())
}
func NewReaderWithContext(u *url.URL, ctx context.Context) (reader *Reader, e error) {
2024-07-01 07:16:55 +00:00
reader = &Reader{ uri: u }
2024-05-12 08:20:51 +00:00
switch u.Scheme {
case "http", "https":
reader.handle, e = NewHTTPReader(u, ctx)
2024-05-12 08:20:51 +00:00
case "file":
fallthrough
default:
reader.handle, e = NewFileReader(u)
2024-07-17 08:19:55 +00:00
reader.exists = func() bool { return FileExists(u) }
2024-05-12 08:20:51 +00:00
}
reader.SetStream(reader.handle.(HandlerReader).Reader())
2024-07-01 07:16:55 +00:00
return
2024-05-12 08:20:51 +00:00
}
func NewReaderURI(uri string) (reader *Reader, e error) {
var u *url.URL
if u, e = url.Parse(uri); e == nil {
return NewReader(u)
}
return
}
2024-05-12 08:20:51 +00:00
type Writer struct {
2024-07-01 07:16:55 +00:00
uri *url.URL
handle Handler
stream io.WriteCloser
2024-07-17 08:19:55 +00:00
exists func() bool
2024-05-12 08:20:51 +00:00
}
2024-07-01 07:16:55 +00:00
func NewWriter(u *url.URL) (writer *Writer, e error) {
return NewWriterWithContext(u, context.Background())
}
func NewWriterWithContext(u *url.URL, ctx context.Context) (writer *Writer, e error) {
2024-07-01 07:16:55 +00:00
writer = &Writer{ uri: u }
2024-07-01 07:16:55 +00:00
switch u.Scheme {
case "http", "https":
writer.handle, e = NewHTTPWriter(u, ctx)
2024-07-01 07:16:55 +00:00
case "file":
fallthrough
default:
writer.handle, e = NewFileWriter(u)
2024-07-17 08:19:55 +00:00
writer.exists = func() bool { return FileExists(u) }
2024-07-01 07:16:55 +00:00
}
writer.SetStream(writer.handle.(HandlerWriter).Writer())
2024-07-01 07:16:55 +00:00
return writer, e
2024-05-12 08:20:51 +00:00
}
func NewWriterURI(uri string) (writer *Writer, e error) {
var u *url.URL
if u, e = url.Parse(uri); e == nil {
return NewWriter(u)
}
return
}
2024-07-17 08:19:55 +00:00
func ExistsURI(uri string) bool {
if u, e := url.Parse(uri); e == nil {
return Exists(u)
}
return false
2024-07-17 08:19:55 +00:00
}
func Exists(u *url.URL) bool {
switch u.Scheme {
case "http", "https":
return HTTPExists(u)
case "file":
fallthrough
default:
return FileExists(u)
}
}
func (r *Reader) Exists() bool { return r.exists() }
2024-05-12 08:20:51 +00:00
func (r *Reader) Read(b []byte) (int, error) {
return r.stream.Read(b)
}
func (r *Reader) Close() error {
return r.stream.Close()
}
2024-07-01 07:16:55 +00:00
func (r *Reader) ContentType() string {
return r.handle.ContentType()
}
func (r *Reader) SetGzip(value bool) {
r.handle.SetGzip(value)
}
func (r *Reader) DetectGzip() { r.handle.DetectGzip() }
2024-07-01 07:16:55 +00:00
func (r *Reader) Gzip() bool {
return r.handle.Gzip()
}
func (r *Reader) Stat() (info fs.FileInfo, err error) {
return r.handle.Stat()
}
2024-05-12 08:20:51 +00:00
func (r *Reader) Signature() string {
2024-07-01 07:16:55 +00:00
return r.handle.Signature()
}
2024-07-17 08:19:55 +00:00
func (r *Reader) SetStream(s io.ReadCloser) {
r.stream = s
}
func (r *Reader) AddHeader(name string, value string) {
r.handle.(*HTTPReader).GetRequest().Header.Add(name, value)
}
func (r *Reader) Status() string {
if httpReader, ok := r.handle.(*HTTPReader); ok {
return httpReader.GetResponse().Status
}
panic("Unable to get HTTP status from reader")
}
func (r *Reader) StatusCode() int {
if httpReader, ok := r.handle.(*HTTPReader); ok {
return httpReader.GetResponse().StatusCode
}
panic("Unable to get HTTP status code from reader")
}
func (r *Reader) Response() *http.Response {
return r.handle.(*HTTPReader).GetResponse()
}
2024-07-01 07:16:55 +00:00
2024-07-17 08:19:55 +00:00
func (w *Writer) Exists() bool { return w.exists() }
2024-07-01 07:16:55 +00:00
func (w *Writer) Write(b []byte) (int, error) {
return w.stream.Write(b)
}
func (w *Writer) ReadFrom(r io.Reader) (n int64, e error) {
if v, ok := w.stream.(io.ReaderFrom); ok {
return v.ReadFrom(r)
} else {
panic("io.ReaderFrom interface not supported by writer")
}
}
2024-07-01 07:16:55 +00:00
func (w *Writer) Close() error {
return w.stream.Close()
}
func (w *Writer) ContentType() string {
return w.handle.ContentType()
}
func (w *Writer) SetGzip(value bool) {
w.handle.SetGzip(value)
}
func (w *Writer) DetectGzip() { w.handle.DetectGzip() }
2024-07-01 07:16:55 +00:00
func (w *Writer) Gzip() bool {
return w.handle.Gzip()
}
func (w *Writer) Signature() string {
return w.handle.Signature()
2024-05-12 08:20:51 +00:00
}
2024-07-17 08:19:55 +00:00
func (w *Writer) SetStream(s io.WriteCloser) {
w.stream = s
}
func (w *Writer) AddHeader(name string, value string) {
w.handle.(*HTTPWriter).PostRequest().Header.Add(name, value)
}
func (w *Writer) Status() string {
return w.handle.(*HTTPWriter).PostResponse().Status
}
func (w *Writer) StatusCode() int {
return w.handle.(*HTTPWriter).PostResponse().StatusCode
}
func (w *Writer) Response() *http.Response {
return w.handle.(*HTTPWriter).PostResponse()
}