jx/internal/transport/http.go

129 lines
2.6 KiB
Go

// Copyright 2024 Matthew Rich <matthewrich.conf@gmail.com>. All rights reserved.
package transport
import (
_ "errors"
"io"
_ "os"
"net/url"
"net/http"
"fmt"
"context"
"path/filepath"
"io/fs"
"decl/internal/identifier"
"strconv"
)
type HTTP struct {
uri *url.URL
path string
gzip bool
exttype string
fileext string
ctx context.Context
get *HTTPConnection
Client *http.Client
}
func HTTPExists(u *url.URL) bool {
resp, err := http.Head(u.String())
if err == nil && resp.StatusCode == 200 {
return true
}
return false
}
func NewHTTP(u *url.URL, ctx context.Context) (h *HTTP, err error) {
h = &HTTP {
ctx: ctx,
uri: u,
path: filepath.Join(u.Hostname(), u.RequestURI()),
Client: http.DefaultClient,
}
h.extension()
h.DetectGzip()
return
}
func (h *HTTP) extension() {
id := identifier.ID(h.path)
h.exttype, h.fileext = id.Extension()
}
func (h *HTTP) DetectGzip() {
h.gzip = (h.uri.Query().Get("gzip") == "true" || h.fileext == "gz")
}
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")
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) {
uri := h.uri.String()
var response *http.Response
if response, err = http.Head(uri); err != nil {
return
}
defer response.Body.Close()
if response.StatusCode > 399 {
err = ErrTransportResourceAbsent
return
}
fi := NewHTTPFileInfo(uri)
contentLength := response.Header.Get("Content-Length")
if contentLength != "" {
if fi.ContentLength, err = strconv.ParseInt(contentLength, 10, 64); err != nil {
return
}
}
if response.Header.Get("Last-Modified") != "" {
fi.LastModified, _ = http.ParseTime(response.Header.Get("Last-Modified"))
}
fi.ContentType = response.Header.Get("Content-Type")
return fi, err
}
func (h *HTTP) ContentType() (contenttype string) {
contenttype = h.get.Response().Header.Get("Content-Type")
switch contenttype {
case "application/octet-stream":
return h.exttype
default:
}
return
}
func (h *HTTP) SetGzip(gzip bool) {
h.gzip = gzip
}
func (h *HTTP) Gzip() bool {
return h.gzip
}