jx/internal/transport/http.go

244 lines
4.7 KiB
Go
Raw Normal View History

2024-07-01 07:16:55 +00:00
// Copyright 2024 Matthew Rich <matthewrich.conf@gmail.com>. All rights reserved.
package transport
import (
_ "errors"
"io"
_ "os"
"net/url"
"net/http"
"strings"
"fmt"
"context"
"path/filepath"
"log/slog"
"io/fs"
2024-07-01 07:16:55 +00:00
)
type Pipe struct {
Reader io.ReadCloser
Writer io.WriteCloser
}
type HTTPConnection struct {
stream *Pipe
request *http.Request
response *http.Response
Client *http.Client
2024-07-01 07:16:55 +00:00
}
type HTTP struct {
uri *url.URL
path string
gzip bool
2024-07-01 07:16:55 +00:00
exttype string
fileext string
ctx context.Context
get *HTTPConnection
post *HTTPConnection
2024-07-01 07:16:55 +00:00
Client *http.Client
}
2024-07-17 08:19:55 +00:00
func HTTPExists(u *url.URL) bool {
return false
}
func NewPipe() *Pipe {
r,w := io.Pipe()
return &Pipe{ Reader: r, Writer: w }
}
func NewHTTPConnection(client *http.Client) *HTTPConnection {
return &HTTPConnection {
Client: client,
2024-07-01 07:16:55 +00:00
}
}
func (h *HTTPConnection) NewPostRequest(ctx context.Context, uri string) (err error) {
h.stream = NewPipe()
h.request, err = http.NewRequestWithContext(ctx, "POST", uri, h.Reader())
return
}
func (h *HTTPConnection) NewGetRequest(ctx context.Context, uri string) (err error) {
h.request, err = http.NewRequestWithContext(ctx, "GET", uri, nil)
return
}
func (h *HTTPConnection) Request() *http.Request {
return h.request
}
func (h *HTTPConnection) Response() *http.Response {
return h.response
}
func (h *HTTPConnection) Writer() io.WriteCloser {
return h.stream.Writer
}
func (h *HTTPConnection) Reader() io.ReadCloser {
return h.stream.Reader
}
func (h *HTTPConnection) Do() (err error) {
slog.Info("transport.HTTPConnection.Do()", "connection", h)
h.response, err = h.Client.Do(h.request)
return
}
func (h *HTTPConnection) Read(p []byte) (n int, err error) {
if h.response == nil {
if err = h.Do(); err != nil {
return
}
}
return h.response.Body.Read(p)
}
func (h *HTTPConnection) Write(p []byte) (n int, err error) {
if h.response == nil {
if err = h.Do(); err != nil {
return
}
}
slog.Info("transport.HTTPConnection.Write()", "data", p, "connection", h)
return h.Writer().Write(p)
}
func (h *HTTPConnection) ReadFrom(r io.Reader) (n int64, err error) {
h.request.Body = r.(io.ReadCloser)
if h.response == nil {
if err = h.Do(); err != nil {
return
}
}
return h.request.ContentLength, nil
}
func (h *HTTPConnection) Close() (err error) {
if h.response != nil {
defer h.response.Body.Close()
}
if h.stream != nil {
err = h.Writer().Close()
}
return
2024-07-01 07:16:55 +00:00
}
func NewHTTP(u *url.URL, ctx context.Context) (h *HTTP, err error) {
h = &HTTP {
ctx: ctx,
2024-07-01 07:16:55 +00:00
uri: u,
path: filepath.Join(u.Hostname(), u.RequestURI()),
Client: http.DefaultClient,
}
h.extension()
h.DetectGzip()
2024-07-01 07:16:55 +00:00
return
}
func (h *HTTP) extension() {
elements := strings.Split(h.path, ".")
numberOfElements := len(elements)
if numberOfElements > 2 {
h.exttype = elements[numberOfElements - 2]
h.fileext = elements[numberOfElements - 1]
}
h.exttype = elements[numberOfElements - 1]
}
func (h *HTTP) DetectGzip() {
h.gzip = (h.uri.Query().Get("gzip") == "true" || h.fileext == "gz")
}
2024-07-01 07:16:55 +00:00
func (h *HTTP) URI() *url.URL {
return h.uri
}
func (h *HTTP) Path() string {
return h.path
}
func (h *HTTP) Signature() (documentSignature string) {
if h.get.Response() != nil {
documentSignature = h.get.Response().Header.Get("Signature")
2024-07-01 07:16:55 +00:00
if documentSignature == "" {
signatureResp, signatureErr := h.Client.Get(fmt.Sprintf("%s.sig", h.uri.String()))
if signatureErr == nil {
defer signatureResp.Body.Close()
readSignatureBody, readSignatureErr := io.ReadAll(signatureResp.Body)
if readSignatureErr == nil {
documentSignature = string(readSignatureBody)
}
}
}
}
return documentSignature
}
func (h *HTTP) Stat() (info fs.FileInfo, err error) {
return
}
2024-07-01 07:16:55 +00:00
func (h *HTTP) ContentType() (contenttype string) {
contenttype = h.get.Response().Header.Get("Content-Type")
2024-07-01 07:16:55 +00:00
switch contenttype {
case "application/octet-stream":
return h.exttype
default:
}
return
}
func (h *HTTP) SetGzip(gzip bool) {
h.gzip = gzip
}
2024-07-01 07:16:55 +00:00
func (h *HTTP) Gzip() bool {
return h.gzip
2024-07-01 07:16:55 +00:00
}
func (h *HTTP) Reader() io.ReadCloser {
if h.get == nil {
h.get = NewHTTPConnection(h.Client)
if err := h.get.NewGetRequest(h.ctx, h.uri.String()); err != nil {
panic(err)
}
2024-07-01 07:16:55 +00:00
}
return h.get
2024-07-01 07:16:55 +00:00
}
func (h *HTTP) Writer() io.WriteCloser {
if h.post == nil {
h.post = NewHTTPConnection(h.Client)
if err := h.post.NewPostRequest(h.ctx, h.uri.String()); err != nil {
panic(err)
}
2024-07-01 07:16:55 +00:00
}
return h.post
}
func (h *HTTP) ReadWriter() io.ReadWriteCloser {
return nil
}
func (h *HTTP) GetRequest() *http.Request {
return h.get.Request()
}
func (h *HTTP) GetResponse() *http.Response {
return h.get.Response()
}
func (h *HTTP) PostRequest() *http.Request {
return h.post.Request()
}
func (h *HTTP) PostResponse() *http.Response {
return h.post.Response()
2024-07-01 07:16:55 +00:00
}