// Copyright 2024 Matthew Rich . 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 }