mirror of
https://github.com/DeBrosOfficial/network.git
synced 2026-01-30 03:43:04 +00:00
did some fixes
This commit is contained in:
parent
c2071586f8
commit
0a7e3ba3c7
@ -32,6 +32,11 @@ func TestDomainRouting_BasicRouting(t *testing.T) {
|
||||
// Wait for deployment to be active
|
||||
time.Sleep(2 * time.Second)
|
||||
|
||||
// Get deployment details for debugging
|
||||
deployment := GetDeployment(t, env, deploymentID)
|
||||
t.Logf("Deployment created: ID=%s, CID=%s, Name=%s, Status=%s",
|
||||
deploymentID, deployment["content_cid"], deployment["name"], deployment["status"])
|
||||
|
||||
t.Run("Standard domain resolves", func(t *testing.T) {
|
||||
// Domain format: {deploymentName}.orama.network
|
||||
domain := fmt.Sprintf("%s.orama.network", deploymentName)
|
||||
|
||||
@ -1,11 +1,14 @@
|
||||
package deployments
|
||||
|
||||
import (
|
||||
"archive/tar"
|
||||
"compress/gzip"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"time"
|
||||
@ -88,8 +91,23 @@ func (h *StaticDeploymentHandler) HandleUpload(w http.ResponseWriter, r *http.Re
|
||||
zap.Int64("size", header.Size),
|
||||
)
|
||||
|
||||
// Upload to IPFS
|
||||
addResp, err := h.ipfsClient.Add(ctx, file, header.Filename)
|
||||
// Extract tarball to temporary directory
|
||||
tmpDir, err := os.MkdirTemp("", "static-deploy-*")
|
||||
if err != nil {
|
||||
h.logger.Error("Failed to create temp directory", zap.Error(err))
|
||||
http.Error(w, "Failed to process tarball", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
defer os.RemoveAll(tmpDir)
|
||||
|
||||
if err := extractTarball(file, tmpDir); err != nil {
|
||||
h.logger.Error("Failed to extract tarball", zap.Error(err))
|
||||
http.Error(w, "Failed to extract tarball", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
// Upload extracted directory to IPFS
|
||||
addResp, err := h.ipfsClient.AddDirectory(ctx, tmpDir)
|
||||
if err != nil {
|
||||
h.logger.Error("Failed to upload to IPFS", zap.Error(err))
|
||||
http.Error(w, "Failed to upload content", http.StatusInternalServerError)
|
||||
@ -232,3 +250,61 @@ func detectContentType(filename string) string {
|
||||
|
||||
return "application/octet-stream"
|
||||
}
|
||||
|
||||
// extractTarball extracts a .tar.gz file to the specified directory
|
||||
func extractTarball(reader io.Reader, destDir string) error {
|
||||
gzr, err := gzip.NewReader(reader)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to create gzip reader: %w", err)
|
||||
}
|
||||
defer gzr.Close()
|
||||
|
||||
tr := tar.NewReader(gzr)
|
||||
|
||||
for {
|
||||
header, err := tr.Next()
|
||||
if err == io.EOF {
|
||||
break
|
||||
}
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to read tar header: %w", err)
|
||||
}
|
||||
|
||||
// Build target path
|
||||
target := filepath.Join(destDir, header.Name)
|
||||
|
||||
// Prevent path traversal - clean both paths before comparing
|
||||
cleanDest := filepath.Clean(destDir) + string(os.PathSeparator)
|
||||
cleanTarget := filepath.Clean(target)
|
||||
if !strings.HasPrefix(cleanTarget, cleanDest) && cleanTarget != filepath.Clean(destDir) {
|
||||
return fmt.Errorf("invalid file path in tarball: %s", header.Name)
|
||||
}
|
||||
|
||||
switch header.Typeflag {
|
||||
case tar.TypeDir:
|
||||
if err := os.MkdirAll(target, 0755); err != nil {
|
||||
return fmt.Errorf("failed to create directory: %w", err)
|
||||
}
|
||||
case tar.TypeReg:
|
||||
// Create parent directory if needed
|
||||
if err := os.MkdirAll(filepath.Dir(target), 0755); err != nil {
|
||||
return fmt.Errorf("failed to create parent directory: %w", err)
|
||||
}
|
||||
|
||||
// Create file
|
||||
f, err := os.OpenFile(target, os.O_CREATE|os.O_RDWR, os.FileMode(header.Mode))
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to create file: %w", err)
|
||||
}
|
||||
|
||||
if _, err := io.Copy(f, tr); err != nil {
|
||||
f.Close()
|
||||
return fmt.Errorf("failed to write file: %w", err)
|
||||
}
|
||||
f.Close()
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
@ -10,6 +10,8 @@ import (
|
||||
"mime/multipart"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
@ -19,6 +21,7 @@ import (
|
||||
// IPFSClient defines the interface for IPFS operations
|
||||
type IPFSClient interface {
|
||||
Add(ctx context.Context, reader io.Reader, name string) (*AddResponse, error)
|
||||
AddDirectory(ctx context.Context, dirPath string) (*AddResponse, error)
|
||||
Pin(ctx context.Context, cid string, name string, replicationFactor int) (*PinResponse, error)
|
||||
PinStatus(ctx context.Context, cid string) (*PinStatus, error)
|
||||
Get(ctx context.Context, cid string, ipfsAPIURL string) (io.ReadCloser, error)
|
||||
@ -236,6 +239,104 @@ func (c *Client) Add(ctx context.Context, reader io.Reader, name string) (*AddRe
|
||||
return &last, nil
|
||||
}
|
||||
|
||||
// AddDirectory adds all files in a directory to IPFS and returns the root directory CID
|
||||
func (c *Client) AddDirectory(ctx context.Context, dirPath string) (*AddResponse, error) {
|
||||
var buf bytes.Buffer
|
||||
writer := multipart.NewWriter(&buf)
|
||||
|
||||
// Walk directory and add all files to multipart request
|
||||
var totalSize int64
|
||||
err := filepath.Walk(dirPath, func(path string, info os.FileInfo, err error) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Skip directories
|
||||
if info.IsDir() {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Get relative path
|
||||
relPath, err := filepath.Rel(dirPath, path)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to get relative path: %w", err)
|
||||
}
|
||||
|
||||
// Read file
|
||||
data, err := os.ReadFile(path)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to read file %s: %w", path, err)
|
||||
}
|
||||
|
||||
totalSize += int64(len(data))
|
||||
|
||||
// Add file to multipart
|
||||
part, err := writer.CreateFormFile("file", relPath)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to create form file: %w", err)
|
||||
}
|
||||
|
||||
if _, err := part.Write(data); err != nil {
|
||||
return fmt.Errorf("failed to write file data: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := writer.Close(); err != nil {
|
||||
return nil, fmt.Errorf("failed to close writer: %w", err)
|
||||
}
|
||||
|
||||
// Add with wrap-in-directory to create a root directory node
|
||||
apiURL := c.apiURL + "/add?wrap-in-directory=true"
|
||||
|
||||
req, err := http.NewRequestWithContext(ctx, "POST", apiURL, &buf)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to create add request: %w", err)
|
||||
}
|
||||
|
||||
req.Header.Set("Content-Type", writer.FormDataContentType())
|
||||
|
||||
resp, err := c.httpClient.Do(req)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("add request failed: %w", err)
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
body, _ := io.ReadAll(resp.Body)
|
||||
return nil, fmt.Errorf("add failed with status %d: %s", resp.StatusCode, string(body))
|
||||
}
|
||||
|
||||
// Read NDJSON responses - the last one will be the root directory
|
||||
dec := json.NewDecoder(resp.Body)
|
||||
var last AddResponse
|
||||
|
||||
for {
|
||||
var chunk AddResponse
|
||||
if err := dec.Decode(&chunk); err != nil {
|
||||
if errors.Is(err, io.EOF) {
|
||||
break
|
||||
}
|
||||
return nil, fmt.Errorf("failed to decode add response: %w", err)
|
||||
}
|
||||
last = chunk
|
||||
}
|
||||
|
||||
if last.Cid == "" {
|
||||
return nil, fmt.Errorf("no CID returned from IPFS")
|
||||
}
|
||||
|
||||
return &AddResponse{
|
||||
Cid: last.Cid,
|
||||
Size: totalSize,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Pin pins a CID with specified replication factor
|
||||
// IPFS Cluster expects pin options (including name) as query parameters, not in JSON body
|
||||
func (c *Client) Pin(ctx context.Context, cid string, name string, replicationFactor int) (*PinResponse, error) {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user